1

I have multiple directives combined in the same view, all accessing the same Angular $resource. One of the directives contains a form.

I would expect $resource to return a singleton so any change in the data would be reflected automatically in all the other directives, but this is not the case.

See a codepen with an example. See also the code below:

angular
  .module("app", ["ngResource"])
  .controller("c1", function($scope, res) {
    $scope.response = res.get();
  })
  .controller("c2", function($scope, res) {
    $scope.response = res.get();
  })
  .service("res", function($resource) {
    const url = "https://httpbin.org/delay/1";
    return $resource(url, {
      get: { method: "GET" },
      save: { method: "POST" }
    });
  });
<div ng-app="app">
  <div ng-controller="c1">
    c1: {{response.origin}}
  </div>
  <div ng-controller="c2">
    c2: {{response.origin}}<br>
    <input width="200" ng-model="response.origin" style="width: 300px;" /><br>
  </div>
</div>

I would expect any change in the input box to be updated in both views ($scope.response should point to the same object), but only the one under the same isolated scope is changed.

Is there a way to share the same $resource object among views?

Miki
  • 1,625
  • 21
  • 29
  • There are several approaches to sharing data between controllers. There is no specific "right way". The shared object approach has the disadvantage that subscribers are not expllicitly notified of changes to the object. The framework must watch the object for changes. Angular 2+ has abandoned that approach so any AngularJS code that depends on it will have difficulty migrating. – georgeawg Jun 15 '19 at 18:12
  • @georgeawg thanks for your comment. That is not strictly true. See codepen example where a shared service is updated across controllers (https://codepen.io/_miki_/pen/bPEJza). – Miki Jun 15 '19 at 23:10
  • The example in the Codepen depends on the watchers in the template and the controllers are not notified of the update. The disadvantages I stated apply. – georgeawg Jun 15 '19 at 23:23

1 Answers1

0

One way to do this is to keep the $resource inside the service and only access it via service methods. See https://codepen.io/miki/pen/xoVoap. You have to be careful with this approach as the singleton will be updated with the parameters passed every time it is called. So this works well for cases when the resource is unique.

angular
  .module("app", ["ngResource"])
  .controller("c1", function($scope, srv) {
    $scope.srv = srv;
    $scope.srv.get("https://httpbin.org/delay/1");
  })
  .controller("c2", function($scope, srv) {
    $scope.srv = srv;
    $scope.srv.get("https://httpbin.org/delay/1");
  })
  .service("srv", function($resource) {
    let service = {};
    service.get = url => {
      service.$resource = $resource(url, {
        get: { method: "GET" },
        save: { method: "POST" }
      });
      service.resource = service.$resource.get();
    };
    return service;
  });

The HTML:


<div ng-app="app">
  <div ng-controller="c1">
    c1: {{srv.resource.origin}}
  </div>
  <div ng-controller="c2">
    c2: {{srv.resource.origin}}<br>
    <input width="200" ng-model="srv.resource.origin" style="width: 300px;" /><br>
  </div>
</div>

Miki
  • 1,625
  • 21
  • 29