简体   繁体   English

在控制器AngularJs与服务之间共享数据

[英]Share data between controllers AngularJs with Services

Background 背景

I am making Service which has a list to be shared between two controllers. 我正在制作Service,它有一个列表可以在两个控制器之间共享。 To start I followed this tutorial on Services: 首先,我按照本教程关注服务:

And I managed to successfully create and execute the basic tutorial on Plunker: 我成功地创建并执行了Plunker的基础教程:

Problem 问题

The problem here, is that when I click the form button, I need to make an HTTP GET request to my server, and update the service list when I get the response. 这里的问题是,当我单击表单按钮时,我需要向服务器发出HTTP GET请求,并在收到响应时更新服务列表。

To achieve this, I first tried using the following Plunker modification: 为此,我首先尝试使用以下Plunker修改:

The jest of the code can be seen in the service: 可以在服务中看到代码的笑话:

  // Create the factory that share the Fact
  app.factory('ListService', function($http) {
    var list = {};
    list.data = [];

    list.request = function(theHairColor) {
      var theUrl = "https://gnome-shop-fl4m3ph03n1x.c9users.io/api/v1/gnomes?hairColor=" + theHairColor;
      console.log(theUrl);
      $http({
        method: 'GET',
        url: theUrl,
        headers: {
          'Content-Type': 'application/json; charset=utf-8'
        }
      }).then(function successCallback(response) {
        list.data = response.data.entries; //does not work
        console.log(response.data.entries);
      }, function errorCallback(response) {
        console.log('Error: ' + response);
      });
    };

    return list;
  });

If you tried it out, you will see it simply doesn't work, and I don't really understand why. 如果你尝试过,你会发现它根本不起作用,我真的不明白为什么。 In a previous question I made, someone explained to me that it was related to references, and that I should replace list.data = response.data.entries; //does not work 在我之前提出的一个问题中,有人向我解释说它与引用有关,我应该替换list.data = response.data.entries; //does not work list.data = response.data.entries; //does not work for the following: list.data = response.data.entries; //does not work用于以下内容:

//this works but is rather flimsy ....
list.data.length = 0;
Object.assign(list.data, response.data.entries);

Which in deed does work, but I find it rather counter intuitive: 这在行动中起作用,但我发现它相当直观:

Another suggestion was also given, in that I should change my gnomeList controller to : 还给出了另一个建议,我应该将我的gnomeList控制器更改为:

app.controller("gnomeList", function(ListService) {
    var self = this;
    self.listService = ListService;
  });

and then iterate over the service's list directly: 然后直接遍历服务列表:

<div ng-controller="gnomeList as listCtrl">
      <p ng-repeat="gnome in listCtrl.listService.data">{{ gnome.id }}: {{ gnome.name }}</p>
</div>

Which also works, but attaches the controller directly to the service: 哪个也有效,但将控制器直接附加到服务:

Questions: 问题:

  1. Are there any other ways to make my first code sample (that didn't work) work? 有没有其他方法可以使我的第一个代码示例(不起作用)工作?
  2. Which of these solutions would be preferable and why? 哪种解决方案更可取?为什么? (which one is more Angulary ?) (哪一个更像Angulary ?)

Problem is you initially copy the data in your gnomeList and it is passed by value. 问题是你最初复制gnomeList中的数据并按值传递。

app.controller("gnomeList", function(ListService) {
  var self = this;
  self.list = ListService.data;
});

When your controller gets initialized here, it puts a copy of ListService.data into self.list . 当您的控制器在此处初始化时,它会将ListService.data的副本放入self.list However, when updating the values in the services, this controller does not get initialized again and therefore the value is not updated. 但是,更新服务中的值时,此控制器不会再次初始化,因此不会更新该值。

Objects in javascript are passed by reference. javascript中的对象通过引用传递。 Just like you said, you could directly put the service on scope to use its data or you simply set the properties on an object before you set them on your scope. 就像你说的那样,你可以直接将服务放在范围内以使用它的数据,或者只需在对象上设置属性,然后再在范围上设置它们。 ( Plunkr ) 普兰克

Javascript 使用Javascript

app.controller("gnomeList", function(ListService) {
  var self = this;
  self.list = ListService.value; // value is an object
});

// Create the factory that share the Fact
app.factory('ListService', function($http) {
  var list = {};
  list.value = {};

  list.request = function(theHairColor) {
    var theUrl = "https://gnome-shop-fl4m3ph03n1x.c9users.io/api/v1/gnomes?hairColor=" + theHairColor;
    console.log(theUrl);
    $http({
      method: 'GET',
      url: theUrl,
      headers: {
        'Content-Type': 'application/json; charset=utf-8'
      }
    }).then(function successCallback(response) {
      list.value.data = response.data.entries; // extend value object
    }, function errorCallback(response) {
      console.log('Error: ' + response);
    });
  };

  return list;
});

HTML HTML

<div ng-controller="gnomeList as listCtrl">
  <p ng-repeat="gnome in listCtrl.list.data">{{ gnome.id }}: {{ gnome.name }}</p>
</div>

Moreover it is better to use built in angular.extend for extending objects. 此外,最好使用内置的angular.extend来扩展对象。

So this doesn't work? 所以这不起作用?

list.request = function(theHairColor) {
  var theUrl = "https://gnome-shop-fl4m3ph03n1x.c9users.io/api/v1/gnomes?hairColor=" + theHairColor;
  console.log(theUrl);
  $http({
    method: 'GET',
    url: theUrl,
    headers: {
      'Content-Type': 'application/json; charset=utf-8'
    }
  }).then(function success(data) {
    list.data = data;
    console.log(data);
    return data;
  });
};

That would be a structure we've used in the past (we use Restangular now), but this link is a good page to see about $http that would help you. 这将是我们过去使用过的结构(我们现在使用Restangular),但是这个链接是一个很好的页面,可以看到有助于您的$ http。

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

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