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!
Related
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
I'm facing a stupid problem.
In a web app (my stack is vue + vuex + vue-router) I'm totally unable to synchronize my store state with the page the user is viewing.
When a user triggers the back or forward button, it triggers the same onpopstate event that gives absolutely no information about "direction" or the number of page. Only the array key in the state object seem to be barely workable (saving it when going to new places and then guessing where the user went onpopstate) but I don't even know where the "door" corresponding for "the key".
So from there I thought about manually tracking the history state key and guessing where the user has been but I guess it wouldn't be cross-compatible, and also it's heavy code to lift.
Here is my question: Am I missing some key element in the html5 API, how could I do (and keep code/logic minimalist)?
Thank you in advance!
EDIT: renamed the title and added info
EDIT2: vuex-router-sync is inappropriate since it only provides route info on vuex side and does not really sync router state and store state...to bad
P.S.: please don't c/p definitions, read carefully, think
onpopstate provides the state object in event.state correlating to the respective place in history of your application.
Write your application so that providing this state object encompasses the entire state of your application, regardless of time. I recommend you read about State pattern, and understand what "state" means, e.g.
the particular condition that someone or something is in at a specific time.
The implication I'm making is that you should not need to know the relative location in history your application is in, because event.state should be all your application needs in order to determine what to render.
We are creating an React application, which has lists with basic CRUD operations in multiple places. The basic example, of course is:
Fill input to have name for the item, click submit
Send request to server
Fire callback on success
Update list with item using response data
I want this operation to be fully optimistic:
Fill input to have name for the item, click submit
Update list with item using given name
Send request to server
Fire callback on success
Update item in the list with response data
So, in the first example we would simply make an item out of the response and update app state. In second example we make the item and when response comes back, we need to find the right item.
The items have id's when they come back from the server. If item has an id, updating, of course, is very simple. The problem with the second example is, that we don't know the backend id for the item.
I have personally solved the issue by giving a frontend id, which is only used for referring to right element on callbacks. Me and my colleagues don't really like the approach, because it is a bit... messy.
What would be an appropriate, efficient pattern for handling this kind of case?
First of all I am glad you have found a place for optimistic UI in your project ;)
Concerning your question: what you're doing is indeed a totally valid solution. Setting frontend ID is totally fine. But I, in the similar cases, do it a bit differently. Instead of updating the item on your last step, I would again update the whole list. The point with this is that you get the response with the full list anyway so why not to use it? It solves two issues:
no need to rely on frontend ID or any other way of marking/storing the item for that matter;
in case there is a possibility of multi-threaded updates to the list from different clients (in the timeframe between your client gets the list and clicks submit), updating the whole list will keep it up-to-date much better;
Note though that updating a large list might have an impact on performance after all. At the same time, you don't need to parse the list after getting the response so you save some time here.
So compare both solutions and make a decision based on the best possible outcome for your users ;)
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 was assigned a task to modify a custom joomla component's search functionality that is only done through ajax, and doesn't have any url/query string handling, so the users cannot go to previous searches through browser back button as well as it is impossible to bookmark a specific search query for sharing etc.
Currently, the search is done by a jquery script that collects all of the form elements' selected values on the page and sends that (with ajax) to a separate controller task (ajax.ajaxSearch) which echoes json with all available results. In the view then there is a code that parses that json and builds an ul list for all items. And the url stays always the same (it's the homepage currently).
What I was thinking to do is in the script that receives the items from the model, to set some history handling ie:
var params = '&beds=2&fireplace=1&kitchen=1';
history.pushState(params, null, '?task=search'+params);
With this I will have urls like www.mysite.com/properties/?task=search&beds=2&fireplace=1&kitchen=1 with back button working and params will be saved in the window.state object which hopefully I could use to re-run the ajax search query with the selected params. And I know I will have to code couple of methods that will take care of such routes like www.mysite.com/properties/?task=search&beds=2&fireplace=1&kitchen=1 to be properly handled when accessed directly.
What I want to know is the approach described above feasible to go after? Is there a maybe better solution that could solve this problem more elegantly and easily ? What would your approach be if faced with similar task?
You can try some history frameworks but anyway if you want the back button to work you need an anchor to move back and foward. I don't see why it shouldn't work.