Is there a way to bind input to objects instead of single variables.
I know we can do this simple trick
<input v-model="name">
But the following doesn't work:
<input v-model="user.name">
That's what i was used to in Angular, is there a way to achieve this in vue.js?
you can bind directly to data, code as follow:
var demo = new Vue({
el: "#demo",
data: {
user: {
name: "please enter"
}
}
})
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<div id="demo">
<input v-model="user.name">
<span>{{user.name}}</span>
</div>
This works in Vue as well, make sure to define complete object in data which will make it reactive, Here is a working fiddle.
Vue Code:
var demo = new Vue({
el: '#demo',
data: function(){
return {
user: {
name: 'This is working fine'
}
};
}
})
Related
I have question related to data of Vue.
I created data with an empty object.
data(){
return {
myObj: {}
}
}
and function like this:
methods: {
changeMyObj() {
this.myObj.newKey = 'aaaa';
}
}
Then I show it on template by click
<a #click="changeMyObj">Click change</a>
{{myObj.newKey}}
With this click, the nested key is not rendered on template. How can I resolve this issue?
Note: I do not meet this issue with Vuex or state of React.
This happens because of vue.js reactivity. In fact, here you are modifying a value that was not declared when the component mounted and Vue cannot track the changes.
You can update values by using the Vue.set method which allows Vue to track the data.
Vue.set(this.myObj, "myKey", "Hello world")
You can also make a deep copy of the object instead of just adding the key.
This can be done using the spread operator.
For example
this.myObj = {...this.myObj, myKey: "Hello world"}
Here is a small example using the two versions
new Vue({
el: "#app",
data: () => ({
myObj: {}
}),
methods: {
addKey(){
this.myObj = {...this.myObj, myKey: "Hello world foo"}
},
addKey2(){
Vue.set(this.myObj, "myKey", "Hello world bar")
},
},
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
{{ myObj.myKey }}
<button #click="addKey">Add key</button>
<button #click="addKey2">Add key 2</button>
</div>
I found the solution for this.
this.myObj = {...this.myObj, newKey:'aaaa'}
I do not think it is solution while it has no difference with:
this.myObj['newKey'] = 'aaaa';
or
this.myObj.newKey = 'aaaa';
If someone can explain why please let me know. Thanks
Correct way to assign a new property in an existing object is Vue.set(this.myObj, 'newKey', 'aaaa') to make it reactive instead of this.myObj.newKey = 'aaaa'
Demo :
new Vue({
el: '#app',
data: {
myObj: {}
},
methods: {
changeMyObj() {
Vue.set(this.myObj, 'newKey', 'aaaa')
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<button #click="changeMyObj">Click change</button>
{{ myObj.newKey }}
</div>
In order to ease the styling of my page, I'd like to create a bunch of mini components like, and exploit how attributes are merged in VueJs. So for example, here is a minimal js file also hosted on this JSFiddle:
Vue.component('my-button', {
template: '<button style="font-size:20pt;"><slot></slot></button>'
})
var app = new Vue({
el: "#app",
data: {
message: "world",
},
methods: {
sayHello: function () {
alert("Hello");
}
}
})
and then in my html I just want to use <my-button> instead of button:
<div id="app">
Hello {{message}} <my-button #click="sayHello" style="color:red;">Style works, but not click</my-button> <button v-on:click="sayHello" style="color:red;">Both works</button>
</div>
Unfortunately, it seems that attributes are merged, but not listeners, so it means that I can't do v-on:click on my new button... Any way to make it possible?
Thanks!
-- EDIT --
I saw the proposition of Boussadjra Brahim of using .native, and it works, but then I found this link that explains why it's not a great practice and how to use v-on="$listeners" to map all listeners to a specific sub-button. However, I tried, to just change my template with:
template: `<button style="font-size:20pt;" v-on="$listeners"><slot></slot></button>`,
but I get an error:
Vue warn: Property or method "$listeners" is not defined on the instance but referenced during render. Make sure to declare reactive data properties in the data option."
Here is the JSFiddle.
Your fiddle didn't work because you were using an old version of Vue, $listeners was added in Vue 2.4.0.
Here's a demo:
Vue.component('my-button', {
template: '<button style="color: red" v-on="$listeners"><slot/></button>'
})
new Vue({
el: '#app',
methods: {
sayHello() {
alert('Hello')
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<my-button #click="sayHello">Custom Button</my-button>
<button #click="sayHello">Ordinary Button</button>
</div>
I have this
<template id="vButton">
<button v-bind:title="name">{{name}}</button>
</template>
<div id="app">
<ti-button></ti-button>
</div>
js
Vue.component('ti-button', {
props: ['name'],
template: '#vButton'
});
var vm2 = new Vue({
el: '#app',
data: {
name : 'hi'
}
});
I want the button to have innerText and title attribute to say 'hi'. But it does not. Does anyone know why?
Ref: https://v2.vuejs.org/v2/guide/components.html
Thanks
Vue.component('ti-button', {
props: ['name'],
template: '#vButton'
});
var vm2 = new Vue({
el: '#app',
data: {
name: 'hi'
}
});
<script src="https://cdn.jsdelivr.net/npm/vue#2.5.17/dist/vue.js"></script>
<script type="text/x-template" id="vButton">
<div>
<button>{{name}}</button>
<button>{{$root.name}}</button>
</div>
</script>
<div id="app">
<ti-button name="first_button"></ti-button>
</div>
UPD:
Do you mean you don't see this?
You are doing things mostly right, you just need to pass your data to your prop using a v-bind:
<ti-button v-bind:name="name"></ti-button>
Static values can be passed without v-bind but for dynamic values like you are attempting to pass you need to bind the prop. Check out the static/dynamic prop documentation for more information.
And here is a working demo: https://codepen.io/egerrard/pen/qJpzMQ
Please have a look at example
http://jsfiddle.net/g77uv054/
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/0.10.5/vue.min.js"></script>
<div id="todo">
<h1>My Test</h1>
Sample 1 <span v-text="form.title"></span>
Sample 2 <b><span v-text="'' +form.title"></span></b>
</div>
<script>
var form = new Vue({
data: {
title: "My Form"
}
});
var app = new Vue({
el: '#todo',
data: {
form : form
}
})
</script>
For some reason, binding in "Sample 1" does not show nothing and Sample 2 works fine. Can someone please explain why adding '' to string makes any difference ?
I don't believe you can use a vue instance inside another vue instance.
Normally you either define form as a component or as a class.
I attached fiddles for the two approaches:
http://jsfiddle.net/DarkFruits/g77uv054/1/
<div id="todo">
<h1>My Test</h1>
Sample 1<span v-text="form.title"></span><br/>
Sample 2<span v-text="'' +form.title"></span>
</div>
class formĀ {
constructor() {
this.title = 'My Form'
}
}
var app = new Vue({
el: '#todo',
data: {
form : new form()
}
})
http://jsfiddle.net/DarkFruits/g77uv054/2/
<template id="my-form">
<span v-text='title'></span>
</template>
<div id="todo">
<h1>My Test</h1>
Sample 1<my-form v-bind:title='title'></my-form><br/>
</div>
Vue.component('my-form', {
template: '#my-form',
props: ['title']
})
var app = new Vue({
el: '#todo',
data: {
title : 'My Form'
}
})
Edit:
FYI, in the second fiddle I removed vue as an external resource and added it in the javascript settings. This also gives you better error messages in the console.
js 2.0 and I'm stock in dynamic props.
See Image attached
My HTML code like this:
<div id="app">
<div>
<input v-model="parentMsg">
<br>
<child v-bind:my-message="parentMsg"></child>
</div>
</div>
My Component code:
Vue.component('child', {
props: ['myMessage'],
template: '<p>{{ myMessage }}</p>',
})
var app = new Vue({
el: "#app",
});
I know that data should be a function but how I'm going to implement it. I get this error on the console.
Property or method "parentMsg" is not defined on the instance but referenced during render
I think message is clear. "parentMsg" is not defined on the instance. You have to define parentMsg at parent level. like following:
var app = new Vue({
data: {
"parentMsg": ""
}
el: "#app"
});
You can have a working fiddle here.