2

JSBin例的transcluded內容內更新範圍: http://jsbin.com/yuyetakonowu/1/edit?html,js,outputAngularJS,分配不一致時對一個指令的分離的範圍

摘要: 我有兩個指令的(myParentDirective和myChildDirective)。 myParentDirective transcludes myChildDirective內容。我試圖在myChildDirective中雙向綁定模型對象。當我通過簡單地改變或添加屬性到現有的對象實例來「更新」對象時,它成功地工作。但是,當我「分配」一個新對象時(使用控制器的超時函數中的等號運算符)myChildDirective不會被更新。

HTML

<html ng-app='ValidationApp'> 

<head> 
    <title>Assigning a model object after isolated scope is set doesn't work</title> 
</head> 

<body ng-controller='MyController'> 

    <h2>MyController.assignedObject: {{assignedObject}}</h2> 
    <h2>MyController.updatedObject: {{updatedObject}}</h2> 

    <my-parent-directive assigned-object='assignedObject' updated-object='updatedObject'> 
     <my-child-directive></my-child-directive> 
    </my-parent-directive> 


    <script src='//ajax.googleapis.com/ajax/libs/angularjs/1.3.0-beta.17/angular.js'></script> 
    <script src='app.js'></script> 
</body> 

</html> 

的JavaScript

var app = angular.module('ValidationApp', []) 

app.controller('MyController', [ 
    '$scope', 
    '$http', 
    function($scope, $http) { 
     // Model objects loaded on page-load 
     $scope.assignedObject = {value: 'pre-update'} 
     $scope.updatedObject = {value: 'pre-update'} 

     // Mock ajax request 
     setTimeout(function() { 

      // This is what I'm ultimately trying to accomplish. However, myChildDirective is not properly 
      // showing the updated value 'post-update'. 
      $scope.assignedObject = {value: "post-update"} 

      // I noticed that this line will properly update myChildDirective, but it's not an ideal solution. 
      // I'm including it in the example just to show the inconsistent results in myChildDirective. 
      $scope.updatedObject.value = "post-update" 

      $scope.$apply() 

     }, 1000) 
    } 
]) 

app.directive('myParentDirective', function() { 
    return { 
     restrict: 'E', 
     transclude: true, 
     scope: { 
      assignedObject: '=', 
      updatedObject: '=' 
     }, 
     template: '\ 
      <h2>myParentDirective.assignedObject: {{assignedObject}}</h2>\ 
      <h2>myParentDirective.updatedObject: {{updatedObject}}</h2>\ 
      <div ng-transclude></div>\ 
      ', 
     controller: function($scope, $element) { 
      this.assignedObject = $scope.assignedObject 
      this.updatedObject = $scope.updatedObject 
     } 
    } 
}) 

app.directive('myChildDirective', function() { 
    return { 
     restrict: 'E', 
     require: '^myParentDirective', 
     scope: false, 
     template: '\ 
      <h2>myChildDirective.myParentDirective.assignedObject: {{myParentDirective.assignedObject}}</h2>\ 
      <h2>myChildDirective.myParentDirective.updatedObject: {{myParentDirective.updatedObject}}</h2>\ 
      ', 
     link: function($scope, $element, $attrs, myParentDirective) { 
      $scope.myParentDirective = myParentDirective 
     } 
    } 
}) 

回答

2

,我發現我的問題幾個解決方案...

的問題是,我指定$ scope.assignedObject指向myParentDirective中的this.assignedObject。當我這樣做時,myChildDirective無法知道屬性何時發生變化。通常情況下,將調用$ scope。$ apply()函數來通知所有觀察者scope屬性已更改,但由於我將此對象引用重新分配給this.assignedObject,myChildDirective從不接收該事件。

最簡單的解決方案可以在這裏找到:http://jsbin.com/yuyetakonowu/11/edit。基本上,這只是繼承父範圍,以便我可以依靠angular的範圍來發出相應的事件並相應地更新myChildDirective。

但是,這對我來說還不夠好,因爲我還需要使用myChildDirective來創建具有自己屬性的隔離範圍。這意味着我不能簡單地「繼承」父範圍。我已使用以下方法解決了此問題:http://jsbin.com/yuyetakonowu/9/edit

最終結果是:

HTML:

<html ng-app='ValidationApp'> 

<head> 
    <title>Assigning a model object after isolated scope is set doesn't work</title> 
</head> 

<body ng-controller='MyController'> 

    <h1>MyController</h1> 
    <h2>assignedObject: {{assignedObject}}</h2> 
    <h2>updatedObject: {{updatedObject}}</h2> 

    <my-parent-directive assigned-object='assignedObject' updated-object='updatedObject'> 
     <my-child-directive child-property='child-property-value'></my-child-directive> 
    </my-parent-directive> 


    <script src='//ajax.googleapis.com/ajax/libs/angularjs/1.3.0-beta.17/angular.js'></script> 
    <script src='app.js'></script> 
</body> 

</html> 

的JavaScript:

var app = angular.module('ValidationApp', []) 

app.controller('MyController', [ 
    '$scope', 
    '$http', 
    function($scope, $http) { 
     // Model objects loaded on page-load 
     $scope.assignedObject = {value: 'pre-update'} 
     $scope.updatedObject = {value: 'pre-update'} 

     // Mock ajax request 
     setTimeout(function() { 

      // This is what I'm ultimately trying to accomplish. However, myChildDirective is not properly 
      // showing the updated value 'post-update'. 
      $scope.assignedObject = {value: "post-update"} 

      // I noticed that this line will properly update myChildDirective, but it's not an ideal solution. 
      // I'm including it in the example just to show the inconsistent results in myChildDirective. 
      $scope.updatedObject.value = "post-update" 

      $scope.$apply() 

     }, 1000) 
    } 
]) 

app.directive('myParentDirective', function() { 
    return { 
     restrict: 'E', 
     transclude: true, 
     scope: { 
      assignedObject: '=', 
      updatedObject: '=' 
     }, 
     template: '\ 
      <h1>myParentDirective</h1>\ 
      <h2>assignedObject: {{assignedObject}}</h2>\ 
      <h2>updatedObject: {{updatedObject}}</h2>\ 
      <div ng-transclude></div>\ 
      ', 
     controller: function($scope, $element) { 
      // Generally, exposing isolate scope is considered bad practice. However, this directive is intended 
      // to be used with child directives which explicitly depend on this directive. In addition, child 
      // directives will likely need their own isolated scope with two-way binding of properties on this scope. 
      this._scope = $scope 
     } 
    } 
}) 

app.directive('myChildDirective', function() { 
    return { 
     restrict: 'E', 
     require: '^myParentDirective', 
     scope: { 
      childProperty: '@' 
     }, 
     template: '\ 
      <h1>myChildDirective</h1>\ 
      <h2>childProperty: {{childProperty}}</h2>\ 
      <h2>assignedObject: {{assignedObject}}</h2>\ 
      <h2>updatedObject: {{updatedObject}}</h2>\ 
      ', 
     link: function($scope, $element, $attrs, myParentDirective) { 
      myParentDirective._scope.$watch('assignedObject', function(newValue, oldValue) { 
       $scope.assignedObject = newValue 
      }) 
      myParentDirective._scope.$watch('updatedObject', function(newValue, oldValue) { 
       $scope.updatedObject = newValue 
      }) 
     } 
    } 
})