2014-06-17 164 views
10

我無法工作了我如何定義這兩個自定義指令中使用NG-型號:角指令:分離範圍

  1. 用途隔離範圍,並
  2. 採用NG-模型指令在其模板中的新範圍內。

下面是一個例子:

HTML:

<body ng-app="app"> 
    <div ng-controller="ctrl"> 
    <dir model="foo.bar"></dir> 
    Outside directive: {{foo.bar}} 
    </div> 
</body> 

JS:

var app = angular.module('app',[]) 
    .controller('ctrl', function($scope){ 
    $scope.foo = { bar: 'baz' }; 
    }) 
    .directive('dir', function(){ 
    return { 
     restrict: 'E', 
     scope: { 
     model: '=' 
     }, 
     template: '<div ng-if="true"><input type="text" ng-model="model" /><br/></div>' 
    } 
    }); 

這裏的期望的行爲是,輸入的值綁定到所述外部範圍的foo.bar屬性,通過指令的(隔離)範圍model屬性。這不會發生,因爲模板的封閉div上的ng-if指令會創建一個新的作用域,所以這個作用域的model被更新,而不是指令的作用域。 通常你通過確保表達式中有一個點來解決這些ng模型問題,但是我看不出有什麼辦法可以做到這一點。我想,如果我也許能夠使用這樣的事情對我的指令:

{ 
    restrict: 'E', 
    scope: { 
    model: { 
     value: '=model' 
    } 
    }, 
    template: '<div ng-if="true"><input type="text" ng-model="model.value" /><br/></div>' 
} 

但是,這並不工作...

Plunker

回答

9

你說得對 - ng-if在輸入文本字段中輸入文本時會創建一個導致問題的子範圍。它在子作用域中創建一個名爲'model'的陰影屬性,它是具有相同名稱的父作用域變量的副本 - 有效地打破了雙向模型綁定。

對此的修復很簡單。在模板中,指定$父前綴:

template: '<div ng-if="true"> 
        <input type="text" ng-model="$parent.model" /><br/> 
      </div>' 

這保證了它能夠解決從$父範圍「模式」,你已經設置已經爲雙向模式通過隔離範圍結合。

最後,'。'在ng模型中保存一天。我認爲有必要考慮點的剩餘部分,以便Angular通過範圍繼承來解決屬性問題。如果沒有點,解析屬性只會成爲我們分配範圍變量時的問題(否則,查找很好,包括只讀{{model}}綁定表達式)。

+1

謝謝 - 我完全忘了$父母。在這種情況下,這確實解決了我的問題,但我仍然對它是一個通用解決方案猶豫不決:這意味着我必須跟蹤我的模板中引入新範圍的位置以及我需要的層次結構級別目標,這似乎很容易出錯... – Duncan

+0

我同意你的看法。米斯科解釋說,有人每週會記錄一次有關此問題的錯誤 - 它並不是一個真正的錯誤,它是原型繼承的工作方式。要正確設置模型,您需要知道範圍繼承如何在更深層次上工作,以及哪些指令將創建子範圍。我想不出更好的辦法。 – pixelbits

+0

是的,公平點,但我想我得到的是,有一個使用ng-model =「$ parent.bar」而不是ng-model =「foo.bar」的特定問題,因爲前者我總是不得不考慮子範圍在哪裏創建,而後者我不知道(只要我認爲沒有子範圍有一個名爲'foo'的屬性)。 – Duncan

0

ng-if創建一個額外的prototypally繼承範圍,所以ng-model="model"綁定到新範圍的繼承屬性,而不綁定到指令範圍的雙向綁定屬性。

更改爲ng-show,它將work

您可以使用我寫過的a small Firebug extension檢查角度範圍。

+0

是的,我知道這就是發生了什麼 - 我用ng - 如果只是爲了演示問題 – Duncan