Skip to content
This repository has been archived by the owner on Apr 12, 2024. It is now read-only.

Add option to $watch to prevent recursive firing #834

Closed
ProLoser opened this issue Mar 28, 2012 · 25 comments
Closed

Add option to $watch to prevent recursive firing #834

ProLoser opened this issue Mar 28, 2012 · 25 comments

Comments

@ProLoser
Copy link
Contributor

When watching an object, if I make changes to the object from within the callback, this will trigger the $watch to be fired again after it's completion. This can occasionally cause recursive loops or redundant firing of the same $watch un-necessarily. It would be nice if we could pass an option (or imploy it by default) a way to ignore this. Other $watches can be fired, but the same $watch should not fire itself from it's own changes.

Example Use Case:

I have a complex reports & pagination page containing a lot of different filters
Filters
(cropped for privacy)
The filters are on the left and the result table is on the right.

Any time one of the filters changes, i need to fire an ajax request to immediately update the results table. I could watch all 10-20 of my individual filters, including the non-visible flags that might be associated with them (such as paging, limit, etc) but it's much easier to lump them all into 1 object and simply change the object to refresh the page.

For instance, if i want page 2, i simply do filters.page++

The problem is that some filters involve a 2 step process like selecting 1 filter might enable or render a second optional filter. Or perhaps certain options might select or deselect other filters. This actually seems like a fairly common scenario for moderately complex pages.

@IgorMinar provided this solution http://jsfiddle.net/IgorMinar/pn6Ur/1/ which still fires sibling $watches but does not allow a $watch to re-fire itself due to its own changes. I tried to think of any scenario where I would prefer the alternative behavior but I could only conclude that this is a much easier scenario to deal with.

I would like to propose adding it to the core. If there is a concern with overhead, perhaps make it an option for $watch at the very least

@vojtajina
Copy link
Contributor

Yep, if you change watched object from the watcher, it will always lead to infinite digest. That feels a bit like a dog trying to catch his own tail :-D

How about this http://jsfiddle.net/vojtajina/una6x/27/ ?
It can miss a watch, if both special watch and something else changes the object during the same digest, but that should not happen that often :-D

@ProLoser
Copy link
Contributor Author

Actually Igor solution proved to be better for me since I have a complex object. NY reason for posting is not because I need a fix anymore but because I think this solution should be in the core.

Sent via Hubroid

@btford
Copy link
Contributor

btford commented Oct 3, 2013

This is stale. If you think it's worth discussing more, let me know and I'd be happy to reopen it.

@btford btford closed this as completed Oct 3, 2013
@tommybananas
Copy link

Is a solution for this available yet? I really think it's worth the discussion.

I need to watch an array of objects and perform async tasks to some of the objects, so boolean flags will not work with my indeterministic work flow. I think being able to modify the watched object inside the callback would be an awesome feature.

@moroshko
Copy link
Contributor

Igor's link above doesn't work.
I think it worth a discussion.

@anri-asaturov
Copy link

I would be happy to see such a feature too.

@szymexpawlowski
Copy link

👍

@Webjin
Copy link

Webjin commented Jul 11, 2014

I worked out a different solution. If my watcher functions makes changes to the object it is watching I will tell the watcher the new value before it is triggered. This solves the recursion problem.

see: http://jsfiddle.net/webjin/TUh7K/

@Hengjie
Copy link

Hengjie commented Jul 27, 2014

I'd like to have this as well, as I'm trying to implement an undo function that can call itself recursively.

@luckylooke
Copy link
Contributor

+1

@vimes1984
Copy link

+1 for this... It's just drove me mad...

@schellmax
Copy link

+1

@schellmax
Copy link

i've worked out another workaround for the issue: http://jsfiddle.net/ubdr3ou5/
what i'm doing here is to remove the watcher when changing the object, and immediatly re-applying it. this works because "the listener fn is called asynchronously (via $evalAsync) to initialize the watcher." (See https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$watch)

@goerwin
Copy link

goerwin commented Aug 1, 2015

+1. This would solve many problems :). If you want to do dom manipulations using directives, often you want the directive to listen to a model update and then put it to 'default' value after doing your stuff inside the $watch method. But the moment I change the model to its 'default' value, it triggers the $watch again.

@codeofsumit
Copy link

+1

1 similar comment
@lucas-nadalutti
Copy link

+1

@AlinCiocan
Copy link

+1

Meanwhile, @schellmax 's solution is the most elegant one.

@calebjacob
Copy link

+1

1 similar comment
@iBasit
Copy link

iBasit commented Dec 27, 2015

+1

@icfantv
Copy link

icfantv commented Feb 17, 2016

Please do not only add +1 to issues - it doesn't add anything of intrinsic value to the conversation and serves to only clutter up the thread. OSS repos, in general, tend to frown on this practice.

@btford, would you guys be willing to please reopen this? I'm not really a fan of $watches but they do have their uses and there are certainly use cases where it would be beneficial to prevent a [user-created] $watch from firing on a model change. Thanks.

@icfantv
Copy link

icfantv commented May 16, 2016

@yaminm, please see previous comment re +1s. Also, GitHub now has support emojis you can click rather than cluttering up the thread.

@suiz0
Copy link

suiz0 commented Nov 18, 2016

+1

2 similar comments
@SyedFayaz
Copy link

+1

@bbeckSLS
Copy link

+1

@petebacondarwin
Copy link
Member

petebacondarwin commented Mar 5, 2018

We believe that one of $watchGroup or the private API $$postDigest should solve all the use cases in this issue. Please can you try out these approaches and comment here if your use case is not covered.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests