KO.Computed equivalent in Angular / Breeze Initializer
Asked Answered
D

2

21

Trying to get a more in-depth understanding of how Angular treats data binding and understanding it better and one thing is difficult to get my head around -

In Knockout I use a computed to keep track of changes to a property. In Angular it to move this logic into the view, which is a it trivial to me, but if that is the way to do it I understand.

My question is when I am initializing a new entity with Breeze/Angular how do I create computed-like properties that are notified when changes occur to the entities property?

myEntity.fullName = ko.computed(function () {
    return myEntity.firstName + ' ' + myEntity.LastName;
});

in Angular would the equivalent be

myEntity.fullName = function () {
    return myEntity.firstName + ' ' + myEntity.LastName;
};

And does that properly track the entity?

Domash answered 14/8, 2013 at 2:6 Comment(1)
It does not properly track the entity. The function is triggered everytime any value in the myEntity object changes.Montes
M
18

You are correct to simply make it a function. If your entity as shown is added to the $scope, then you would access the property like so:

<span class="fullname">{{ user.fullName() }}</span>

Whenever Angular runs a $digest cycle, it will check for a change to the bound property. In this instance, it means it will call the fullName() function and check to see if the result has changed. If it has, anything that has a $watch attached to that item — including simple binding — will be notified of the change.

One caveat of this technique, however, is to make sure that the operations being performed within your function are relatively fast, and also have no side effects. Bound functions like this will be called many times throughout the application.

If you need to have a more complex function, it would be better to handle that within the controller, and update a property on the object manually when it changes.

Megavolt answered 14/8, 2013 at 2:56 Comment(3)
So if I understand this correctly anytime I make a keystroke inside of any tag with ngModel on it the function would be reevaluated?Domash
I believe so. It's far, far faster than you might imagine.Megavolt
Cool, I will mark as an answer as long as no one has an opposing view that refutes the fabric of your answers' existence pretty soon. Could you hint at the difference between using it as a function vs just assigning a value? Is the latter just creating a constructor that will not be updated whereas a function will?Domash
M
0

I found the answer on the following website. If you don't do something similar, what you will find is that all functions are ran during the digest phase and are not triggered by the change of a dependent observable or property. The solution below allows you to only trigger the function when a value it uses is changed.

http://www.jomendez.com/2015/02/06/knockoutjs-computed-equivalent-angularjs/

Explains how to duplicate the subscribe and computed feature in knockoutjs

var myViewModel = {
    personName: ko.observable('Bob')
};
myViewModel.personName.subscribe(function(oldValue) {
    alert("The person's previous name is " + oldValue);
}, null, "beforeChange");

This is what I found as result of my research (this is the AngularJs equivalent) Using the $scope.$watch method see the AngularJs life cycle https://docs.angularjs.org/guide/scope

$scope.myViewModel = {
    personName: 'Bob'
};
$scope.$watch(‘myViewModel.personName’, function(newValue, oldValue){
    //we are able to have both the old and the new value
    alert("The person's previous name is " + oldValue);
});

//knockout computed
var isVendorLoading = ko.observable(),
isCustomerLoading = ko.observable(),
isProgramLoading = ko.observable(),
isWaiting = ko.observable();

var isDataLoading = ko.computed(function () {
    return isVendorLoading() || isCustomerLoading() || isProgramLoading() || isPositionLoading() || isWaiting();     
});

This is the AngularJs Equivalent for KnockoutJs computed:

$scope.isDataLoading = false;
$scope.$watch(
    function (scope) {
        //those are the variables to watch
        return { isVendorLoading: scope.isVendorLoading, isCustomerLoading: scope.isCustomerLoading, isProgramLoading: scope.isProgramLoading, isWaiting: scope.isWaiting };
    },
    function (obj, oldObj) {
         $timeout(function () {
              //$timeout used to safely include the asignation inside the angular digest processs
              $scope.isDataLoading = obj.isVendorLoading || obj.isCustomerLoading || obj.isProgramLoading || obj.isPositionLoading || obj.isWaiting;
         });
    },
    true
);
Montes answered 7/10, 2015 at 23:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.