1

I want to make performance optimization of my app. And I came across the following issue. Let me have an object with multiple keys (which are not changeable within one object) and a view similar to this:

<div ng-if="vm.model">
    <span>{{ vm.model.property1 }}</span>
    <span>{{ vm.model.property2 }}</span>
    <span>{{ vm.model.property3 }}</span>
</div>

I would have wanted to use one-time bindings for my properties, but if I change vm.model inside the controller to another object by reference, then my expressions won't be updated inside the view, unless I do an explicit change of model to a falsy value and trigger a digest cycle somehow, to force the whole block to be removed and then recompiled.

Is there a way I can avoid having these 3 redundant watchers, since these properties shouldn't be watched, but only the parent object reference should.

Alexey Katayev
  • 248
  • 2
  • 10

2 Answers2

0

https://docs.angularjs.org/guide/expression

Try this

<div ng-if="vm.model">
    <span>{{ ::vm.model.property1 }}</span>
    <span>{{ ::vm.model.property2 }}</span>
    <span>{{ ::vm.model.property3 }}</span>
</div>
doge1ord
  • 311
  • 1
  • 8
  • I've already mentioned that I cannot use one-time bindings here, and explained the reason. If I do for example scope.vm.model = { ... } inside the directive link function, then those expressions won't be updated. – Alexey Katayev Jul 28 '16 at 10:48
0

@Alexey Katayev Based on my understanding of your problem the issue is not related with AngularJS but its a point about how JavaScript works with the references passed to functions.

Check this post on Is JavaScript a pass-by-reference or pass-by-value language? and the below simple example, I hope it will be of help to you in order to solve your problem.

angular
  .module('demo', [])
  .controller('DefaultController', DefaultController);
  
  function DefaultController() {
    var vm = this;
    vm.model = data[0];
    
    vm.changeModel = changeModel;
    
    function changeModel(model) {
      model.property1 = data[1].property1;
      model.property2 = data[1].property2;
      model.property3 = data[1].property3;
    }
  }
  
  var data = [
  { property1: 'Property 1', property2: 'Property 2', property3: 'Property 3' },
  { property1: 'Property 4', property2: 'Property 5', property3: 'Property 6' },
  { property1: 'Property 7', property2: 'Property 8', property3: 'Property 9' }
  ];
  
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="demo">
  <div ng-controller="DefaultController as vm">
    <button type="button" ng-click="vm.changeModel(vm.model)">Change Model</button>
  
    <div ng-if="vm.model">
      <span>{{ vm.model.property1 }}</span>
      <span>{{ vm.model.property2 }}</span>
      <span>{{ vm.model.property3 }}</span>
    </div>
  </div>
</div>
Community
  • 1
  • 1
Abdul Mateen Mohammed
  • 1,864
  • 1
  • 12
  • 21
  • my goal was to decrease the number of watchers, how is this achieved in your code? it looks the same as my example – Alexey Katayev Jul 28 '16 at 18:05
  • As you say that the expressions in the view are not updating ... are you assigning vm.model (passed as parameter) to another object directly in a function? like this https://jsfiddle.net/tkv1eodg/ this won't affect the parameter, if vm.model is used directly in the function instead of it being passed as the parameter it updates the view see this https://jsfiddle.net/tkv1eodg/1/ or else if the properties of the parameter are updating then the view is also updated as shown in the above embedded code snippet. – Abdul Mateen Mohammed Jul 28 '16 at 18:20