Pass object as props on Vue - javascript

How do you go on passing objects as props on vue? I would imagine this would be a simple task but apparently not.
I have the following code on a .vue file:
// register the child component
Vue.component('component', {
props: {
data: {
type: Object
}
},
template: '<div>Data: {{data}}</div>',
mounted: function () {
console.log(this.data)
}
})
new Vue({
el: '#example'
})
<template>
<div id="example">
<component :data="msg"></component>
</div>
<template/>
<script>
export default{
data(){
return{
msg:{}
}
},
created(){
this.msg = { x: 6}
}
}
<script/>

Vue.component('component', {
props: {
data: {
type: Object,
default: () => ({
x: Number
})
}
},
template: '<div>Data: {{data.x}}</div>',
mounted: function () {
console.log(this.data)
}
})
new Vue({
el: '#example'
})
try this you use x but you never put default in it

Related

vue - data reference another data

I very new in vue, how can mylist random, can get the same value from somerandom
export default {
data () {
return {
somerandom:"foo",
mylist:{
random: this.somerandom
}
}
}
}
You can try with computed property:
new Vue({
el: '#demo',
data () {
return {
somerandom:"foo",
mylist:{
random: ''
}
}
},
computed: {
rand() {
return this.mylist.random = this.somerandom
}
}
})
Vue.config.productionTip = false
Vue.config.devtools = false
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="demo">
<p>{{ rand }}</p>
</div>
model init an object with value.
can set value by default or run func after computed or mounted
data() {
return {
somerandom: '',
someOther: [],
}
},
computed: {
useRandom() {
this.somerandom = this.rand();
}
},
methods: {
rand(){
return 'random';
}
}

Updating data according to props value in Vue file returning not defined error message

I am trying to change the data depending on the value of my props in a Nuxtjs app.
export default {
props: {
moved: {
default: false,
type: Boolean,
}
},
data: function () {
if (!this.moved){
dataName: {
fill: "value1"
}
else dataName: {
fill: "value2"
}
return dataName
}
}
}
But I have an error message telling me that dataName is not defined. I don't know what I am doing wrong here...
You can make computed property instead:
Vue.component('Child', {
template: `
<div>
{{ dataName }}
<svg height="210" width="500">
<polygon points="100,10 40,198 190,78 10,78 160,198" :fill="dataName.fill"/>
</svg>
</div>
`,
props: {
moved: {
default: false,
type: Boolean,
}
},
computed: {
dataName() {
let mov = {}
this.moved ? mov.fill = 'blue' : mov.fill = 'red'
return mov
}
}
})
new Vue({
el: '#demo',
data() {
return {
moved: false
}
},
methods: {
changeMov() {
this.moved = !this.moved
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="demo">
<button #click="changeMov">Change</button>
<Child :moved="moved" />
</div>

Custom input component ignores update from method

I did a custom input component, it works correctly but there is a problem: when i try to update its value from a method the model is updated but the input value still there.
This is my component:
https://codepen.io/ken-ramirez/pen/JgyKad
const BasicInput = {
template: '<input v-model="content" #input="handleInput" />',
prop: ['value'],
data () {
return {
content: this.value
}
},
methods: {
handleInput (e) {
this.$emit('input', this.content)
}
}
}
new Vue({
el: '#app',
data: { name: '' },
components: { BasicInput },
methods: {
restart() {
this.name = ''
}
}
})
You can press on restart button to see what i mean.
You have a mistake in your code: props, not prop.
But this is not enough, also you need to update your content manually, it's not reactive with value prop. Everything declared inside data is not reactive with its initial values.
const BasicInput = {
template: '<input v-model="content" #input="handleInput" />',
props: ['value'],
data () {
return {
content: this.value
}
},
methods: {
handleInput (e) {
this.$emit('input', this.content)
}
},
watch: {
value(val) {
this.content = val;
}
}
}
Like #NikitaK mentioned in his answer you're making a typo , you should write props instead of prop, but i want to give a shorter solution without using watcher property only with this code #input="$emit('input',$event.target.value)"
Full example
const BasicInput = {
template: `<input :value="value" #input="$emit('input',$event.target.value)" />`,
props: ['value']
}
new Vue({
el: '#app',
data() {
return{
name: ''
}},
components: { BasicInput },
methods: {
restart() {
this.name = ''
}
}
})
body {
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
<div id="app">
<basic-input v-model="name"></basic-input>
<p>
<strong>Name:</strong> {{ name }}
</p>
<button #click="restart">restart</button>
</div>

Vue binding parent and child components

How to binding parent's model to child in Vue.js?
These codes below is works fine. if i fill the input manually, then child's model return it's value to the parent's model.
But the issue is, if the data set from AJAX request in a parent, the input doesn't automatically filled.
Can anyone help me on this?
Form.vue
<template>
<form-input v-model="o.name" :fieldModel="o.name" #listenChanges="o.name = $event"/>
<form-input v-model="o.address" :fieldModel="o.address" #listenChanges="o.address = $event"/>
</template>
<script>
import FormInput from '../share/FormInput.vue'
export default {
data () {
return {
o: {
name: '',
address: ''
}
}
},
components: { 'form-input': FormInput },
created: function() {
axios.get('http://api.example.com')
.then(response => {
this.o.name = response.data.name
this.o.address = response.data.address
})
.catch(e => { console.log(e) })
}
}
</script>
FormInput.vue
<template>
<input type="text" v-model='fieldModelValue' #input="forceUpper($event, fieldModel)">
</template>
<script>
export default {
props: ['fieldModel'],
data() {
return {
fieldModelValue: ''
}
},
mounted: function() {
this.fieldModelValue = this.fieldModel;
},
methods: {
forceUpper(e, m) {
const start = e.target.selectionStart;
e.target.value = e.target.value.toUpperCase();
this.fieldModelValue = e.target.value.toUpperCase();
this.$emit('listenChanges', this.fieldModelValue)
}
}
}
</script>
Things are more straightforward if you take advantage of v-model in components.
If you put v-model on a component, the component should take a prop named value, and should emit input events to trigger it to update.
I like to make a computed to hide the event emitting, and allow me to just v-model the computed inside my component.
new Vue({
el: '#app',
data: {
o: {
name: '',
address: ''
}
},
components: {
'form-input': {
template: '#form-input',
props: ['value'],
computed: {
fieldModelValue: {
get() {
return this.value;
},
set(newValue) {
this.$emit('input', newValue.toUpperCase());
}
}
}
}
},
// Simulate axios call
created: function() {
setTimeout(() => {
this.o.name = 'the name';
this.o.address = 'and address';
}, 500);
}
});
<script src="//unpkg.com/vue#latest/dist/vue.js"></script>
<div id="app">
Name ({{o.name}})
<form-input v-model="o.name"></form-input>
Address ({{o.address}})
<form-input v-model="o.address"></form-input>
</div>
<template id="form-input">
<input type="text" v-model='fieldModelValue'>
</template>
The mounted() hook is blocking subsequent updates from the parent.
Remove mounted and change v-model to 'fieldModel'
<template>
<input type="text" :value='fieldModel' #input="forceUpper($event, fieldModel)">
</template>
<script>
export default {
props: ['fieldModel'],
data() {
return {
fieldModelValue: ''
}
},
// mounted: function() {
// this.fieldModelValue = this.fieldModel;
// },
methods: {
forceUpper(e, m) {
const start = e.target.selectionStart;
e.target.value = e.target.value.toUpperCase();
this.fieldModelValue = e.target.value.toUpperCase();
this.$emit('listenChanges', this.fieldModelValue)
}
}
}
</script>
Demo CodeSandbox

watch for a property in vue component

I have an async operation in parent component and need to notify child, that this operation was completed. Could I watch in child for a property change. Somewhat like:
new Vue({
props:['parentReady'],
watch:{
parentReady(val){
alert('parentReady prop was changed');
}
}
})
There are several ways you could do this. You could set a property in the parent when the asynchronous action was complete.
console.clear()
Vue.component("child", {
props: ["parentLoading"],
template: `
<h1 v-if="isParentLoading">Parent is loading...</h1>
<h1 v-else>Parent loading complete!</h1>
`,
computed: {
isParentLoading() {
return this.parentLoading
}
}
})
new Vue({
el: "#app",
data: {
loading: true
},
mounted() {
setTimeout(() => this.loading = false, 2000)
}
})
<script src="https://unpkg.com/vue#2.2.6/dist/vue.js"></script>
<div id="app">
<child :parent-loading="loading"></child>
</div>
You could call a method on the child.
console.clear()
Vue.component("child",{
template:`
<h1 v-if="!loaded">Parent is loading...</h1>
<h1 v-else>Parent loading complete!</h1>
`,
data(){
return {
loaded: false
}
},
methods:{
onLoaded(){
this.loaded = true
}
}
})
new Vue({
el:"#app",
mounted(){
setTimeout(() => this.$refs.child.onLoaded(), 2000)
}
})
<script src="https://unpkg.com/vue#2.2.6/dist/vue.js"></script>
<div id="app">
<child ref="child"></child>
</div>
You could just watch the property.
console.clear()
Vue.component("child", {
props: ["parentLoading"],
template: `
<h1 v-if="parentLoading">Parent is loading...</h1>
<h1 v-else>Parent loading complete!</h1>
`,
watch: {
parentLoading(newVal) {
return newVal
}
}
})
new Vue({
el: "#app",
data: {
loading: true
},
mounted() {
setTimeout(() => this.loading = false, 2000)
}
})
<script src="https://unpkg.com/vue#2.2.6/dist/vue.js"></script>
<div id="app">
<child :parent-loading="loading"></child>
</div>

Categories

Resources