AngularJS: Differential REST update to avoid flashing? - javascript

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.

Related

Is there a way to preserve DOM state of the component after navigating away and back in Angular

After researching the issue for a few days I've seem to have reached a dead end.
I'm dealing with, what I assumed, was a fairly common scenario: After user navigates to a certain page and makes some changes (content of an input field, scroll through grid data or even changing some editable cell values ), he navigates to different page. When user returns to original page, all of the changes must remain the same.
Now, that means that cursor in the aforementioned input field must be in the same place, scroll position in the grid and changed cell values, as well as any other changes user made, must be preserved.
Solutions like storing data in localStorage, using services or even custom reuse strategy will not work, because saving that amount of information contained in multiple sub components will be impossible.
Currently, I'm considering DOM manipulation, where rendered template will be moved to a container in parent component in onDestroy hook, and returned later in onInit. That, of course, is a hail Mary attempt and feels very unnatural.
I'm hoping someone had (and solved) this problem before because, like I've mentioned, it seams like fairly common use pattern.
There is not much option to do this in angular compared to React,
What I can recommend you is, store all the data in "environment" as object and when user routes back populate data from environment.
Usually I do this, when a component loads I store values in objects. When on destroy called all this objects goes to the environment under a one main object.
When oninit calls I am checking if object has values and restoring the page to where it was.
I think you are looking for Angular RouteReuseStrategy, where Angular can cache some routes state, without destroying the component state, so when ever the user visit the same route a cached view will be used,
RouteReuseStrategy Docs.
You can also check this medium article, implementing the required methods
Medium
for small amount data we can use services or localstorage as you mentioned
for large amount data we can go with
NgRx
https://dzone.com/articles/angular-app-state-management-with-ngrx
I use a service for this purpose, saving and restoring the state of the page from an object stored in the service but i haven't been able to figure out how persist the result of a user file upload where i am holding a user uploaded image
Pending file upload to cloud storage. Any ideas on solving this helpful as it seems like the cached file is cleared by angular navigation process

Should updates to Firstore items in AngularFire be done through the AngularFirestoreCollection?

In my app, I have a list that requires an "or" condition. But, as the docs say:
In this case, you should create a separate query for each OR condition and merge the query results in your app.
As a result, in my service, I'm managing two queries and surfacing them as a single observable list to consumers.
The problem comes in with updating. I have the choice of doing extra work to match up the item needing update to the correct collection so I can do the following:
myCollection.doc(item.id).update(item);
or I can make this much more simple and just:
angularFirestore.doc(`path/to/${item.id}`).update(item);
I'm operating under the assumption that the first method will result in faster updates as I'm using the same reference that it would optimistically update instantly. And that the latter will be slower in that it would be more round about by updating the persistence layer and then the collection referencing getting notified about later (probably still a small time).
All of the above is assumption, however. I back this just with a few random instances where I've seen it take a second or two for an update or delete to show up in an other part of the view, but I haven't been able to actually inspect the process.
Does anyone know if the above is correct? Should I be doing the extra work to write through the collection references or does angularfire(and/or firestore) handle this and make them effectively the same operation under the hood?
AngularFire2 is a thin wrapper around RxFire, which itself is a relatively thin wrapper around the Firebase JavaScript SDK.
There should be no significant performance difference between updating a document through AngularFire or updating it directly through the JavaScript SDK. In both cases the majority of the time is spent in the JavaScript SDK, and on the wire between the client and server. For this reason I typically update directly through the JavaScript SDK, since it's often a bit more direct and the AngularFire abstraction has little advantage for me in write operations. Given that AngularFire is built on top of this SDK, it picks up the changes instantly even when they're not made through AngularFire.
If you have an instance where this does not seem to be the case, I recommend creating a question with the minimal, complete/standalone code that reproduces that problem.

browser performance impact of Knockout.js form with thousands of observables

I'm creating a form where the user will be able to add multiple rows with knockout.js, each row will have a 5 inputs and the user could potentially add hundreds of rows.
I want to use observable array and make it's properties also observable, for each input.
So it would be likely for some users there could be approx 5000 observable properties on the page.
Is there any performance issues which could arise from such an approach? Could is slow down the browser? And if there is, are there any methods to protect against it.
We're using controls with observables en observableArrays that hold 20k+ records clientside and we're now hitting a bit of a javascript/knockout wall. with 5k it still went pretty smooth but it also strongly depends on the client's browser/hardware.
1 major issue while updating all items in an obs. array is that if you'll iterate the change it would hang the page until the end of the iteration. You could use the apply method to get around that if logic allows that. Function.prototype.apply()
I'd say if you're 100% sure it won't grow over 5k, go for it, it'll work. But honestly nowadays you'd probably be better of leaving most of the data on the server and only retrieve what you need at that point.

How to track user changes in Vue.js?

I have a website built with Vue.js and I need to do an audit and, optionally, implement cancel functionality for this website so I'm looking for my options/best practices.
Let's say I have an Items array defined in data() so on created () I'm doing an Ajax request and pushing data into this array of items.
Now user loads this page and does his job which for me means he changed a few objects. Let's say each Item is a Customer object and it has First name, Last name, DOB and a IsActive boolean field.
I would like to give this user an option to revert specific item to the original state without reloading anything and when he hits Save I would like to know what was changed (so I can log this information)
Here are my ideas so far:
keep a copy of the original list of Items and do a diff later to see what was changed or use it to restore objects as needed
try to utilize watch() and keep track of changes. Perhaps, I can even store this information in the object itself.
leave a UI as is and on the backend (while saving or updating) re-read object from the DB and do the job there since it is the only truly secure way of doing an audit anyway.
What's the best way to track changes and/or implement both cancel and audit?
Maybe there is a Vue-way of doing this which I'm missing, because I just switched to Vue from a different framework.
Thank you! Any help appreciated!

Changes-aware list in angularjs

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

Categories