Reputation: 4237
Which is better for performance, readability and maintainability (Angular 1.5)?
Less, but more complex watches
// component template
<div ng-if="vm.obj.a.b + vm.stuff.c.d + vm.another.thing">
{{ vm.obj.a.b + vm.stuff.c.d + vm.another.thing }}
</div>
Or more, but simpler watches
// component template
<div ng-if="vm.sum">
{{ vm.sum }}
</div>
// component controller...
var vm = this;
$scope.$watch('vm.obj.a.b', fnSum);
$scope.$watch('vm.stuff.c.d', fnSum);
$scope.$watch('vm.another.thing', fnSum);
function fnSum() {
vm.sum = vm.obj.a.b + vm.stuff.c.d + vm.another.thing;
}
Or is there a better way that I'm missing?
This is just a simplified illustration of a situation I come across a LOT. Please focus on the principle, not this exact example.
Upvotes: 2
Views: 55
Reputation: 48968
For readability and maintainability invoke the function directly from the template:
<div ng-show="vm.sum = vm.fnSum()">
{{ vm.sum }}
</div>
JS
vm.fnSum = function fnSum() {
return vm.obj.a.b + vm.stuff.c.d + vm.another.thing;
}
Also using ng-show
avoids creating a new scope.
Be aware that, under the hood, ng-if
, ng-show
, and {{ fn() }}
all create scope watchers. Adding additional watchers for each term of an expression doesn't improve performance.
Upvotes: 2
Reputation: 1785
The latter is better for maintenance reasons:
It allows you to put a succinct end-result into the view, allowing anyone scrolling through to simply read the intended output, rather than parts of what will produce the final result. The view remains uncluttered, while the controller can have verbose comments and contain the entire process for getting the ngIf
determination.
It abstracts a potentially volatile result. Say that you needed to change/update what actually triggered ngIf
; the former would require you to change every instance in the view along with whatever controller changes you're making. The latter is simply updating how the final value came to be in the controller, and knowing that the view is already set.
You could probably make the latter a little better by refactoring it into one $watch
:
var vm = this;
$scope.$watch(function(){
return vm.obj.a.b + vm.stuff.c.d + vm.another.thing;
}, fnSum);
function fnSum(newSum, oldSum) {
vm.sum = newSum;
}
Upvotes: 1