Reputation: 213
Can anyone suggest how do I create a service to over ride angular js default $watch and $digest loop?
My requirement is to $watch a scope object with a listener and the listener function should have 4 parameters, @param1 - newObject, @param2 - oldObject, @param3 - Exact attribute which changed, @param4 - the heirarchy of the attribute in that object to that attribute which changed.
required :-
$scope.$watch('objectName', function(param1,param2,param3,param4){
//log param3 and param4 in a stack for later use.
//Note:- I dont want to log entire changed object since its too big.
}, true);
NOTE:- Right now we can deep watch an object but the listener would provide us with 2 objects, old object and new object. All I want is to get the exact attribute changed.
Any help will be highly appreciated. Please refer the below link for my complete problem.
Upvotes: 0
Views: 809
Reputation: 171679
I think you can probably create an undo system that uses some sort of classification system for various types of undo along with a more event oriented approach. I focused on comments you made about iterating whole objects for each keystroke so will start there
I'm assuming that you aren't updating server for every keystroke on inputs in which case you wouldn't need to watch anything other than the specific input's key events while it is in focus. When you bind CTRL +Z to the document, do it in a way that nothing global happens when an input is in focus.
Following scenario is based on simplest UI action to track...update field only.
On focus of an input you would immediately take a copy of it's current model value, and store that as value to use for a complete undo of the ng-model later.
While in focus, CTRL+Z would be bound to that input and keystrokes events can be undone at very local level not impacting any need to watch at higher level. Unbind key events for that input on blur.
On blur of an input, you would then be able to $emit
an update event
that you would track as category like "field update". Send the old stored value , the object that contains the ng-model
and update category to a tracking service that listens for updates and pushes updates into an undo array.
When user now hits undo, service looks at update type and changes the value of the object associated to the field name stored and removes that last stored item from the queue
I did something similar to this using only jQuery for a UI that was set up to both create and manage a web page layout with absolute positioned elements throughout, as well as inserting and updating content.
I've only started on user level input that assumes no new data objects created or deleted. Those might be handled by $.watch watching array lengths. By only watching length you wont have to iterate over every property of every object contained to figure out what changed.
One helpful tracking property for all of this is the $$hashKey
property that angular gives to every object it touches in all scopes. Using haskey could help map array length changes to find differences. I haven't though all of this section through a lot yet.
Hope the event driven input tracking concept helps. At least at user input level it would cut out a significant amount of overhead using $watch
Also angular recently added a shallower listener $watchCollection
was added in 1.2. Haven't used it yet, but surely lightens overhead where it's use case might not warrant a full watch
Upvotes: 0