简体   繁体   English

在angularjs中共享和保存来自多个控制器的数据

[英]share and save data from multiple controllers in angularjs

I can't seem to figure out which way to go about this problem: 我似乎无法弄清楚该问题的解决方法:

I got multiple angular controllers, they all need a user-object, which they can manipulate with, and each time it gets manipulated the "new" data needs to be out in the other controllers aswell. 我有多个角度控制器,它们都需要一个用户对象,可以对其进行操作,并且每次操纵该对象时,“新”数据也需要在其他控制器中输出。 At the same time i need to save this user-object in the database for retrievel afterwards (so a auto save function when data is changed on user-object) 同时,我需要将此用户对象保存在数据库中,以便以后进行检索(因此,当用户对象上的数据发生更改时,它具有自动保存功能)

But i can't seem to figure out whether i should using a factory or a service to hold this user-object, and how i can get this factory/service to save the user on change via a API. 但是我似乎无法弄清楚是否应该使用工厂或服务来保存此用户对象,以及如何通过API通过此工厂/服务来保存用户以进行更改。

I read this Sharing ajax data between multiple controllers in angular using service example where he wants to accomplish some of the same things, but the API part and async automatic saving is really giving me trouble! 我阅读了这篇有关在角度使用服务示例的多个控制器之间共享ajax数据的文章 ,他想完成一些相同的事情,但是API部分和异步自动保存确实给我带来了麻烦!

Bottom line is, i have multiple controllers which needs a user-object from the serverside. 最重要的是,我有多个控制器,它们需要服务器端的用户对象。 And these controllers manipulates with the same user-object, and after each manipulation(maybe with some debounce), i want to save the object to the database via API. 这些控制器使用相同的用户对象进行操作,并且在每次操作后(可能会有一些反跳),我都希望通过API将对象保存到数据库中。

(first of, i thought of watching the object in the service/factory, but found out i couldn't :( ) (首先,我想到要在服务/工厂中查看对象,但发现我无法:()

Can you guys point me in the right direction? 你们能指出我正确的方向吗?

Whether to create a service or factory is really a design issue. 创建服务还是工厂实际上是一个设计问题。

You probably want to look at libraries such as $resource , Restangular or ThickM , which helps you create services which relate your models to API endpoints for fetching and saving. 您可能想要查看$ resourceRestangularThickM之类的库,这些库可帮助您创建将模型与API端点相关联的服务以进行获取和保存。

Asynchronous automatic saving could be solved either in the service or on controllers. 异步自动保存可以在服务中或在控制器上解决。

Disclosure: I'm the author of ThickM. 披露:我是ThinM的作者。

  1. You create a User object (either via a service or a factory). 您创建一个User对象(通过服务或工厂)。
  2. You inject that object into any controller that wants to interact with it. 您可以将该对象注入要与之交互的任何控制器中。
  3. You $watch that object (from inside the service itself if you consider that functionality to be a core part of the User entity) and update the backend when a change is detected (optionally with a debounce). 您可以从服务本身$watch这个对象(如果您认为该功能是User实体的核心部分,则可以从服务本身内部),并在检测到更改时更新后端(可以选择使用反跳功能)。
  4. For $watch ing something from inside a service, you can inject the $rootScope service. 对于$watch从服务内部查看内容,可以注入$rootScope服务。
  5. Keep in mind that (in a real app) you need to account for errors and corner-cases. 请记住(在真实应用中),您需要考虑错误和极端情况。 Eg what happens if the user navigates away from the page before the debounce period has passed etc. 例如,如果用户在经过反跳周期之前导航离开页面,该怎么办?

Below is a naive POC implementation. 以下是朴素的POC实施。 In the real world, you'd probably want to use module (like the ones mentioned by Mikke ) and wrap yur service around it, in order to save a lot of boilerplate code while interacting with your RESTful data source. 在现实世界中,您可能希望使用模块(如Mikke提到的模块 )并在其周围包装yur服务,以便在与RESTful数据源进行交互时节省大量样板代码。


A demo service might look like this: 演示服务可能如下所示:

.factory('User', function ($q, $rootScope, $timeout) {
    var apiEndpoint = '/api/user';
    var guest = {
        username: 'Guest',
        email   : null,
        loggedIn: false
    };
    var user = {};

    user.login = function (credentials) {
        user.logout();

        // In real app: Make a login request
        var request = $q.defer();
        $timeout(function () {
            user.username = 'ExpertSystem';
            user.email    = 'expert@system';
            user.loggedIn = true;
            request.resolve(user);
        }, 1000);

        return request.promise;
    };

    user.logout = function () {
        // In real app: Make a logout request
        angular.extend(user, guest);
    };

    user.update = function () {
        // In real app: Make a request to update user info
        alert('Updating the backend...');
    };

    var updateTimeout;
    user.updateWithDebounce = function () {
        $timeout.cancel(updateTimeout);
        updateTimeout = $timeout(function () {
            user.update();
        }, 1000);
    };

    $rootScope.$watchCollection(function () {
        return user;
    }, function (newValue, oldValue) {
        var shouldUpdate = newValue && newValue.loggedIn &&
                           oldValue && oldValue.loggedIn;
        // Immediate backend update
        //if (shouldUpdate) user.update();

        // Debounced backend update (1 sec debounce)
        if (shouldUpdate) user.updateWithDebounce();
    });

    user.login();

    return user;
});

See, also, this short demo . 另请参见此简短演示

When sharing data between controllers a service is the way to go. 当在控制器之间共享数据时,一种服务是必经之路。 You seem to have a good idea about this already. 您似乎已经对此有了一个好主意。

For saving the user after each manipulation I don't understand what the issue is. 为了在每次操作后节省用户,我不了解问题所在。 Create a modify user method after which you could do an object comparison. 创建一个修改用户方法,之后您可以进行对象比较。 If there is a difference send the PUT request to the api. 如果存在差异,则将PUT请求发送到api。

I recommend you always share data between your controllers (and also directives) using a Service/Factory and injecting it on both sides. 我建议您始终使用Service / Factory在控制器(以及指令)之间共享数据,并在两侧注入数据。

After that, just use your promise resolution function to update the service value. 之后,只需使用您的承诺解决功能即可更新服务价值。

app.factory('SharedService', function() {
  return {
    sharedObject: {
      value: '',
      value2: ''
    }
  };
});

app.controller('FirstCtrl', function($scope, SharedService) {
  $scope.model = SharedService.sharedObject;
});

app.directive('myDirective',['SharedService', function(SharedService){
  return{
    restrict: 'E',
    link: function(scope){
      scope.model = SharedService.sharedObject;
    },
    template: '<div><input type="text" ng-model="model.value"/></div>'
  }
}]);

Here is a plunkr showing how it can be done: http://plnkr.co/edit/Q1VdKJP2tpvqqJL1LF6m 这是一个显示如何完成操作的插件: http ://plnkr.co/edit/Q1VdKJP2tpvqqJL1LF6m

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM