How to pass data into components in vue.js? - vue.js

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

Related

How to make a template variable non-reactive in Vue

I have an edit form with variables held in the data(). I don't want the title of the edit page to update yet I want to maintain the v-model sync of data between the input and data. What's the simplest way to make the title non-reactive in the h1 tag? Mr You has to have something up his sleeve for this..
<template>
<div>
<h1>{{ title }}</h1>
<input v-model="title">
</div>
</template>
<script>
export default {
data: {
title: 'Initial value'
}
}
</script>
The Vue docs recommend Object.freeze() on the returned object in data() to disable reactivity on properties:
data() {
return Object.freeze({ title: 'Initial value' })
}
But the caveat is it freezes all properties (it doesn't look like there's a way to freeze only some properties using this method), and using v-model with this causes console errors (Cannot assign to read only property).
Vue.config.devtools = false;
Vue.config.productionTip = false;
new Vue({
el: '#app',
data() {
return Object.freeze({
message: 'Hello Vue.js!',
})
}
})
<script src="https://unpkg.com/vue#2.5.17"></script>
<div id="app">
<p>{{ message }}</p>
<input v-model="message"> <!-- XXX: Cannot use v-model with frozen property. This will cause a console error. -->
</div>
Alternatively, you could arbitrarily remove the reactivity from any configurable data property by redefining it with writeable: false:
methods: {
removeReactivity() {
Object.defineProperty(this, 'title', {value: null, writeable: false});
}
}
Vue.config.devtools = false;
Vue.config.productionTip = false;
new Vue({
el: '#app',
data() {
return {
message: 'Hello Vue.js!',
}
},
methods: {
removeReactivity() {
Object.defineProperty(this, 'message', {value: null, writeable: false});
}
}
})
<script src="https://unpkg.com/vue#2.5.17"></script>
<div id="app">
<p>{{ message }}</p>
<input v-model="message">
<div>
<button #click="removeReactivity">
Remove reactivity for <code>message</code>
</button>
</div>
</div>
You could potentially use v-once directive for your purpose if you don't want to create a separate variable for input. From the docs:
Render the element and component once only. On subsequent re-renders,
the element/component and all its children will be treated as static
content and skipped.
new Vue({
el: "#app",
data: {
title: "initial value"
}
})
<script src="https://cdn.jsdelivr.net/npm/vue#2.5.17/dist/vue.min.js"></script>
<div id="app">
<input v-model="title">
<p>Reactive title: {{ title }}</p>
<p v-once>Static title: {{ title }}</p>
</div>
If you don't want the input to change the value of your data item, use value to bind it rather than the two-way v-model. Then it just acts as an initializer for the input.
If you want to have two values, one that doesn't change and one that does that gets initialized from the other, you need to have two data items. The non-changing one can be a prop with a default value. The other is a data member which, if you use a data function, can initialize itself to the prop value.
new Vue({
el: '#app',
props: {
initTitle: {
default: 'Initial value'
}
},
data() {
return {
title: this.initTitle
};
}
});
<script src="https://unpkg.com/vue#latest/dist/vue.js"></script>
<div id="app">
<h1>{{ initTitle }}</h1>
<input v-model="title">
<div>Title is "{{title}}"</div>
</div>
You could alternatively use the little-known $options properties to define your title as a sort of internal constant rather than a prop. I am of mixed feelings about whether this is a good design approach or a step too weird.
new Vue({
el: '#app',
initTitle: 'Initial value',
data() {
return {
title: this.$options.initTitle
};
}
});
<script src="https://unpkg.com/vue#latest/dist/vue.js"></script>
<div id="app">
<h1>{{ $options.initTitle }}</h1>
<input v-model="title">
<div>Title is "{{title}}"</div>
</div>
Working backwards from the contents of this blog...
It appears that when you create an object for Vue, it creates the properties with reactive getters and setters. If you then append a property to that object out-of-band, then it won't get the reactive capability, but will still be accessible as a value.
This should solve it for you:
<template>
<div>
<h1>{{ titleContainer.value }}</h1>
<input v-model="title">
</div>
</template>
<script>
export default {
data: {
titleContainer: {}
}
}
titleContainer.value = "Initial Value"
</script>
There is no easy way to solve your problem with Vue as is since Vue automatically injects reactive getters and setters for all object properties. You could use Object.freeze() on the variable to remove reactivity BUT it would apply across the whole object itself which is not what you want.
I created a fork out of vue called vue-for-babylonians to restrict reactivity and even permit some object properties to be reactive. Check it out here.
With it, you can tell Vue to not make any objects which are stored in vue or vuex from being reactive. You can also tell Vue to make certain subset of object properties reactive. You’ll find performance improves substantially and you enjoy the convenience of storing and passing large objects as you would normally in vue/vuex.

How to pass multiple props from parent to child component in Vue

I'm trying to pass two properties from parent to child, but for some reason this isn't working and all the examples I've found refer to passing a single property. What I've tried to do is:
Parent vue component:
<template>
<div class="statistics_display">
<multiLineChart :rowsA="reading['A'].price_stats" :rowsB="reading['B'].price_stats"></multiLineChart>
</div>
</template>
multiLineChart vue component:
export default {
name: 'MultiLineChart',
props: ['rowsA', 'rowsB'],
mounted: function() {
console.log(this.rowsA);
}
the console log is returning undefined. If I executethe exact same code and pass a single prop, it returns the expected prop contents. What am I missing?
HTML attributes are case-insensitive, so
<multiLineChart :rowsA="reading['A'].price_stats" :rowsB="reading['B'].price_stats"></multiLineChart>
Are actually bound to props: ['rowsa', 'rowsb'].
If you want props: ['rowsA', 'rowsB']to work, use, in the template: :rows-a="..." and :rows-b="...".
See it working below.
Vue.component('multilinechart', {
template: "#mtemplate",
props: ['rowsA', 'rowsB'],
mounted: function() {
console.log(this.rowsA, this.rowsB);
}
})
new Vue({
el: '#app',
data: {
reading: {A: {price_stats: 11}, B: {price_stats: 22}}
}
});
<script src="https://unpkg.com/vue#2.5.13/dist/vue.min.js"></script>
<div id="app">
<div class="statistics_display">
<multiLineChart :rows-a="reading['A'].price_stats" :rows-b="reading['B'].price_stats"></multiLineChart>
</div>
</div>
<template id="mtemplate">
<div>I'm multilinechart</div>
</template>

Component does not show in vue

I do not get vue components really .... I have a vue component in my html and want to show it, but it does not show anything, what do I do wrong?
What is the proper way to register and show a component in vue? Can someone give me a simple example for a beginner? :)
This is my code:
HTML
<div id="na-vue-app">
<activity-filter>
<template>
'Some Text'
</template>
</activity-filter>
</div>
Vue
new Vue({
el: '#na-vue-app'
});
const filterActivity = Vue.extend({
data: function () {
return {
distance:100,
}
},
mounted() {
},
methods: {
}
});
Vue.component('activity-filter', filterActivity);
Look at this pen: https://codepen.io/Nartub600/pen/oopBYJ
HTML
<div id="app">
<my-component msg="Hi!">
</my-component>
</div>
JS
Vue.component('my-component', {
props: ['msg'],
template: '<p>{{ msg }}</p>'
})
var app = new Vue({
el: '#app'
})
It's the easiest form to try components I think

Vue.js 2.0 Dynamic Props Docs

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.

How get data from from Vue Template?

I have got next HTML:
<div id="app">
<component :is="currentView"></component>
</div>
Vue code:
var GuestMenu = Vue.extend({
template: `
<input v-model="username">
`});
Vue.component('guestmenu', GuestMenu);
var App = new Vue ({
el: '#app',
// template: '<usermenu></usermenu>',
data:
{
currentView: "guestmenu",
username: ""
}
})
I need to get username from v-model. The problem that all examples show how to get it's directly, but my data placed in template...
http://jsfiddle.net/u9L569ku/
I believe that this is what you want to achieve. Basically, there is a parent-child realtionship in your example but the communication was not set up correctly. The username in your component was not bound to the username in the Vue instance's data.
jsfiddle
html
<div id="app">
<component :username.sync="username" :is="currentView"> </component>
{{username}}
</div>
javascript
var GuestMenu = Vue.extend({
props : ['username'],
template: `<input v-model="username">`
});
Vue.component('guestmenu', GuestMenu);
var App = new Vue ({
el: '#app',
data: {
currentView: "guestmenu",
username: ""
}
})