2014-02-18 5 views
9

Ich habe AngularJS für ein experimentelles Projekt versucht und ich kam mit diesem Problem. In meinem html mag ich, dass ich mit einem einfachen Controller

Index.HTML

<h1>Some list</h1> 
<div ng-controller="datlist"> 
    <div ng-repeat="item in items"> 
     <div>Item description: {{item.description}}</div> 
     <div>Item name: {{item.name}}</div> 
    </div> 
</div> 

zunächst eine Liste der Elemente anzuzeigen, diese Informationen und aktualisiert, um die Ansicht zu erhalten nur mit:

controllers.js (original)

function datlist($scope,$http){ 
$http({method: 'GET', url: 'http://localhost:61686/getdatlist?format=json', headers: {'Access-Control-Allow-Origin': 'localhost:*'}}). 
    success(function(data, status, headers, config) { 
     $scope.items=data.itemsToReturn; 
     console.log(data); 
}). 
error(function(data, status, headers, config) { 
    console.log("fail"); 
}); 

} 

Das funktionierte ziemlich gut und ich konnte die Liste der Gegenstände bekommen. Indem ich meine Struktur ändere, um eine Factory zu verwenden, um die gleiche Anfrage zu stellen und sie an $ scope.items zu binden, funktioniert es nicht. Ich habe viele Variationen von $ watch ausprobiert, aber ich konnte es nicht dazu bringen, $ scope.items zu aktualisieren. Ich habe etwas über $ gefunden, aber ich kann wirklich nicht verstehen, wie man es benutzt.

controllers.js (neu)

var datModule = angular.module('datModule',[]); 
datModule.controller('datlist', function ($scope, datfactory){ 
    $scope.items = datfactory.getlist(); 
    $scope.$watch($scope.items, $scope.items = datfactory.getlist()); 
}); 
datModule.factory('datfactory', function ($http){ 
    var factory = {}; 
    factory.getlist = function(){ 
     $http({method: 'GET', url: 'http://localhost:61686/getdatlist?format=json', headers: {'Access-Control-Allow-Origin': 'localhost:*'}}). 
     success(function(data, status, headers, config) { 
      console.log(data.itemsToReturn); //I get the correct items, all seems ok here 
      return data.itemsToReturn; 
     }). 
     error(function(data, status, headers, config) { 
      console.log("fail"); 
     }); 

    } 
    return factory; 
}); 

Irgendwelche Ideen dazu wird groß sein. PS: Ich habe viele Posts über dieses Problem gefunden, aber keiner von ihnen hat mir geholfen, eine vollständige Lösung zu bekommen.

Dank

Antwort

18

eine Uhr für die Verwendung ist irgendwie hässlich.

versuchen Sie dies:

datModule.factory('datfactory', function ($http, $q){ 

    this.getlist = function(){    
     return $http.get('http://localhost:61686/getdatlist?format=json',{'Access-Control-Allow-Origin': 'localhost:*'}) 
      .then(function(response) { 
       console.log(response); //I get the correct items, all seems ok here 
       return response.data.itemsToReturn; 
      });    
    } 
    return this; 
}); 

datModule.controller('datlist', function ($scope, datfactory){ 
    datfactory.getlist() 
     .then(function(arrItems){ 
     $scope.items = arrItems; 
     }); 
}); 

Dies ist, wie Sie verspricht für async Materie verwenden.

UPDATE (15.01.2015): Jetzt noch schlanker!

+0

Arbeitete wie ein Charme. Danke –

+0

Schön, danke Konstantin. –

1

Nun, es sieht perfekt aus, aber sie $apply wie diese verwenden können.

datModule.controller('datlist', function ($scope, datfactory){ 
    $scope.$apply(function() { 
     $scope.items = datfactory.getlist(); 
    }); 
}); 
+0

Das scheint nicht zu arbeiten Mate. Danke trotzdem. Ich habe eine ng-Änderung, um auf eine andere Eingabe zu schauen, und ich console.log ($ scope.items) und ich bekomme sowieso undefiniert. Ich weiß nicht wirklich, dass dies nicht funktioniert. –

+0

Versuchen Sie, $ apply –

1

try $scope.items = []; an Controller zu initialisieren, bevor Anruf $ http

ich es Ihnen helfen hoffen.

+0

zu verwenden. Ich hatte das schon ausprobiert. Funktioniert auch nicht. Danke trotzdem. –

8

Das Problem hat nichts mit dem Scope Digest-Zyklus zu tun. Sie versuchen, direkt aus einem Callback heraus zurückzukehren, was nicht asynchron möglich ist.

Ich empfehle, dass Sie entweder ein Versprechen verwenden oder das http-Versprechen direkt zurückgeben.

var factory = {}; 
factory.getlist = function(){ 
    return $http({method: 'GET', url: 'http://localhost:61686/getdatlist?format=json', headers: {'Access-Control-Allow-Origin': 'localhost:*'}}); 

} 
return factory; 

das Versprechen direkt zurückzukehren, und behandeln den Erfolg/Fehler bei factory.getlist().success()

Alternativ Ihr eigenes Versprechen, wenn Sie rund um die Anfrage zusätzliche Logik wickeln möchten.

var datModule = angular.module('datModule',[]); 

datModule.controller('datlist', function ($scope, datfactory){ 
    $scope.items = []; 
    datfactory.getlist().then(function(data) { $scope.items = data }); 
}); 

datModule.factory('datfactory', function ($http, $q){ 
    var factory = {}; 
    factory.getlist = function(){ 
     var defer = $q.defer(); 
     $http({method: 'GET', url: 'http://localhost:61686/getdatlist?format=json', headers: {'Access-Control-Allow-Origin': 'localhost:*'}}). 
     success(function(data) { 
      // alter data if needed 
      defer.resolve(data.itemsToReturn); 
     }). 
     error(function(data, status, headers, config) { 
      defer.reject(); 
     }); 
     return defer.promise; 
    } 
    return factory; 
}); 
+0

Arbeitete wie ein Charme. Danke –

0

Ich denke, eine andere elegante Lösung für dieses Problem könnte sein - wenn Sie eine der Routing-Bibliotheken verwenden, in meinem Fall ist es der UI-Router, könnte aber auch ngRoute, macht Ihren Controller abhängig von der Antwort von das Versprechen, z. Hinzufügen einer resolve-Eigenschaft zu dem adäquaten Zustand/Route, die nicht den Controller Last nicht lassen, bis das Versprechen gelöst wird und die Daten bereit sind, so in Ihre config:

.state('datpage', { 
     url: '/datpage', 
     controller: 'DatpageController', 
     resolve:{ 
     datData: function (datfactory) { 
      return datDataService.getData("datDataParam"); 
     }] 
     }, 
     templateUrl: 'views/datpage.html' 
    }) 

Und die datData Abhängigkeit injizieren in Ihrem Controller, wo Sie es direkt auf das $ scope anwenden können:

.controller('DatpageController', function ($scope,datData) { 
$scope.datPageData = datData; ...