Is it idiomatic to update a property of a prop, without an event? - vue.js

I pass the list of inputs as a prop,
v-for input in inputProps
v-model input.value
Should I be using events, instead of v-model?
Passing an event to manually update a property of a value in a list would involve
[index]'path to property', would it not?

It is idiomatic for props to flow down and events to flow up.
when the parent property updates, it will flow down to the child, but
not the other way around. This prevents child components from
accidentally mutating the parent’s state, which can make your app’s
data flow harder to reason about.
In the case of the v-for, yes, you would need to indicate the index of the item so the parent could take appropriate action on it. Depending on what you're doing, exactly, you might also catch the native input event in the parent and process it there, so that the child component is not involved in the transaction.

Related

VueJS - Update a parent computed property after a child component modifies prop data

I have a relatively complex API request object I need to make, with a large number of UI components responsible for updating different properties of the object.
I'm passing the basic request model as a prop from a parent component to its children, which pass it on to theirs (down several "generations").
At the parent level, I have a computed property that returns a field of this data model, and a watch on that computed property.
When a child component updates the property on the model, it successfully updates everywhere that has a reference to it, but the computed property on the parent fails to recalculate, and resultantly the watch never activates.
I'm guessing I've missed the point somewhere along here, but I can't think about how else to update without resorting to long event chains through the UI.. How should I be approaching this instead?
To anyone with a similar question - from my research it seems that modifying reference values on props is not the intended approach for VueJS. Which is a shame, because initially it seemed like quite a neat pattern.
I've implemented vuex now, which is working well, and avoids long lines of events going back to the original owner of the prop data.
IF you wanted to press it, then modifying references on the object itself will force updates down the chain. So (e.g.) if you wanted to update an array property of the prop data, then instead of "pushing" to it, you would replace the whole array object (causing other components with computed properties on that array property to recalculate). But again, not recommended.

Should I create the deep copy of Vue component parameter?

From Vue documentation:
All props form a one-way-down binding between the child property and the parent one: when the parent property updates, it will flow down to the child, but not the other way around.
However, if to pass the nested object or array from parent's data as child component's parameter and child will change it, the data of parent will change, too.
Ideally, good framework must take care about deep copying when required, but Vue does not.
The one of solution is creating the copy based on parameter's value. Should I do it?
I dont think creating copy is a good solution as far as i know.
The best practice for your task is to use .sync modifier!

Binding and custom event triggering on multiple level in VUE.JS

I am new in VUE.JS but i have finished some beginner courses of vuemastery. Though I know how to bind properties and how to emit custom events, I have a problem: I don't know how to make these things through multiple levels of components.
Let's say we have the following hierarchy:
I need to have control on the Home component's properties from the Elements and Input components from the bottom of the diagram. Right now I am emitting custom events from level to level from down to up, but it doesn't look like an elegant solution.
Is there a better way to do this? And of course when I change one of the properties from Input component it need to have effect on the properties in the Element components as well.
For example the Element components are elements having width and height calculated based on totalWidth property, which can be edited in the Input component. I'm having here a warn as well in the console: [Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders.
Use this.$root.$emit to emit event on the root component, that would then propagate event on its child components, regardless of depth level
I would recommend using vuex to manage the state of your application. Emitting events all over the place is not the most elegant solution.

Modifying child data from parent vue

I have a component that represents an option in a form, with data representing the currently selected option. There is a parent component which represents the full form, with a submit button and a reset button. I keep track of what options are currently selected in the form by emitting events from the child to the parent (this is important because the form updates dynamically)
.
I'm trying to design the reset button, which clears all fields in the form (sets the currently selected option to an empty string). I would need to modify the data of the child component. Should I do this using a Vue instance as a bus? That seems overkill. Is there a better way to design these components?
I think you want to use sync on the properties your passing into the child component. I use it to load my child component like:
<textbox :content.sync="new_comment" placeholder="Add a comment..."></textbox>
If you already emitting from your child component then changes to new_comment will automatically be passed through.
You can find a lot of ways to do this here.
For me, after a lot of playing around with props, i found that the best and safest way is to use this.$refs.
Even if you have more than one child component with the same ref name, you can go through each child with a forEach.
You can create a custom event to listen to the reset button on each form field. Check out the documentation for this here
Just put a method in the child, perhaps Clear, and call it from the parent. You use $refs in the parent to get to the children.

Vue: how to fire an event on a sibling component

In Vuejs, I have a parent component (P), and two child components (C1 and C2). The parent has objects which it shares with both child components.
Component C1 displays the objects (in a table) and component C2 lets the user modify the properties of the shared objects. Because the objects are shared as objects, I am updating their properties directly in C2, and the changes are displayed in C1.
The problem is that C1 is responsible for saving changes (by making an ajax call to the server). If the user modifies a property directly in C1, it triggers the change event, and an event handler makes the call. However if the property is updated in C2, the change event is not fired in C1, so the change is not persisted.
So, the question is, how do I fire a change event in C1, based on an event in C2? I have an event bus in place (in the root element). I could (perhaps) use an event listener to grab the element (e.g. with jQuery), and fire the event, but obviously this is not the most elegant way to do it. What's the Vue way?
I hope I understood you correctly: You're sharing an object between two children and you're manipulating that object in either child component directly?
That pattern itself is the problem. You don't want to manipulate state inside a child component. The clean way that'll keep the reactiveness is to bind the object via a prop from the parent to both child components. The children should never manipulate the state of the prop object (vue should actually throw a warning if you do that), they should only emit an event that they want to change the object by using:
this.$emit('input', newObject)
Now simply listen to that event in the parent and manipulate the object there, or, for simplicity you can also use the v-model pattern as described here.
<c1 #input="myUpdateFunction" />
or with the v-model pattern
<c1 v-model="mySharedObject" />
That's it. If your other component has the same object bound to it as a prop as well, it'll update its template automatically.
If you want an even more elegant way to share state for an entire application I suggest using Vuex.
Your question it is not too clear.However you can use eventBus and it will work fine.
My recommendation though,is to use vuex.
You can manipulate the store properties and whenever the properties changing,the changes will be reactive and applied to all components.
So if you have two components c1 and c2,and in store you have a property name: 'John Doe'.
If in c1 component you change the name like: this.$store.state.name = 'Jane Doe' this change has also take effect to component c2.
Of course it is not so simple.In vuex store you should have state,getters,mutation,actions and on your components to use computed properties to use fetch the store properties though getters.