【问题标题】:Angular ui-router get asynchronous data with resolveAngular ui-router 通过解析获取异步数据
【发布时间】:2013-08-02 23:32:08
【问题描述】:

我想显示一个包含与编辑项目对应的数据的表单。我使用ui-router 进行路由。我定义了一个状态:

myapp.config(function($stateProvider) {

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

PropertyController 中,我想使用来自以下调用(Google Cloud Endpoints)的数据设置$scope.property

    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 未定义。如何从url: "/properties/:propertyId" 获得propertyId

基本上我想将PropertyController 中的$scope.property 设置为异步调用返回的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;
}

});

【问题讨论】:

  • 请添加一个jsfiddle。

标签: angularjs angular-ui angular-ui-router


【解决方案1】:

试试这个简单的方法来正确使用resolve

州代码:


.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 服务,该服务根据 id 检索一些 json 数据。最后,数据将存储到 actionData 您可以使用该名称直接在控制器中使用它

以下代码根据在状态级别传递的 id 返回一些 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;
    });

})();

【讨论】:

    【解决方案2】:

    您需要阅读the docs for resolve。解析函数是可注入的,您可以使用$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;
    
    });
    

    【讨论】:

    • deferred.resolve 被调用但控制器未被调用。看来诺言被卡住了。如果我用deferred.resolve("resolved") 替换我的异步调用,就会调用控制器。有什么想法吗?
    • 由于某种原因,我不得不在deferred.resolve之后打电话给$rootScope.$apply();
    • 这是因为 Angular 的 promise 系统与作用域系统的摘要循环挂钩。对于所有利用 Promise 的 Angular 内置 API,它都会为您处理这些问题。当您使用外部异步 API 时,您需要自己刷新范围。
    【解决方案3】:

    这个怎么样:

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

    【讨论】:

    • PropertyController已经存在,那么使用控制器函数controller: function PropertyController($scope, $stateParams),是创建一个新的PropertyController,还是使用已有的PropertyController
    【解决方案4】:

    我认为您的控制器功能需要$stateParams 参数,您可以从中获取您的propertyId。然后你可以使用$q 参数并创建promise 来设置$scope.property,如下所示:

    var deferred = $q.defer();
    
    gapi.client.realestate.get(propertyId).execute(function(resp) {
        deferred.resolve(resp);
    });
    
    $scope.property=deferred.promise;
    

    这里是description of using promises,用于处理异步调用。

    【讨论】:

    • PropertyController已经存在,那么通过控制器函数controller: function PropertyController($scope, $stateParams),是新建一个PropertyController,还是使用已有的PropertyController
    • 如果存在,它的外观如何?
    • 所以继续添加 $stateParams, $q 到这个定义中: ...'ProperyController', function($scope, $stateParams, $q) { ...
    • 我编辑了我的控制器。但是我不明白如何触发loadData函数。
    • 为什么需要这个 loadData,为什么要在控制器内部定义它?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-23
    相关资源
    最近更新 更多