2014-11-14 3 views
8

Ich habe eine Richtlinie mit Isolat Umfang, die einen Umfang variableAngularJs: Warum wird der Bereich innerhalb meiner Direktive nicht aktualisiert, wenn asynchrone Daten eintreffen?

durch Bezug nimmt
angular.module('myApp') 
    .directive('myDirective', function() { 
     return { 
      scope: { 
       items: '=' 
      }, 
      templateUrl: 'template.html', 
      replace: true, 
      controller: 'myDirectiveCtrl', 
      controllerAs: 'ctrl' 
     }; 
    }) 
    .controller('myDirectiveCtrl', function($scope) { 
     this.items = $scope.items; 
    }); 

Dieses in etwa so übergeben wird:

<div my-directive items='items'></div> 

In der externen Steuereinrichtung Daten asynchron geladen wird, und der Umfang Elemente weitergegeben in die Richtlinie aktualisiert:

angular.module('myApp', []) 
    .controller('myCtrl', function($scope) { 

    $scope.setItems = function() { 
     $scope.items = [ 
     'Here', 
     'There', 
     'Everywhere' 
     ]; 
    }; 
    }); 

Wenn die Daten geladen werden, aktualisiert der Bereich außerhalb meiner Direktive, aber drinnen tut es

nicht

Mein html:

 <div my-directive items='items'></div> <!-- this doesn't update --> 

     Outside directive 
     <ul ng-repeat='i in items'>   <!-- this does update --> 
     <li>{{i}}</lu> 
     </ul> 

     <button ng-click="setItems()">Set items</button> 

Wie kann ich meinen Umfang in meiner Anweisung erhalten zu aktualisieren? I Do

Plunker here

Antwort

4

Wenn Angular erste läuft Ihre Richtlinie der Controller-Funktion, Ihr $scope.items === undefined, also wenn Sie tun this.items = $scope.items, Ihre this.items === undefined auch.

Das ist es. Danach ändert sich nichts this.items.

Dies ist anders als $scope.items. $scope.items ist bidirektional an den äußeren Bereich gebunden. Wenn also Angular eine Änderung extern erkennt, wird die isolierte Bereichsvariable festgelegt.

Der einfachste Weg (und am besten geeignet, meiner Meinung nach) ist in der Richtlinie direkt die $scope Eigenschaft zu verwenden:

<div> 
    Inside directive 
    <ul ng-repeat="i in items"> 
     <li>{{ i }}</li> 
    </ul> 
</div> 

Wenn Sie Ihren Controller als Ansichtsmodell statt Umfang nutzen (I don‘ t wissen, warum Sie würden), die Sie tun können:

$scope.$watchCollection("items", function(newVal, oldVal) { 
    ctrl.items = newVal; 
}); 

EDIT:

In Angular 1.3 können Sie auch tun bindToController: true in der Definition der Richtlinie, so dass die Controller-Eigenschaft "items" erhalten die Zwei-Wege-Bindung, die $scope.items bekommt. Dann müssen Sie nicht einmal :

Ihre forked plunker zu illustrieren.

+0

Danke dafür. Die Verwendung des Controllers wurde durch diesen Blogeintrag beeinflusst: http://teropa.info/blog/2014/10/24/how-ive-improved-my-angular-apps-by-banning-ng-controller.html –

+0

Ich habe nicht gesagt, dass Sie keinen Controller verwenden sollten. Ich meinte, dass die scope-exposed-Variable nicht der Variablen des Controllers zugewiesen werden muss. –

+1

@SteveLorimer, ich bearbeitete die Antwort mit einem anderen Ansatz mit 'bindToController', um Ihr Beispiel zu arbeiten –

3

Wenn es Rahmen isoliert ist, können Sie nicht ändern, was in der Richtlinie ist es, nachdem Sie eine separate Variable in der Richtlinie Controller erstellen.

Here ist der aktualisierte Behälter, der den Controller für die Richtlinie entfernt.

1

Versuchen Sie, Ihre Objekte in ein Objekt zu setzen. See this example at Plunker

index.html

<div my-directive items='allItems'></div> 

    Outside directive 
    <ul ng-repeat='i in allItems.items'> 
    <li>{{i}}</lu> 
    </ul> 

    <button ng-click="setItems()">Set items</button> 
</div> 

directive.js:

'use strict'; 

angular.module('myApp') 
.directive('myDirective', function() { 
    return { 
    scope: { 
     items: '=' 
    }, 
    templateUrl: 'template.html', 
    replace: true, 
    controller: 'myDirectiveCtrl', 
    controllerAs: 'ctrl' 
    }; 
}) 
.controller('myDirectiveCtrl', function($scope) { 
    this.items = $scope.items; 
}); 

template.html:

<div> 
    Inside directive 
    <ul ng-repeat="i in ctrl.items.items"> 
    <li>{{ i }}</li> 
    </ul 
</div> 

script.js: hier

angular.module('myApp', []) 
.controller('myCtrl', function($scope) { 
    $scope.allItems={}; 
    $scope.setItems = function() { 
    $scope.allItems.items = [ 
     'Here', 
     'There', 
     'Everywhere' 
    ]; 
    }; 
}); 

Es gibt eine bessere Erklärung:

Angular - ngModel not updating when called inside ngInclude

Verwandte Themen