Angular ui-router получает асинхронные данные с разрешением

Я хочу отобразить форму с данными, соответствующими редактируемому элементу. Я использую ui-router для маршрутизации. Я определил состояние:

myapp.config(function($stateProvider) {

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

В PropertyController я хочу установить $scope.property с данными, поступающими из следующего вызова (конечные точки Google Cloud):

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

Я не знаю, смогу ли я использовать resolve, потому что данные возвращаются асинхронно. Я попытался

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

Первая проблема, propertyId не определена. Как получить propertyId из url: "/properties/:propertyId"?

В основном я хочу установить $scope.property в PropertyController для объекта resp, возвращаемого асинхронным вызовом.

РЕДАКТИРОВАТЬ:

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;
}

});

person Sydney    schedule 01.08.2013    source источник
comment
добавьте jsfiddle, пожалуйста.   -  person zs2020    schedule 02.08.2013


Ответы (4)


Вам необходимо прочитать документацию по разрешению. Функции разрешения можно внедрять, и вы можете использовать $stateParams, чтобы получить правильное значение из ваших маршрутов, например:

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;
    }
}

Наконец, значения для функций разрешения могут быть введены в ваш контроллер после разрешения:

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

    $scope.property = propertyData;

});
person Nate Abele    schedule 02.08.2013
comment
deferred.resolve вызывается, но контроллер не вызывается. Кажется, что обещание застряло. Если я заменю свой асинхронный вызов на deferred.resolve("resolved"), будет вызван контроллер. Есть идеи? - person Sydney; 03.08.2013
comment
По какой-то причине мне пришлось позвонить $rootScope.$apply(); после deferred.resolve - person Sydney; 03.08.2013
comment
Это потому, что система промисов Angular подключена к циклу дайджеста системы видимости. Для всех встроенных API-интерфейсов Angular, использующих промисы, он позаботится об этом за вас. Когда вы используете внешние асинхронные API, вам необходимо обновить область самостоятельно. - person Nate Abele; 03.08.2013

Я думаю, что вашей функции контроллера нужен параметр $stateParams, из которого вы можете получить свой propertyId. Затем вы можете использовать параметр $q и создать обещание установить $scope.property примерно так:

var deferred = $q.defer();

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

$scope.property=deferred.promise;

Вот описание использования промисов для обработки асинхронных вызовов.

person efan    schedule 01.08.2013
comment
PropertyController уже существует, поэтому, используя функцию контроллера controller: function PropertyController($scope, $stateParams), он создает новый PropertyController или использует существующий? - person Sydney; 02.08.2013
comment
Если он существует, как он выглядит? - person efan; 02.08.2013
comment
Итак, добавьте $stateParams, $q к этому определению: ...'ProperyController', function($scope, $stateParams, $q) { ... - person efan; 02.08.2013
comment
Я редактировал свой контроллер. Но я не понимаю, как вызвать функцию loadData. - person Sydney; 02.08.2013
comment
Зачем вам нужны эти loadData и почему вы определяете их внутри контроллера? - person efan; 02.08.2013
comment
Вы можете поместить тело вашего loadData прямо в функцию контроллера. Если вы хотите большего разделения интересов, вам, вероятно, следует рассмотреть возможность использования сервисов. - person efan; 02.08.2013

Попробуйте этот простой способ использовать разрешение правильно

Код штата:


.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"
            })

В приведенном выше коде я отправляю данные параметров, которые я отправляю в URL-адресе. Например, если я отправлю вот так /demo/action/5, это число 5 отправится в службу actionData, которая извлечет некоторые данные json на основе идентификатора. Наконец, эти данные будут сохранены в actionData Вы можете использовать это в своем контроллере напрямую, используя это имя

Следующий код возвращает некоторые данные JSON на основе идентификатора, который передается на уровне состояния.


(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;
    });

})();

person Ramesh M    schedule 19.11.2016

Как насчет этого:

function PropertyController($scope, $stateParams) {
   gapi.client.realestate.get($stateParams.propertyId).execute(function(resp) {
     $scope.property = resp;
   });
}
person ambi    schedule 01.08.2013
comment
PropertyController уже существует, поэтому, используя функцию контроллера controller: function PropertyController($scope, $stateParams), он создает новый PropertyController или использует существующий? - person Sydney; 02.08.2013