2013-08-01 4 views
28

Ich möchte ein Formular mit Daten anzeigen, die dem bearbeiteten Element entsprechen. Ich verwende ui-router für das Routing. I definiert einen Zustand:Angular-UI-Router erhalten asynchrone Daten mit Auflösung

myapp.config(function($stateProvider) { 

    $stateProvider. 
    .state('layout.propertyedit', { 
     url: "/properties/:propertyId", 
     views : { 
      "[email protected]": { 
       templateUrl : 'partials/content2.html', 
       controller: 'PropertyController' 
      } 
     } 
    }); 

In PropertyController, ich möchte setzen $scope.property mit Daten aus dem folgenden Aufruf kommen (Google Cloud Endpoints):

gapi.client.realestate.get(propertyId).execute(function(resp) { 
     console.log(resp); 
    }); 

Ich weiß nicht, ob ich resolve verwenden können weil die Daten asynchron zurückgegeben werden. Ich habe versucht,

resolve: { 
     propertyData: function() { 
      return gapi.client.realestate.get(propertyId).execute(function(resp) { 
       console.log(resp); 
      }); 
     } 
    } 

Erste Ausgabe, die propertyId nicht definiert ist. Wie bekommen Sie die propertyId von der url: "/properties/:propertyId"?

Grundsätzlich möchte ich $scope.property in PropertyController auf die resp Objekt vom Async-Aufruf zurückgegeben werden.

EDIT:

myapp.controller('PropertyController', function($scope, , $stateParams, $q) { 

    $scope.property = {}; 

    $scope.create = function(property) { 
    } 

    $scope.update = function(property) { 
    } 

function loadData() { 
    var deferred = $q.defer(); 

    gapi.client.realestate.get({'id': '11'}).execute(function(resp) { 
     deferred.resolve(resp); 
    }); 

    $scope.property = deferred.promise; 
} 

}); 
+1

Füge bitte eine JSFiddle hinzu. – zsong

Antwort

52

Sie müssen the docs for resolve lesen. Resolve Funktionen sind injizierbare, und Sie können $stateParams verwenden Sie den richtigen Wert aus Ihren Routen zu erhalten, etwa so:

resolve: { 
    propertyData: function($stateParams, $q) { 
     // The gapi.client.realestate object should really be wrapped in an 
     // injectable service for testability... 

     var deferred = $q.defer(); 

     gapi.client.realestate.get($stateParams.propertyId).execute(function(r) { 
      deferred.resolve(r); 
     }); 
     return deferred.promise; 
    } 
} 

Schließlich werden die Werte für resolve Funktionen injizierbare sind in Ihrem Controller einmal aufgelöst:

myapp.controller('PropertyController', function($scope, propertyData) { 

    $scope.property = propertyData; 

}); 
+1

Die 'deferred.resolve' wird aufgerufen, aber der Controller wird nicht aufgerufen. Es scheint, dass das Versprechen fest ist. Wenn ich meinen Async-Aufruf durch 'deferred.resolve (" resolved ")' ersetze, wird der Controller aufgerufen. Irgendeine Idee? – Sydney

+0

Aus irgendeinem Grund musste ich '$ rootScope. $ Apply();' nach 'deferred.resolve' aufrufen. – Sydney

+3

Es liegt daran, dass Angulars Versprechungssystem in den Digest-Zyklus des Scope-Systems eingebunden ist. Für alle integrierten APIs von Angular, die Versprechen nutzen, kümmert sich das für Sie. Wenn Sie externe asynchrone APIs verwenden, müssen Sie den Bereich selbst aktualisieren. –

1

Ich denke, Ihre Controller-Funktion benötigt $stateParams Parameter, von dem Sie Ihre propertyId bekommen. Dann können Sie $q Parameter verwenden und Versprechen erstellen $scope.property mit so etwas zu setzen:

var deferred = $q.defer(); 

gapi.client.realestate.get(propertyId).execute(function(resp) { 
    deferred.resolve(resp); 
}); 

$scope.property=deferred.promise; 

Hier ist description of using promises für async Handhabung von Anrufen.

+0

Der 'PropertyController' existiert bereits, also erzeugt er mit der Controller-Funktion' controller: function PropertyController ($ scope, $ stateParams) '' einen neuen 'PropertyController', oder den vorhandenen? – Sydney

+0

Wenn es existiert, wie sieht es aus? – efan

+0

Sehen Sie meine Bearbeitung für den aktuellen Controller – Sydney

0

Wie wäre es damit:

function PropertyController($scope, $stateParams) { 
    gapi.client.realestate.get($stateParams.propertyId).execute(function(resp) { 
    $scope.property = resp; 
    }); 
} 
+0

Der 'PropertyController' existiert bereits, also mit der Controller-Funktion 'controller: function PropertyController ($ scope, $ stateParams)', erstellt es einen neuen 'PropertyController' oder benutzt den bestehenden? – Sydney

1

diese einfache Art und Weise versucht Entschlossenheit

Staatencode in der richtigen Art und Weise zu nutzen:


.state('yourstate', { 
       url: '/demo/action/:id', 
       templateUrl: './view/demo.html', 
       resolve:{ 
        actionData: function(actionData, $q, $stateParams, $http){ 
         return actionData.actionDataJson($stateParams.id); 
        } 
       }, 
       controller: "DemoController", 
       controllerAs : "DemoCtrl" 
      }) 

In dem obigen Code I Parameterdaten sandten, die ich in der URL schicke, Beispiele wenn ich so /demo/action/5 diese Nummer 5 senden zu actionData Dienst gehen, den Service einig JSON-Daten abrufen, basierend auf Ich würde.Schließlich, dass die Daten in actionData gespeichert werden können Sie, dass in Ihrem Controller verwenden, um direkt durch diesen Namen mit

folgenden Code Rückkehr einig JSON-Daten basierend auf ID, die auf staatlicher Ebene vorbei iam


(function retriveDemoJsonData(){ 

    angular.module('yourModuleName').factory('actionData', function ($q, $http) { 

     var data={}; 
     data.actionDataJson = function(id){ 
      //The original business logic will apply based on URL Param ID 
      var defObj = $q.defer(); 
      $http.get('demodata.json') 
       .then(function(res){ 
        defObj.resolve(res.data[0]); 
       }); 
      return defObj.promise; 
     } 
     return data; 
    }); 

})();