1

I am working on a section of an AngularJS (1.4.2) app and trying to get my head around how to get a controller updated data from a service when its data changes.

I have set up this plunker to demonstrate the problem. I hope the example doesn't seem too convoluted, but in the app I have a main tables view like the one in the plunker, but with five tabs, each with its own partial html file and controller. Right now there's one service that holds all the fields data, much like in the plunker. The idea is that users can check the box next to a given field to activate/deactivate it as it suits their data, and only active fields should be persisted in the database, thus the service returning filtered data to the controller. The verifyFields() function in MainCtrl simulates the save function in my app, and the controller should be populating the newConnectionData object with updated data from the fields service.

I've included a pre to show that the service model data does indeed update when the checkbox is checked and unchecked or when the input value changes. But I've so far been unable to get the data to update in the main controller.

I tried to incorporate separately in the plunker solutions from this stack overflow question that suggests returning a function rather than a primitive from the service:

test.service('fields', function() {
  ...
  var fields = this;
  return {
    ...
    activeOrders    : function() { return filteredOrders },
    activeShipment  : function() { return filteredShipment },
    activeActivity  : function() { return filteredActivity }
  }

test.controller('MainCtrl', ['$scope', '$rootScope', 'fields',
    function($scope, $rootScope, fields) {
  ...
  $scope.activeShipment = function () {
    return fields.activeShipment(); 
  };
  $scope.activeActivity = function () {
    return fields.activeActivity(); 
  };

...and this one that suggests using a $watch:

$scope.$watch(function () { return fields.activeOrders() }, function (newVal, oldVal) {
  if (typeof newVal !== 'undefined') {
    $scope.activeOrders = fields.activeOrders();
  }
});

$scope.newConnectionData = {};
...
$scope.verifyFields = function () {
  $scope.newConnectionData = {
    orders    : $scope.activeOrders,
    shipment  : $scope.activeShipment(),
    activity  : $scope.activeActivity()
  }
  ...
}

...but neither has thus far solved the issue of updating the data in the controller. If you have any suggestions, I would be much obliged. Thank you for your time!

Community
  • 1
  • 1
Bennett Adams
  • 1,808
  • 14
  • 17

2 Answers2

1

let the service expose data as properties. Don't over complicate usage in controller. Just use directly. If you need to show data in html, add reference to the service in $scope.

test.service('fields', function() {
  ...
  var fields = this;
  return {
    ...
    activeOrders    : filteredOrders ,
    activeShipment  : filteredShipment ,
    activeActivity  : filteredActivity 

In controller

test.controller('MainCtrl', ['$scope', '$rootScope', 'fields',
    function($scope, $rootScope, fields) {
 $scope.fields = fields;

In template

{{fields.activeShipment}}
Kirill Slatin
  • 6,085
  • 3
  • 18
  • 38
  • Thank you for taking the time to read through and make this suggestion. I'll go back and refactor my service with your input as well as @Exo's (which solved my immediate problem). The root cause seemed to be the _.where function, and I think I overcomplicated the service reaching for other possible answers. – Bennett Adams Jul 28 '15 at 20:02
0

It looks like you may need to recalculate your _.where with the function calls.

Your factory service's would have lines like:

activeOrders    : function() { return _.where(fields.ordersSchema, {active: true} ); },

Here is what I ended up with.

Zachary Kuhn
  • 1,152
  • 6
  • 13
  • This solved my problem. Thank you very much. I'm not sure I understand why setting the _.where function to a variable and then returning it did not work, as opposed to returning the _.where itself, but I certainly appreciate the feedback. Cheers! – Bennett Adams Jul 28 '15 at 19:57
  • In the original code, `filteredOrders` had its value set to the value returned from `_.where` when it was hit the first time. Every call to `activeOrders` returned that stored value. It never executes `_.where` again. Putting the call to `_.where` within the function means every time that function is called, `_.where` is recalculated. – Zachary Kuhn Jul 28 '15 at 21:18
  • Ah, ok. Makes sense now. Thanks again :) – Bennett Adams Jul 29 '15 at 01:49