0

In my controller I have some scope variables like

$scope.searchText = "abc";
$scope.currentPage ="1";
$scope.sortBy ="dateTime";
$scope.sortOrder="reverse";

$scope.columnSettings = [
                        {"name": "dateTime, 
                         "displayName": "Datetime",     
                         "filterText": ""
                        },
                        {"name": "name, 
                         "displayName": "Name", 
                         "filterText": "xyz"
                        },
                        {"name": "id, 
                         "displayName": "ID", 
                         "filterText": ""
                       }]

I need to watch on all the $scope variables and "filterText" key of the objects in "columnSettings" array.

I am using

$scope.$watchCollection('[searchText, sortBy, sortOrder, currentPage, itemsPerPage, columnSettings]', function(newVal, oldVal){
                    // Ignore initial scope change
                    if(oldVal && newVal !== oldVal){

                        // watch is triggered for changes in searchText, sortBy etc...
// but not for "filterText" change in columnSettings
                    }
                });

My question is

a) watch is triggered for changes in searchText, sortBy, currentPage etc...but not for "filterText" change in columnSettings. How can I solve this?

b) also, I want to trigger watch only on "filterText" key change and not on any changes to the other keys.

Any help is greatly appreciated.

4
  • 3
    You really shouldn't have to watch all of these. If you bind them to a template a watch is created for you anyway (this is two-way binding). I'm curious to know why you think you need to watch everything like this. :) Commented Feb 23, 2015 at 23:09
  • All these values are bound to template can be changed by the user. For every change, I need to manipulate couple of values and make http.get call to the backend. Is there a better way to do this? Commented Feb 23, 2015 at 23:15
  • 1
    For "every key press in searchText" you are going to make an http call? This doesn't sound very nice. If you trigger the http call somehow (like with a button click) maybe that is a better place to arrange the data before calling the server. However, without more code (like the HTML template) it is impossible to comment further. Commented Feb 23, 2015 at 23:17
  • Yes, that's the requirement I have. Need to make $http.GET for every change. Commented Feb 23, 2015 at 23:20

3 Answers 3

2

I'm guessing filterText is populated by an input on your web page. In that case you should use an ng-change attribute in the template (on each input), and this can trigger an event handler on your $scope. As Davin noted in the comments, what you are trying to do is usually a bad idea (except maybe in some rare cases I cannot picture).

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

2 Comments

Yes, ng-change makes sure that the dirty check is only triggered by a UI change and therefore doesn't involve the digest loop continuously.
If your event handler is to fetch data on a server, you'll also want to use throttling (typically: only call the server after the input has not been edited in the last second)
0

If you only want to get notified on changes on one of the object's properties you could simply add $watch as follows:

$scope.$watchCollection('columnSettings', function (obj) {
    // handle obj.filterText change
});

You can not add columnSettings to $watchCollection as it's a collection itself, so it unfortunately has to be watched on it's own.

4 Comments

columnSettings is an Array. Can $watch be used this way ? That seems a bit funny (is this watching all filterTexts inside the objects in the array ?)
I was hoping to have one place where I can watch all the variables and avoid not having both $watchCollection and $watch. Also, columnSettings is an array. Not sure if I can use columnSettings.filterText.
@user3701057, one thing to keep in mind with Angular is that using $watch ends up being quite expensive when they all add up. We should avoid using it whenever possible. Angular already adds some $watch for you through the template binding.
Yep folks, you're right. @user3701057 i don't think that you can reduce it to one watch call. Check my edited answer. ;)
0

I ended up doing like this.

$scope.$watchCollection('[searchText, sortBy, sortOrder, currentPage, itemsPerPage]', function(newVal, oldVal){

});

and use $watch for columnSettings and watch only "filterText" changes

$scope.$watch(function($scope) {
                    return $scope.columnSettings.
                        map(function(obj) {
                            return obj.filterText
                        });
                }, function(newVal, oldVal){
});

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.