I'm doing some work on existing angularjs code, and I have something of that sort: I have a list of objects on the client side, which I transfer via a put request to a server side.
The existing code simply takes the list of objects in the $scope and puts it in the json as is.
I want to implement a mechanism where only the objects that have been changed since some event would be sent.
I can do that hardcodedly and save another list of objects and clear it when I submit the changes, but I want something cleaner - f.e, a Changes aware list,
Then, I could do something in the sort of list.changedObjects.
I couldn't seem to find anything like that from basic research, so I was hoping you guys would know something about it.
I feel this is a use-case of Observer pattern. https://github.com/melanke/Watch.JS has an lib/example to observe changes in javascript object. Then you can trigger an event in Angular to do your job accordingly
http://jsfiddle.net/2zT4C/23/
$watch helps to listen for $scope changes
AngularJS can then check the value returned against the value the watch function returned the last time. That way AngularJS can determine if the value has changed.
$scope.$watch('list', $scope.sendNewList, true);
it will will update innerHtml if new value of object is not equal to old value of object i.e if it has been changed.
For detailed info check this - $watch() or $watch
AngularJS watch array of objects for data change
Related
i just starting to learn angular JS a month ago. And found something difficult.
I have the following plunker http://plnkr.co/edit/nsu6Pj?p=info
<input id="tags" ng-keyup="complete()" ng-model="data"/>
selected = {{data}}
As you can see, there is a list of available tags. i want to pass the selected value in the index.html page to next.html page by clicking the button.
Actually i want pass not just 1 parameter. Just like md-autocomplete in angular material.
Here is the image for example parameters i want to pass
I hope you guys can help me :) Thanks.
Well, if you're passing multiple values, you can choose to hold your values in an array or an object. I personally would just set your complete function to push the values to an array.
Now, as for exchanging data - You have three options that I can think of:
create a service that allows controllers to communicate with each other. You could then use that service to set a variable in one controller (holding your tags) and then use same service in a different controller to get the value.
broadcast an event in one controller with $rootScope.$broadcast and then listen to the event with $rootScope.$on
Save the data to the browser's cookies with angular's $cookieStore.
Now the way your stuff is actually set up you're instantiating a new module and controller in each page so options 1 and 2 are out. Here's how I set up saving the values in the cookies.
I have an array of Device objects which is fetched regularly from a REST server using $resource. Whenever this happens, the UI gets "reloaded", meaning the ng-repeat for this device array is executed again. The DOM update is annoying, because it screws up the current user interaction with devices. Instead I want the newly fetched Device array to update the existing one only WHERE stuff has changed. So if I get a fresh Device array, and there was only a name change in one of the 10 devices, then only that single data binding for that name of this one device shall incur a DOM update.
I couldn't find a method of doing this. Since it seems a common problem to me, I wanted to ask before writing my own "mergeUpdate" method which basically just does a deep-compare-replace operation and only write the things into the existing binding that actually have changed on the server-side.
Note that each device is uniquely identified by an id, thus this algorithm is possible at all. Without this id field it would not work (probably the reason why there is no generic method supplied with AngularJS).
Actually, angular.equals is a partial solution. Now I want something that can at least transfer modified properties too, without invalidating the whole array.
Thanks!
What you are looking for is "track by" for ngrepeat. In your case,
<div ng-repeat="item in items track by item.id"></div>
With this, ngrepeat will keep track of existing items and not rerender them. The merge logic is internal to ngrepeat.
I have an object:
NAMESPACE.SOMEOBJECT.VALUE = 0
Some other foreign script owns and changes that value based on an event that I don't have access to. I know that the value is changed by different events on different pages. I can't edit the .js that controls that object. Does anyone have any idea how i can listen to that specific object and then run a function if that value changes?
I cannot add a new library or any external script. I'm using Backbone, require.js and jQuery.
If I were to use a backbone.model and add a reference to this object in my model, and then in my view I were to listenTo my model, would that tell me if that object has been updated? If so, sow would I go about doing this?
I DO have access to an ID on the page that allows me to access a DIV that has the value that I'm looking for. Keep in mind, that every time my object value updates, I need to know if it's been updated.
Unfortunately there's no way to 'add a reference to this object in the model' as this is just another way of saying that something should 'listen' for changes on the object. In order for a model to trigger a change event, one of its attributes has to change and this cannot happen by any means other than calling the model's set method or (re-)fetching (changed) data from the server-side.
How about polling the object instead of listening for an event? You could use setInterval to periodically query the relevant value and track its changes. In the event that the value has changed you can invoke the desired behaviour.
You could also wrap this functionality in a Backbone model if this is a good fit for your app's design: In the model's initialize / constructor use setInterval to start polling the value periodically and use set to copy it onto one of the model's attributes. Backbone will take care of tracking state for you and the model will trigger a change event if (and only if) the value changes.
Hope this helps.
I want to get the name of a model going all the way back to the $rootScope. So, something that looks like: $rootScope.ctrlScope.foobar.modelName.
I want it to be able to update that model from anywhere and to take into consideration variable model names like: box[$index].value. Where $index becomes 0.
The reason I want this is because I'm creating a directive that gets this new model name and it's value and sends it up via a socket to NodeJS where it comes back down to another user and updates the same model on their end.
The way I tried doing this before was getting all of the use cases and designing special callbacks for each one. This was super buggy and obviously not very scalable. But tying each data / template change to a specific model and simply sending up that model change seems like a much more elegant solution.
I want to sync changes to the server automatically. Currently I'm detecting changes in a scope.$onEval handler by JSON serializing the application state and comparing that to a previously serialized copy, using diff-match-patch.
I was wondering if AngularJS has anything built in to make this more efficient.
You could use multiple $watch'es instead of a single $onEval (note that $watch can take a function as an argument instead of a string/expression, and in version >=0.10.0 the watched values are compared using angular.Object.equals). Other than that, I don't know any AngularJS mechanism that would be useful for this.
I am working on something similar. Like #psyho suggested I am using $watch to catch the changes.
scope.$watch("dataObject",function (newValue, oldValue) {
//calculate changes
//send the changes to the server
});
I then use the logic from jquery diff to calculate what changes were made.