2014-03-24 182 views
0

我想爲點擊編輯輸入字段生成指令。由於我需要處理各種不同類型的輸入字段,因此我希望將其設置爲只是跨輸入字段本身的屬性類型指令。角度transclude和範圍

但是,問題是當使用範圍參數指向描述(對於ipDisable)時,事情停止工作,因爲他們應該(嘗試在jsFiddle js部分第44行中註釋)。據推測,這是一個範圍錯誤,但我真的不知道從哪裏開始調試它,任何幫助,將不勝感激。

的jsfiddle: http://jsfiddle.net/HbYwX/3/

HTML:

<input inplace type="string" ip-disable=false name="username" ng-model="uname"> 

JS:

myApp.directive('inplace', function($compile) { 

var compile = function(tElem,tAttrib,transclude) { 

    var whole = $('<div ng-scope></div>'); 

    var editable = $('<div class="editable-transclude" ng-hide="static">'+ 
        '<a ng-click="changeStatic()" ng-show="!static && !disable()">'+ 
        '&ltsave&gt</a></div>'); 

    whole.append(editable).append('<span class="disabledText" ng-show="static">{{ngModel.$viewValue}}</span>' + 
      '<a ng-click="changeStatic()" ng-show="static && !disable()">'+ 
      '&ltedit&gt</a>'); 

    tElem.replaceWith(whole); 

    transclude(tElem,function(clone) { 
    clone.removeAttr('inplace'); 
    editable.prepend(clone); 
    }); 

    return function(scope, element, attrs) { 

    var input_element = $($(element).find('input')[0]); 
    scope.name = input_element.name; 
    scope.ngModel = element.controller('ngModel'); 

    scope.static = true; 

    scope.changeStatic = function() { 
     if (scope.static) { 
     scope.static = false; 
     } else if (!scope.ngModel.$error[scope.name]){ 
     scope.static = true; 
     } 
    }; 
    }; 
}; 

return { 
    transclude: 'element', 
    scope: { disable: '&ipDisable' }, 
    restrict: 'A', 
    compile: compile 
}; 
}); 

回答

1

埃德的建議解決方案解決了一部分問題。然而,還有一個可能讓我擺脫了第一位:

模板被編譯到父範圍內,而不是被附加到新的指令範圍。爲了解決這個問題,我需要在鏈接器函數中手動編譯創建的模板,我可以將它綁定到適當的範圍。

工作的解決方案是: http://jsfiddle.net/HbYwX/5/

myApp.directive('inplace', function($compile) { 

var compile = function(tElem,tAttrib,transclude) { 

    var whole = $('<div ng-scope></div>'); 

    var editable = $('<div class="editable-transclude" ng-hide="static">'+ 
        '<a ng-click="changeStatic()" ng-show="!static && ipDisable()">'+ 
        '&ltsave&gt</a></div>'); 

    transclude(tElem,function(clone) { 
    clone.removeAttr('inplace'); 
    clone.attr('ng-model','model'); 
    editable.prepend(clone); 
    }); 

    whole.append(editable).append('<span class="disabledText" ng-show="static">{{model}}</span>' + 
      '<a ng-click="changeStatic()" ng-show="static && !ipDisable()">'+ 
      '&ltedit&gt</a>'); 


    return function(scope, element, attrs) { 

    element.replaceWith($compile(whole)(scope)); 

    scope.name = attrs.name; 

    scope.static = true; 

    scope.changeStatic = function() { 
     if (scope.static) { 
     scope.static = false; 
     } else { 
     scope.static = true; 
     if (scope.name) scope.$emit('inplace-edit',scope.name); 
     } 
    }; 
    }; 
}; 

return { 
    transclude: 'element', 
    scope: { ipDisable: '&', model: '=' }, 
    restrict: 'A', 
    compile: compile 
}; 
}); 

(這可能是任何人尋找類似的一些有用的東西,是在MIT許可即你希望做什麼用)。

1

這是因爲你移動一個具有分離範圍的元素中的input元素,所以它不能再與其外部的範圍進行交互。因此,您綁定的uname將不會與輸入到ng-model中的那個範圍相同。

您有幾個選擇 - 第一個不是創建隔離範圍 - 您仍然可以在鏈接功能中訪問ipDisableattrs

另一個(更好的)解決方案是將ngModel也添加到隔離範圍(scope: { disable: '&ipDisable', ngModel:'='})中,並在輸入發生更改時使用ngModelController自行更新輸入值。

+0

我簡單地嘗試了myown上的第一種可能性,並且無法完成它的工作(我將不得不$ $看有問題的屬性,對吧?)。 更好的解決方案聽起來相當複雜,除非我錯過了一些東西。有沒有一種簡單的方法可以將整個ng-model直接綁定到輸入字段ng-model,還是我必須手工連接所有的API調用? – velochy