According to Vue.js docs (Components: One-Way data Flow) I assumed that I'm not able to update parent's variable from child component.
How is it possible, that when I bind a variable to child component, it is updated without emitting any event?
Here is Vue SFC playground example.
How can I use a copy of variable in child component without propagating changes to parent?
Edit: I'm curious why the property userAccount in AccountPage.vue gets updated.
There's no v-model, no events submitted, yet it still gets updated.
Edit:
In AccountForm.Vue an reactive and mutable ref object is created when writing
const userAccount = ref ({..})
Changing the reactive object will affect the parent. If you remove the ref() you'll see that the parent isn't updated.
https://v3.vuejs.org/api/refs-api.html#ref
Old answer:
When you use v-model you create a two-way data binding. V-model is a shorthand for v-bind and input, that is you bind data to child via v-bind and receive data via input event that is emitted from child.
So,
<input v-model="searchText">
is the same as writing
<input
v-bind:value="searchText"
v-on:input="searchText = $event.target.value"
>
https://v2.vuejs.org/v2/guide/components.html#Using-v-model-on-Components
The example demonstrates the usage of v-model and as stated in the docs
Custom events can also be used to create custom inputs that work with
v-model. Remember that:
<input v-model="searchText">
does the same thing as:
<input v-bind:value="searchText" v-on:input="searchText = $event.target.value">
meaning it does fire an event
Related
I try to learn how i can create custom element for Shopware 6
although I cannot understand why we have to use the methods:
this.$emit('element-update', this.element);
in all SW Blocks?
All CMS element components should use the cms-element mixin. The mixin has a model for the property element which is bound to the element-update event. By emitting this event with the value you update the property, as if you were using a child component with the form input binding v-model. Since mutating props directly is considered an anti-pattern, this is a way to properly update it.
I have this component which has a v-model directive:
<my-component v-model="someData.someProp"></my-component>
Now, I'd like to be able to watch this piece of data inside the component and make changes based on this model changing via outside influences. So here's what I tried and it's not working:
watch : {
value (newVal, oldVal) {
// ...
}
}
It seems like it should work, or something comparable should be out there, but I just can't find it right now.
EDIT:
The most common answers I found and provided center on using the watcher to watch the data as if it's inside the parent component - but I'd like to watch it inside the child component without concern of what's going on in the parent.
I'm able to work around this by not using v-model and using simple named properties such as :my-data="someData.someProp" at which point I can successfully watch a myData variable inside the child component. I can also use #input to set the data back in the parent component if it's changed from within. But v-model is shorter and if there's a way to use that instead of a workaround that would be preferable.
From what I understand you are trying to pass a prop to your child component from your parent one and watch it in your child.
Assuming you have something like this in your parent:
<div>
<my-component v-model="someData.someProp"></my-component>
</div>
I understand you are getting undefined for that prop when you watch it, which is normal because you should pass it like this:
<my-component :myValue="someData.someProp"></my-component>
Then you should have access to the prop trought this.myValue.
If someData.someProp changes on the parent component it will automatically reflect on the child one.
Again this is what I could understand from your explanation and the amount of code you provided.
I have a very small checkbox component which I was trying to listen to via the #click event. But the v-model data updates 7ms later than the event callback. So I had to remove the #click listener and to add a computed property/method of the checked value and add a watch method for it to $emit the updated checked value. It works fine this way. But I just want to understand what's going behind the scenes. Can someone explain? Or maybe reference to a good resource on the net?
I also couldn't find the v-model methods in the Vue's source code. Where can I find v-model related code in the node_modules?
You should try using #change instead and then print it for testing. For Example:
<input
type="checkbox"
v-model="item"
#change="sendEvent"
/>
sendEvent () {
this.$emit('click', this.item);
},
I was just wondering if this is even possible, lets assume I have this code here:
<div v-for="tile in container" v-bind:class="proper-class">
<tile :tile='tile' #update="update-class"></tile>
</div>
I want to change the css class of the parent div when a variable inside of the component changes.
I know we should use $emit but we have a v-for in here, so we're creating multiple components, the $emit callback will update proper-class BUT this will update the css class of ALL the parents and not just the parent of the component that issued the update event.
What could be a solution to this?
Thanks in advance.
You can use the sync modifier to create a two way binding between the parent and child. It's nothing more than syntactic sugar for the child component emitting an event back to the parent with the desired payload.
this.$emit('update:propName', payload)
Vue sync modifier
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.