9

Ich bin in der Lage, ein Objekt mit primitiven Daten von einem Service an eine Bereichsvariable von einem Controller richtig zu binden, aber ich habe Probleme, das gleiche mit einer Array-Variable aus dem Dienst zu tun .AngularJS Service-Array-Variable an Controller-Bereich binden

service.js

myServices.factory('MyService', ['$http', function($http) { 
var mySets = []; 

    return { 
    initMySets: function(userId, success, error) { 
    $http.get(apiUrl + "/controller/getmysets", {params:{id:userId}}).success(function (data) { 
     mySets = []; 
     angular.copy(data, mySets); 
    }).error(error); 
    }, 

    getMySets: mySets 


}]); 

controllers.js

myControllers.controller('MenuController', ['$scope', 'UserService', 'MyService', 
    function ($scope, UserService, MyService) { 

    $scope.user = UserService.user; 
    $scope.mySets = MyService.getMySets; 

    $scope.logout = function() { 
    UserService.logout(); 
    } 
}]); 

index.html

<nav id="app-menu" ng-controller="MenuController" ng-class="{hide:!global.showMenu,slide:global.showMenu}"> 
    <div id="menu-head"> 
    <h4>{{user.Email}}</h4> 
    </div> 
    <ul> 
    <div ng-switch on="user.UserId != null"> 
     <li ng-switch-when="true"><a href="#/main" ng-click="toggleMenu();logout();">Logout</a></li> 
     <li ng-switch-when="false"><a href="#/login" ng-click="toggleMenu()">Login</a></li> 
     <li ng-switch-when="true" ng-repeat="mySet in mySets"> 
     <a href="#/mySet /{{mySet.MySetId}}" ng-click="toggleMenu()">{{mySet.Label}}</a> 
     </li> 
    </div> 
    </ul> 
</nav> 

ich eine Login-Funktion haben, die initMySets auf Erfolg ruft in der Benutzer-ID und ich vorbei weiß, dass die mySets-Variable im Service auf der eckigen Kopie korrekt ausgefüllt wird, aber ich nicht das aktuelle Update im Controller bekommen.

Die Variable $ scope.user wird vom UserService aktualisiert, aber die mySet ng-repeat zeigt die Liste nicht vom Dienst an.

Die Daten, die von http.get zurückgegeben werden, sind eine IEnumerable-Sammlung komplexer Objekte von meinem MVC-Web-API-Controller. Ich bin mir nicht sicher, ob das einen Unterschied macht.

+1

Werfen Sie einen Blick auf '$ apply()' Methode: http://docs.angularjs.org/api/ng.$rootScope.Scope – Cherniv

+0

@Cherniv während '$ apply' erzwingt ein Update und kann für einige nützlich sein, haben Dienste selbst keine Gültigkeitsbereiche und das Aufrufen dieser Methode auf dem $ rootScope kann teuer sein. – Blowsie

Antwort

16

Die Bindung funktioniert nicht, da sich Ihr Array (in Ihrem Controller) niemals ändert.

Wenn Ihre initSets-Erfolgsfunktion aufgerufen wird, verweist Ihr internes Array auf ein neues Array, aber Ihre Bereichsvariable zeigt immer noch auf Ihr leeres Ausgangsarray.

Stattdessen erstellen ein neues Array, deaktivieren Sie Ihre erste Array und neue Elemente Push-Array initial:

dass ersetzen:

mySets = []; 
angular.copy(data, mySets); 

Durch das:

mySets.length = 0; // Clear initial array 
mySets.push.apply(mySets, data); // Push data to initial array 

diese Geige Siehe (Ich simuliere einen asynchronen Rückruf mit $ Timeout): http://jsfiddle.net/UJTPD

+0

Danke, ich sehe die Daten in meinem Controller-Bereich jetzt, wenn ich {{mySets [0] .Label}} in der Ansicht rendere, aber die ng-repeat-Schleife durch mySets wird nicht aktualisiert. Muss ich etwas anderes tun, um diese Schleife neu zu starten? –

+0

Okay, es funktionierte, als ich den ng-switch-when = "true" auf dem ng-repeat ablegte. Irgendeine Idee, warum das ein Problem verursachte? –

+0

Das ist ein Lebensretter !! Ich habe stundenlang gekämpft, um ein ähnliches Problem zu lösen. Danke joshua.johnson.814 für die Nachfrage und danke @Mickael für die Antwort – koramaiku

0

Anstatt eine neue Liste zuzuweisen (mySets = []) und dann angular.copy aufzurufen, rufen Sie einfach angular.copy an;

Gefällt mir dies;

angular.copy(data, mySets);