1

I'm using AngularJS 1.5, ui-router, and angular-resource and I am developing a component-based application. I have one parent state, which is used for getting and updating data, this data is bound to multiple child states via a parent state resolver.

When I change the data manually in the parent component controller (e.g. vm.town.x = 666), everything works fine and the change is visible in the child state components. However, when I change data in the parent component controller from the response of the rest service (using angular-resource), the data change is visible only in the parent state component.

state definition:

.state('town', {
  url: '/my-towns/:townId/',
  component: 'town',
  bindings: {
    town: 'townData'
  },
  resolve: {
    townData: function(Town, $stateParams) {
      return Town.get({
        townId: $stateParams.townId
      });
    }
  }
})

.state('town.detail', {
  url: 'detail',
  component: 'townDetail',
  bindings: {
    town: 'townData'
  }
})

parent (town) component controller definition:

function TownCmpController(TownServices,Town,BuildingUpgradeRest) {
  var vm = this;
  this.upgradeBuilding = function(data) {
     vm.town = BuildingUpgradeRest.update({townId:  vm.town.TownId,buildingId: data.building.BuildingId});
}

rest service definition:

.factory('BuildingUpgradeRest',function($resource){
    return   $resource('api/public/v1/myaccount/towns/:townId/buildings/:buildingId/upgrade', {townId:'@townId', buildingId: '@buildingId'}, {
    'update': {
      method: 'PUT'
      }
    });
  })

'town' object binding is same in both components

bindings: {
    town: '<'
  }

Both services return the same object type and both work.

5
  • This works initially because you are resolving the town during the transition. When it's successful, both components get the resolve value of town bound to their inputs. When you change the value of vm.town you are overwriting the reference on the parent controller. But the child controller isn't bound to the parent controller; it's bound to the resolved value. If you look at the DOM you will see <town-detail town="::$resolve.town"></town-detail> Commented Jan 10, 2017 at 15:13
  • (...continued) I suggest you update the townId state param so that the town is re-fetched cleanly. If the townId hasn't changed, you can use the { reload: 'town' } transition option to force the town resolve to re-fetch. Commented Jan 10, 2017 at 15:16
  • Hi, thanks for your answer. I just don't understand, why I can do for example vm.town.x = 666 in parent component controller and everything works (the changes are visible in child states components). But only change vm.town by calling the service BuildingUpgradeRest.update() doesn't work. If I understand your suggestion, it means I need to call my rest services 2x for every change of town object (first call for change, second call in state resolve)? Commented Jan 11, 2017 at 11:01
  • It is because with vm.town.x you are changing a property on an object. Because the same object is bound in both controllers, the change is reflected. However, changing vm.town actually changes the vm's reference to a different object. In the other controller, the reference to the original object is still the old one. Commented Jan 11, 2017 at 18:06
  • I don't suggest calling REST services twice each time. I do suggest reloading the resolve (from the REST service) after you save it. If you definitely need to mutate the data in the child and have it reflect in the parent, you could follow the parent/child communication pattern outlined here: ui-router.github.io/guide/ng1/… Commented Jan 11, 2017 at 18:09

1 Answer 1

1
function TownCmpController(TownServices,Town,BuildingUpgradeRest) {
  var vm = this;
  this.upgradeBuilding = function(data) {
     BuildingUpgradeRest.update({townId:  vm.town.TownId,buildingId: data.building.BuildingId}).then(function (response) {
       vm.town = response;
     })
  }
}

Your service return promise, so you reslove service response and then setup vm.towns

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.