AngularJS.关于来自服务的正确双向数据绑定的最佳实践 [英] AngularJS. Best practice concerning proper two way data binding from a service

查看:18
本文介绍了AngularJS.关于来自服务的正确双向数据绑定的最佳实践的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个帐户"服务,它充当多个控制器和视图中使用的集中式数据存储.除了 getter 和 setter 方法之外,该服务将保存与两种类型的用户相关联的所有数据,即登录用户和匿名用户.

I have an 'Account' service which acts as a centralized data storage used in multiple controllers and views. This service will hold, besides getter and setter methods all data associated with two types of users, being a logged in user and an anomonous user.

这个服务背后的想法是它应该被用作一个集中的数据结构,使所有相关的视图和控制器保持同步.例如:如果用户登录,他将知道他的电子邮件和所有新闻通讯订阅"字段都可以预先填写.

The idea behind this service is that it should be used as a centralized data structure which will keep all associated views and controllers in synch. Eg: If a user logs in whe will know his email and all 'newsletter subscription' fields can be prefilled.

我使用的当前设置如下.请注意,服务器上的每个异步调用都会返回一个承诺.

The current setup i use is as below. Note that each Async call on the server will return a promise.

// The Service
angular.module('A').provider('AccountService', [function() {

    this.$get = function ($resource) {

        var Account = {
            getLoggedInAccountAsync : function () {
              var Account = $resource(WebApi.Config.apiUrl + 'Account/Get');
              return Account.get();
            },

            getUserData : function () {
                return Account.userData; 
            },

            setUserData : function (accountData) {
                var merge = angular.extend((Account.currentAccountData || {}), accountData);
                Account.currentAccountData = merge; 
            }    
        };

        return Account;
    }
});

// Our main app controller. Get's fired on every page load.
angular.module('A').controller('MainController', ['AccountService', function (AccountService) {

    var loggedInAccount = AccountService.getLoggedInAccountAsync();
    loggedInAccount.$then(loggedInAccountPromiseResolved);

    function loggedInAccountPromiseResolved (response) {
       if (response.data.isLoggedIn) {
           AccountService.setAccountData(response.data);
       }
    };

    return $scope.MainController= this;
}])

// Our specific controller. For example a newsletter subscription.
angular.module('A').controller('SpecificController', ['AccountService', function (AccountService) {
    this.getUserData = AccountService.getUserData;
    return $scope.Controller = this;
}])

// Newsletter subscription view
<input id="email" type="email" name="email" ng-model="SpecificController.getUserData().UserName"/>

使用上述代码可确保每当我们使用该服务通过 Controller.getUserData().property 将我们的数据绑定到我们的视图时,它将在我们的整个应用程序中保持同步.

Using the above code ensures that whenever we use the service to bind our data via Controller.getUserData().property to our view it will stay in synch throughout our entire app.

例如,如果未定义 .UserName 值,或者在出现匿名用户的情况下根本没有帐户数据,则上面的代码也会抛出.解决此问题的一种方法是使用空值在我们的服务中转储"我们的模板"对象,这将确保键/值存在.另一种方法是使用观察者并让我们的控制器写入"我们的服务,以防用户填写字段.

The code above will also throw if for example the .UserName value is not defined, or if there is no account data at all in case of an anomonous user. One way around this is to 'dump' our 'template' object within our service with null values this will ensure the key/values exist. Another way would be to use watchers and let our controller(s) 'write' to our service in case an user fills a field.

第一个选项为我提供了更大的灵活性,因为我可以将所有数据绑定集中在服务中,但感觉很脏,因为您永远不知道服务器数据会发生什么,例如,它可以采用不同的格式.

The first option gives me more flexability as i can centralize all the data binding in the service but it feels dirty because you never know what will happen with the server data, it could come in as a different format for example.

有没有人有其他解决办法?我不想让我的控制器将数据写入服务.

Does anyone have any other solution? I would prefer to not let my controllers do the writing of the data to the service.

感谢您的宝贵时间!

推荐答案

  1. 首先,如果您在 AngularJS 中使用服务,我们期望调用服务器或任何可能不会立即返回数据的东西.所以我们有两种方法使用丑陋的回调或漂亮的$q.

我更喜欢使用 promise,因为它写起来更简洁.我会以更好的方式重写您的片段:

I prefer using promise since it's cleaner to write. I will rewrite your snippets in a better way :

// Service
angular.module('A').provider('AccountService', [function() {

    this.$get = function ($resource, $q) {

        var Account = {
            getUserData : function () {
                var d = $q.defer();
                d.resolve(Account.userData);
                return d.promise; 
            }    
        };

        return Account;
    }
});

// Controller
angular.module('A').controller('Controller', ['AccountService', function (AccountService) {
    var init = function() {
      getUserData();
    };

    var getUserData = function() {
       AccountService.getUserData().then(function(data) { $scope.username = data; }); 
    };

    init();
    //return $scope.Controller = this; // you don't need to do this 
}])

HTML:

<input id="email" type="email" name="email" ng-model="username"/>

这篇关于AngularJS.关于来自服务的正确双向数据绑定的最佳实践的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆