I use LocalStorage to persist some content of my Vue3 app. Today, I just write to LocalStorage any changes in the content I want to preserve and read from that contact in specific cases (an interval, or some other trigger).
The last part is not optimal because I need to have complex logic about how to make the LocalStorage → app update (LocalStorage can be updated by "something else", and this update should reflected in the app)
The solution would be to bind the content of LocalStorage with a reactive variable, which would natively bring two advantages:
any change in the variable or LocalStorage is reflected in the other one
changes are naturally persistent
Question 1: Is this something that is possible (Vue3 and a modern browser)?
Question 2: I recently heard about FileSystem which seems to be a possible alternative to LocalStorage, but I do not know it enough to assess whether it could be more suited to solve my problem?
Note: there is a similar question (How to make data from localStorage reactive in Vue js) but it does not cover Vue3 and the possible use of FileSystem. The answer is basically "it is not possible natively. I will mark it as a duplicate if this is still the case.
If I understand your question right, if you are updating localStorage at one place, it should also update on other pages.
I never tried this, but I can think of two approaches.
where you can listen to storage event https://developer.mozilla.org/en-US/docs/Web/API/Window/storage_event
this has some limitations, please check.
Create an Event and attach it to the window & whenever you are updating localStorage dispatch the custom event and on listening to the custom event, fetch the data from localStorage.
Related
I'm working on a vue app that uses vuex and gets objects from an api. The tables have paging and fetch batches of objects from the api, sometimes including related entities as nested objects. The UI allows some editing via inputs in a table, and adds via modals.
When the user wants to save all changes, I have a problem: how do I know what to patch via the api?
Idea 1: capture every change on every input and mark the object being edited as dirty
Idea 2: make a deep copy of the data after the fetch, and do a deep comparison to find out what's dirty
Idea 3: this is my question: please tell me that idea 3 exists and it's better than 1 or 2!
If the answer isn't idea 3, I'm really hoping it's not idea 1. There are so many inputs to attach change handlers to, and if the user edits something, then re-edits back to its original value, I'll have marked something dirty that really isn't.
The deep copy / deep compare at least isolates the problem to two places in code, but my sense is that there must be a better way. If this is the answer (also hoping not), do I build the deep copy / deep compare myself, or is there a package for it?
It looks like you have the final state on the UI and want to persist it on the server. Instead of sending over the delta - I would just send over the full final state and overwrite whatever there was on server side
So if you have user settings - instead of sending what settings were toggled - just send over the "this is what the new set of settings is"
Heavy stuff needs to be done on the server rather than the client most of the time. So I'll follow the answer given by Asad. You're not supposed to make huge objects diffs, it's 2022 so we need to think about performance.
Of course, it also depends of your app, what this is all about. Maybe your API guy is opposed to it for a specific reason (not only related to performance). Setup a meeting with your team/PO and check what is feasible.
You can always make something on your side too, looping on all inputs should be feasible without manually doing that yourself.
TLDR: this needs to be a discussion in your company with your very specific constrains/limitations. All "reasonable solutions" are already listed and you will probably not be able to go further because those kind of "opinion based" questions are not allowed anyway on SO.
I'm working on a narrow cast that displays an amount of tickets (an integer with the total added up to eachother) from a 3rd party API. I want to display a notification when this amount increases. I've read about mutationobservers, and that they are good for doing similar tasks like when something gets added or deleted.
The app has a Vue frontend, and a Laravel backend which does the requesting/authenticating. The index blade loads in a Vue component which contains the other components (and distributes the data from the API to child components).
I'm not quite sure wether mutationobservers are good for this specific job, though. Googling really didn't give me great alternatives.
In conclusion, I want to know if mutationobservers are the right tools for this task and what property would work. Better suited alternatives are also welcome.
Using vue, you can use a watcher function to watch for changes in a particular variable (amount). Mutation Observers only watches for dom updates, it won't give you what you want
I'm trying to update a web app that uses the jQuery.data() function to store information. The update involves refactoring the interface so that there are separate windows for different types of information rather than using just divs on the same page. Because of the way some plugins work the code that calls them has been moved into different windows to run in the window where they are needed. However, many of the callbacks used by these plugins use .data() to find stored information, but then code that sets the data stored by .data() is in the parent window, and it does not seem to attach the data to the DOM, it stores it somewhere attached to the window, so in the child window the callbacks can no longer find the data they are looking for.
Will it work using call(parent, DOMelement.data);? And is there possibly a tidier way of dealing with this?
Thanks in advance!
Thanks for all the suggestions. This wasn't using cookies because the information doesn't need to be stored beyond the current session. All of the interaction is done via javascript, there are no server requests until you save at the end. The windows that have to communicate are all open at the same time, hence the call() suggestion. I ended up solving this using .prop in place of .data as the syntax and functionality was almost identical. This directly associates the data with the DOM on the relevant window. $_SESSION only works when each page is requested from the server.
So, if you are trying to store information that needs to be accessed by multiple windows simultaneously or without a page refresh you can use the jQuery .prop() function to attach data to the DOM. .attr() could also work, but .prop() allows you to directly access values using . notation.
The .data functions are designed to prevent circular references but they store the information somewhere that means you can't access it without using .data which stores info separately for each context.
I want something like document.referrer. But since I'm building a single page app, with backbone and pushstate, the value is "".
How can I get something like history.prevState().url.
EDIT: I do not need the event. I want to access info of the previous state anytime/anywhere I want.
Perhaps you could simply store the last state in the new state object.
history.pushState({
lastState: 'some state'
}, '', 'newpage.html');
console.log(history.state.lastState); //some state
If you are building a single-page application, even if there are no standardization on how the state transition is initiated you could probably manage to intercept all of them by listening to the popstate and the onhashchange events.
You could then just push every states encountered in an array and store a serialized version of it in the localStorage. That would allow you retrieving any previous states. However, this collection will grow so you would have to make sure that you control it's size. You could also simply keep the last state instead of all of them.
However, it would definitely be better to establish a standard across modules. Not only it would make accessing the previous state easier, but it would also be easier to maintain and more flexible in terms of future changes.
I have a rather complex web page with various tabs, forms, radio buttons, drop downs, etc. It's all bound using Knockout.js to a very complex JavaScript object that was loaded via an AJAX call. Of course the user can muck with stuff to their heart's content, at which point they hit a Save button to persist all their changes back to the server.
I'm in the process of coming up with a good design to track exactly what was changed on the page so I can implement saving. So, I've come up with a few possible implementations.
Option 1) Just send everything back and let the server sort it out: With this method, I'd let Knockout just update the data source. The Save button would call .toJS() and send that data back to the server. Pros: It's super easy, and takes very little work on the client. Cons: The server doesn't really know what changed and has to either load the data from the database to compare, or just save all the fields again. These fields come from multiple tables and have complex relations. It also treats the entire document as a single atomic unit. If someone else changed Field A and you changed field B, one user is going to lose their change.
Option 2) Use JavaScript to compare the original data and the current data: Using this technique, when the user clicks on the Save button, I would systematically compare the original data and current data and generate a graph of changes. Pros: This would ideally result in a compact graph of exactly what the user changed, and could even no-op if nothing was changed. Cons: The data I'm binding to is complex. It consists of strings, arrays, objects, arrays of objects, arrays of objects with other objects, etc. Looking for changes would be a rather complex nested loop.
Option 3) Track changes as they are being made in the UI: I would have to observe changes as they happen, and keep a delta as UI elements were changed. The Save button would simply send that change graph to the server if it had any pending changes. Pros: No need to compare two huge JavaScript objects looking for changes, but still has all the benefits of option 2. Cons: Knockout doesn't appear to have a standard way to listen to all changes using a single event handler. I believe I would have to resort to binding to all the UI elements, or creating custom bindingHandlers in Knockout to implement this real-time change tracking.
My Question:
My question is mostly for Knockout.js experts. Is there a standard approach, or recommended guidelines to solving this obviously common scenario? Is sending back all the data, even stuff that hasn't changed, a common design? Or are people implementing custom change trackers? Does Knockout provide any sort of framework that eases this requirement?
Update: Found this thing, not sure if it could be useful or if anyone has any feedback on it.
If it's a question of enabling/disabling the Save button, allowing the user to navigate "from" that page/state, then you can check with the https://github.com/CodeSeven/kolite
check the knockout.dirtyFlag.js
Hope this helps.
Edit: remember that you should "never" trust the data coming from the "UI". The real comparison and validation, ultimately goes in your "controlled" environment within the server.
What I would probably do is take option 2 - the comparison itself can be as simple as stringifying the JS object and comparing it with a cached version of itself.
A few other options are discussed here.
P.S. Maybe ko.mapping can help you manage this monster of a JS object?
I wrote a change tracker extension for knockout that Pete Smith greatly expanded on...
Take a look here:
https://roysvork.wordpress.com/2014/01/12/tracking-changes-to-complex-viewmodels-with-knockout-js/
It works on the principle of extending the observable to track initial state vs. changes the user has made on the client. I think this works really great and can give users real-time feedback to know what they've modified. In practice, we actually implement a save panel that shows all pending changes and even lets them undo individual changes, all by using the change tracker's reusable capability.
ko.extenders.trackChange = function (target, track) {
if (track) {
target.isDirty = ko.observable(false);
target.originalValue = target();
target.subscribe(function (newValue) {
// use != not !== so numbers will equate naturally
target.isDirty(newValue != target.originalValue);
});
}
return target;
};