Vuex two way data binding with mapGetter helper - vue.js

So i know how Vuex implements two way data binding using set() and get methods on the computed property of the component. i.e return the store state or the relevant geeter in the get() method and commit a mutation in the set method which then mutates the state value. I also know how to use mapGetter() helper from Vuex to simply map Vuex getters to the computed property of the component.
My question is how to implement two way data binding when mapGetter helper is used without writing set and get methods for the computed property.

One of the best vue packages around
https://github.com/maoberlehner/vuex-map-fields
Taken from the package description
Enable two-way data binding for form fields saved in a Vuex store.

Related

Vue.js list rendering diff: "same object" vs "has same values"

I have just hit a reactivity problem in Vue.js (2.6.12) component. It was not re-computing and re-rendering after its props were updated. The issue is that the component is used in a list with v-for with a key. The key was not changing, but the object's data was changing i.e. it was the same object, but its data was different.
The key is used as an optimization for diffing the list in v-for so it can re-use and re-order the same components without re-creating them. My original key was the object's id and the solution is to create the key from the id and all the object's changing data. That leads to other issues, like losing the component's internal data state, which has no need to be stored in a Vuex store.
My question is, is there a way in Vue.js (maybe in v3?) to tell in v-for not only if the object is the same (via key using object's id) but also if the object has the same data? Which will update the prop and re-computed and re-render the component without losing its internal data?
Funny thing is that the component's props are updating, it just does not re-compute and re-render. Verified via the Vue Devtools in a browser.
EDIT:
Here is an example where the reactivity does not work. It is using a Vuex store and the array for v-for is a computed property, which joins two properties from the store.
I just figured out that the problem is the joining of the values via the map on line 67: o.number = extras[o.id]. After replacing this with Vue.set(o, 'number', extras[o.id]) it is working!
This problem doesn't exist as described. Here is a small example of object reactivity working properly: https://jsfiddle.net/sh0ber/04s1jt8g
I'm guessing, however, that you're encountering the change detection caveat and need to use Vue.set.
The reason is now clear with the code example: Your computed creates a new property (number) on each Vuex obj that's not defined in Vuex at the time you set objs. If you had initialized the objs to have a number property as well, you wouldn't need Vue.set. Another way to prove it is to set o.text instead of o.number and you'll see it's reactive without Vue.set
(Btw, it makes more sense to do this computation in a Vuex getter instead of a computed; getters are computeds for Vuex. It's nice to decouple the logic from the component, and imagine you needed the result in multiple components)

Using Intertiajs with Element UI

I am using Inertiajs
with Laravel and also trying to use Element UI components but as i use Menu component i am having following error in console, I just used example as given in Element Ui Components as i was testing.
I see 2 different errors in there, both of them are with props.
I assume your component is taking the route as a prop, and you are also using the route as a method, which you might have put inside methods: {} which is not allowed. Make sure you rename your method route to something else.
Note: As a matter of fact you can't have any data coinciding with each other. your props, data, computed props and methods all should have unique names.
You are trying to use v-model on the props directly which won't work in Vue. if the prop is a primitive (Number, String, Boolean etc). but you can pass Object or an Array which can hold a reference to the data. This is because reactivity in Vue can't keep track of props when passed as primitives.
More on prop mutations here: https://v2.vuejs.org/v2/guide/components-props.html#One-Way-Data-Flow

Pass entire data item vs just id as Prop in Vue list when using VueX

I have a VueX state that contains a list of items. E.g.:
{
operations: Operation[]
}
We need to display each Operation as an item in a list. So we have an OperationList component and an OperationItem component.
When it comes to rendering the list (v-for), would it be recommended to pass the entire item as a prop or just the id and have the OperationItem read the data from VueX?
Basically:
<operation-item v-for="operationId in operationIds" :id="operationId" :key="operationId"/>
vs
<operation-item v-for="operation in operations" :operation="operation" :key="operation.id"/>
I think it might be a preference choice but in my projects I usually pass all the prop of the components that way :
<operation-item
v-for="operation in operations"
:key="operation.id"
:prop1="operation.prop1"
:prop2="operation.prop2"
:prop3="operation.prop3"
/>
I'm not sure if that's a good practice or not but in this case, it's more flexible, you don't need to give a structured object for it to render, you just have to give it all it's properties.
A bit like for a class constructor, I would pass all the necessary parameters separately instead of passing them in an $option array or Settings class.
For some components, it also doesn't make sense for them to be aware of the store, they should juste be "stupid" rendered components.
I hope it's clear enough that you get my point !
I'd say pass the entire item. That way your component doesn't need to know where the data came from and you would be able to reuse the component in situations where the data didn't come from Vuex.

Problems with dynamically resetting object references in vuejs + vuex

I am coding a web app with vuex and firestore. In my main.js, under created(), I am calling a vuex action (defined in a store module) to query the firestore db and bind a certain subset of the objects in the collection to vuex, restricted programmatically. Summing up:
Let me simplify my question. Here is my structure:
<template> has a v-for list feeded by the computed() property below.
mounted () a function calling vuexfire action binding db RESTRICTED collection to state.ref
computed () some c. property returning a list of state.ref
methods () some method callong vuexfire action binding db UN***RESTRICTED collection relative to some WHERE TO parameter to state.ref
I want to be able to call the method sometimes to reset state.ref to the UNRESTRICTED set of db objects.
My problem is that calling the method triggers no error, but seems to fail: the computed() list returns no object.

Clarification about Vue Reactivity System

I always wanted to ask the following questions regarding the Vue Reactivity System.
I have read in Vue docs that it is recommended to keep the data of components as plain JS objects over being class objects. Same goes for individual properties of components data.
Why is this recommendation?
What is the problem with having data as instances of class objects?
What edge cases are caused by using getters/setters and methods inside of component data? (this is my main question here)
I have also another question about Vue Reactivity System.
Can I directly change component computed getters/setters and methods at runtime without having problems with Vue Reactivity System?
Are changed computed getters/setters still be cached and optimized?
Are changed methods going to be accessible from component template?
Can I add new computed getters/setters and methods at runtime? How?
Thank you very much!
Vue reactivity system (but i suppose i can extend it to all other reactive framework/lib/whatever) is just an implementation of the observer pattern . In the specific case, the observer function is fired when a property value (data, computed getter result, vuex state) changes. if the property is an integer and its value is 2, is easy for vue to check out that at some point of time it has become '3', after a comparison, fired with a mutation, a vdom change etc...and this is same for other primitive types. When structured object come into play, the comparison between values is still made, but this time the value will be a reference to the object. If the reference doesn't change, vue cannot know that something has changed, so just doesn't react....
if you set val 3 = 'foo' before and val 3 = 'bar' after, the 'val' array is still the same object in the same heap area, so you should clone it, or better use Vue.set()