2014-05-22 44 views
16

在指令中使用scope: { ... }引入了一個隔離範圍,該範圍並不從其父範圍原型繼承。但是,我一直用它出於不同的原因:宣佈HTML一種方便的方式與雙向數據綁定屬性:如何獲取指令*中的雙向數據綁定*沒有隔離範圍?

scope: { 
    attr1: '=', 
    attr2: '?=' 
} 

爲了得到一個非隔離範圍,你必須使用scope: true,它不提供宣佈這些屬性的機會。我現在發現自己需要一個非隔離範圍的指令,但是需要雙向綁定。達到此目的的最佳方式是什麼?


例子:我的使用情況是這樣的,在outer-directive的觀點:

<div ng-repeat="e in element"> 
    <inner-directive two-way-attr="e.value"></inner-directive> 
</div> 

inner-directive相同模塊outer-directive英寸它不需要用隔離範圍封裝。實際上,我需要爲其他目的使用$scope繼承,所以隔離範圍不是選項。只是使用HTML屬性來建立這種雙向通信非常方便。

+1

當您使用'scope:true'時,您可以直接訪問'scope',那麼最新的問題是什麼? _scope:true_將創建一個原型繼承父級的子作用域,以便您可以訪問在指令中父級作用域上定義的值。 – Satpal

+0

https://github.com/angular/angular.js/wiki/Understanding-Scopes – Satpal

+0

@Satpal:我意識到這一點,但對於我的目的來說,這是建立溝通的一種相當不雅的方式。事實上,你剛剛分享的鏈接說:「它被認爲是兩個控制器通過$ scope繼承共享信息的糟糕形式」。 ---我將在我的問題中添加一個用例示例。 – mhelvens

回答

13

通過pixelbits答案幫我算出這個大的時候,但作爲直接回答我原來的問題,這似乎過於複雜。看過之後,解決方案非常簡單。

採取了一項指令,像這樣的分離範圍:

scope: { model: '=myModel' }, 
link: function(scope, element, attr) { 
    //... 
} 

以下是等價的,只是範圍並不孤立:

scope: true, 
link: function(scope, element, attr) { 
    scope.model = scope.$parent.$eval(attr.myModel); 
    //... 
} 

看到這裏工作的例子:http://jsfiddle.net/mhelvens/SZ55R/1/

+11

這隻適用於模型是對象的情況。 –

+0

要使用非對象模型,您應該使用解析:attr =「{{}}」或attr =「{{'string'}}」 – LeonanCarvalho

7

Working Demo Here

,能夠同時具有非分離物的範圍和在相同指令的分離範圍。例如,如果您有兩個非獨立模板(意味着它們不應通過作用域繼承查找綁定)以及獨立模板(它們應僅在其自己的作用域中查找綁定)以及它們都在相同的指令中定義。

爲了設置兩個隔離範圍和非隔離範圍,你可以做到以下幾點:

  1. 在你的指令定義,指定scope=true
  2. 在你的鏈接功能,編譯和鏈接模板針對範圍參數。當你這樣做時,綁定會根據非隔離範圍進行評估(意味着它通過原型範圍繼承來解析綁定)。

    link: function(scope, element, attr) { 
    
        // this template should look for 'model' using scope inheritance 
        var template2 = angular.element('<div> Prototypical Scope: {{ model }}</div>'); 
    
        // add the template to the DOM 
        element.append(template2); 
    
        // compile and link the template against the prototypical scope 
        $compile(template2)(scope); 
        } 
    

    原型範圍繼承的優點是您不必將綁定顯式導入到您的指令當前範圍。只要它在當前範圍或繼承鏈上方的任何範圍(一直到根範圍)中定義,角運行時就可以解決它。

  3. 在同一鏈接功能中,使用scope.$new(true)定義一個隔離範圍。您可以通過導入模型到您的隔離範圍建立一個雙向模型的結合 - isolatedScope.model = scope.$eval(attr.model)

    link: function(scope, element, attr) { 
    
        // this template should look for 'model' in the current isolated scope only 
        var template = angular.element('<div>Isolate Scope: {{model}}</div>'); 
    
        // create an isolate scope 
        var isolatedScope = scope.$new(true); 
    
        // import the model from the parent scope into your isolated scope. This establishes the two-way binding.    
        isolatedScope.model = scope.$eval(attr.model); 
    
        // add the template to the DOM 
        element.append(template); 
    
        // compile and link the template against the isolate scope 
        $compile(template)(isolatedScope); 
    
    } 
    

    的分離範圍的優勢是存在的任何綁定(即是在範圍內。)你明確導入的那些。將此與非隔離作用域相比較 - 在​​當前作用域中不需要顯式定義綁定 - 它可以從鏈上的任何範圍繼承。

+0

謝謝!這看起來很有希望。今天晚些時候我會試一試。 – mhelvens

+0

謝謝,你的回答非常有幫助。但對我的問題的解決方案實際上似乎要簡單得多。關鍵是你使用'scope。$ eval'。說實話,我不確定代碼的其他部分是要完成的,但我想知道。 ---在這裏看到我的改編解決方案:http://jsfiddle.net/mhelvens/SZ55R/1/ – mhelvens

+0

$ eval在這裏建立不是真正的雙重綁定,但只是複製對象引用,因此它不適用於非對象值(標量,如字符串,數字,對象引用) – setec

6

我寫了這個。您可以使用這樣的:

twowaybinder.attach($scope, $attrs.isDeactivated, 'isDeactivated');

.factory('twowaybinder', function ($parse) { 
    function twoWayBind($scope, remote, local){ 
    var remoteSetter = $parse(remote).assign; 
    var localSetter = $parse(local).assign; 

    $scope.$parent.$watch(remote, function (value) { 
     localSetter($scope, value); 
    }); 

    $scope.$watch(local, function (value) { 
     remoteSetter($scope, value); 
    }); 
    } 

    return { 
    attach : twoWayBind 
    }; 
}); 

這將要給你真正的雙向從範圍值綁定。注意我不認爲$ scope。$ parent是必需的,因爲在繼承範圍或無範圍的情況下,任何表達式都應該在當前範圍內解析。你只需要在隔離的範圍內調用$ parent,在這種情況下你不會使用這個,你可以使用隔離的範圍配置。

+0

您測試了這個嗎?我認爲這是正確的方向,但是按照書面形式,它會導致無限的摘要循環。如果你看看[編譯角度](https://github.com/angular/angular.js/blob/master/src/ng/compile.js) - 搜索「case:'='」,你會看到他們已經引入了一些額外的邏輯來防止這一點。恕我直言,該組織的最佳答案。 –

+0

是的,我正在使用它,但只有在一個例子中。我還沒有看到任何無限循環類型的行爲。我明白你的意思,但如果遠程值發生變化,那麼觀察者將設置本地值,它將激發本地觀察者並設置遠程值等等。但是,這似乎並沒有發生。也許$解析中的某些東西正在阻止它。我會仔細看看,謝謝。 – Sam

+0

該解決方案比$ eval解決方案更好,因爲它也適用於原始值和對象引用。 – setec

-2

如果gg是一個對象,那麼你可以使用兩個指令 然後「=」指向一個內存地址!

angular.module('mymodule', []).directive('a', function($parse, $modal) { 
return { 
    restrict : 'A', 
    scope : { 
     gg : "=" 
    }, 
    require : "b", 
    link : function(scope, element, attrs, bCtrl) { 
     scope.$watch('gg',function(gg){ 
      bCtrl.setset(scope.gg); 
     } 
    } 
} 
}); 

angular.module('mymodule').directive('b', function($parse, $modal) { 

return { 
    restrict : 'A', 
    /* 
    * scope : { showWarn : "=" }, 
    */ 
    controller : function($scope) { 
     $scope.bb = {}; 

     this.setset = function(nn) { 

      $scope.bb=nn; 
     }; 

    } 
}); 
相關問題