vuejs : passing props down to a component in javascript? - vue.js

How can i pass down props to a javascript Vue component.
this is how i normally do it.
<child prop="value"></value>
but i want to do it like this
var Child = Vue.extend({
...
});
Chid.passProps( {foo: 'bar'} ) // some thing like this?
is this possible in vue.js?
this is the full code:
var Child = Vue.extend({
props: ['foo'],
methods: {
printIt: function() {
console.log(this.foo)
}
},
template: '#example'
});
var vm = new Vue({
el: '#root',
data: {
foo: 'bar'
},
render: function(createElement) {
return createElement(Child); // pass down foo
}
});
link to jsbin

Please read the section on render functions https://v2.vuejs.org/v2/guide/render-function.html#createElement-Arguments
Essentially you need to pass the props with the call to the render function as part of the data element
var vm = new Vue({
el: '#root',
data: {
foo: 'bar'
},
render: function(createElement) {
return createElement(Child, {
props: {
foo: this.foo
}
})
}
});

Related

Possible to compute/watch property from 'outside' Vue?

I am trying to wrap my head around the reactivity in Vue and how/if I can use it in regard to nested properties in objects from my own and other libraries that are not declared within the Vue components.
Here is one JS fiddle trying to use compute:
http://jsfiddle.net/73r9bk2t/1/
<div id="app">
{{item}}
</div>
var someExternalObject = { thing: 'some value' }
var vm = new Vue({
el: '#app',
computed: {
item() {
return someExternalObject.thing;
}
},
})
setTimeout(() => {
someExternalObject.thing = 'new value';
console.log(someExternalObject.thing);
}, 1000)
Here is another trying to use $watch
http://jsfiddle.net/73r9bk2t/2/
<div id="app">
{{item}}
</div>
someExternalObject = { thing: 'some initial text' }
var vm = new Vue({
el: '#app',
computed: {
item() {
return someExternalObject.thing;
}
},
created()
{
// Give the external object a scoped reference
this.someExternalObject = someExternalObject;
this.$watch('someExternalObject.thing', function (newVal, oldVal)
{
console.log("Watched:", newVal, oldVal);
}, { deep: true, immediate: true });
}
})
setTimeout(() => {
someExternalObject.thing = 'some updated text';
console.log(someExternalObject.thing);
}, 1000)
But nothing seems to work (text output is not updated). I am starting to wonder if I am trying to do something that I shouldn't do.
If you're looking to integrate an external library into Vue and make it reactive then you should consider using Vue.observable. It will let you create a reactive object outside of a Vue instance.
const state = Vue.observable({ count: 0 })
const Demo = {
render(h) {
return h('button', {
on: { click: () => { state.count++ }}
}, `count is: ${state.count}`)
}
}
https://v2.vuejs.org/v2/api/#Vue-observable
Hope this helps!
In Vue 3 you can use ref() or reactive():
import { reactive } from 'vue';
const state = reactive({ count: 0 });
Relevant links:
Reactivity Fundamentals (vuejs.org)
ref vs reactive in Vue 3? (stackoverflow.com)

Vue js class binding in template not working

Having some trouble with this example:
https://v2.vuejs.org/v2/guide/class-and-style.html
I simplified my code for this post:
var classdata = {
"isActive": false
}
Vue.component('app', {
props: ['intel'],
template: '<li v-bind:class="{active: this.isActive}" #click="display(intel)"><p>test</p></li>',
methods: {
display: function (name) {
this.isActive = true;
}
}
})
var app = new Vue({
el: '#app',
data: function() {
return classdata;
},
});
When I console log in methods, (this.isActive) it reflects the updated state, but it doesnt add the class. I also noticed when I do this
<li v-bind:class="{active: true}" it works.
Looking for some clarity!
Try referencing this instead of app:
display: function (name) {
this.isActive = true;
}
Also, if you're managing isActive at the component level, define it in the data instead with props.
Edit:
To manipulate data in the child, pass a method through to its props:
Vue.component('app', {
props: ['intel', 'isActive', 'setActive'],
template: '<li v-bind:class="{active: isActive}" #click="display(intel)"><p>test</p></li>',
methods: {
display: function (name) {
this.setActive(true);
}
}
})
var app = new Vue({
el: '#app',
data: function() {
return classdata;
},
methods: {
setActive: function (val) {
this.isActive = val
}
}
});

How to dynamically change components in VueJS

I want to build an app in vue.js where you can dynamically switch between app views without page reloading.
What is the best way to do it?
And why this code doesn't work? Thank you!
var View01 = {
template: `<button #click="swapComponent('view-02')" type="submit">NEXT VIEW</button>`
}
var View02 = {
template: `<button #click="swapComponent('view-01')" type="submit">BACK TO PREVIOUS VIEW</button>`
}
var vm = new Vue({
el: '#app',
data: {
currentComponent: 'view-01'
},
components: {
'view-01': View01,
'view-02': View02,
},
methods: {
swapComponent: function(component) {
this.currentComponent = component;
}
}
})
You're trying to call a parent method from the child components. You need to pass the method as a prop so it is in the child's scope.
var View01 = {
template: `<button #click="swapComponent('view-02')" type="submit">NEXT VIEW</button>`,
props: ['swapComponent']
}
var View02 = {
template: `<button #click="swapComponent('view-01')" type="submit">BACK TO PREVIOUS VIEW</button>`,
props: ['swapComponent']
}
var vm = new Vue({
el: '#app',
data: {
currentComponent: 'view-01'
},
components: {
'view-01': View01,
'view-02': View02,
},
methods: {
swapComponent: function(component) {
this.currentComponent = component;
}
}
})
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.min.js"></script>
<div id="app">
<div :is="currentComponent" :swap-component="swapComponent"></div>
</div>

Vue.js change template data

I have the following code:
Vue.component('greeting', {
template: `<h1>{{ greeting }}</h1>`,
data: function () {
return {
greeting: app.text
}
},
});
var app = new Vue({
el: '.app',
data: {
text: 'Hello'
},
methods: {
changeText: function () {
this.text = 'Goodbye'
}
}
});
So when I call changeText method it changes text but greeting in the component is not updated. I didn't understand if I should use props, watcher or computed property in this case.
You need to pass it as a prop to the component:
Vue.component('greeting', {
template: `<h1>{{ greeting }}</h1>`,
props: ['greeting']
});
and the html:
<greeting :greeting="text"></greeting>

How can I get data inside of Vue from database like config or smth>

var app = new Vue({
el: '#app',
data: {
positions: []
},
created() {
axios.get('/config').then(function(response) {
this.$set(this.positions, "positions", response.data[0].dragedPositions);
});
console.log(this.positions.positions);
}
});
I have configs for my app in database and I want to use them inside of Vue instance (here are positions of my elements). But when im getting "this.positions.positions" Im getting empty string.. How can I do that?
Sounds like you want to load config first and bootstrap application after that. Use propsData for this:
axios.get('/config').then(function(response) {
new Vue({
el: '#app',
props: ['positions'],
propsData: {
positions: response.data[0].dragedPositions
},
created() {
console.log(this.positions);
}
});
});
I even created little demo :)
const axios = {get () {
return Promise.resolve({data: [{dragedPositions: [1,2]}]})
}}
axios.get("/config").then(function(response) {
new Vue({
el: "#app",
props: ['positions'],
propsData: {
positions: response.data[0].dragedPositions
},
created() {
console.log('created hook', this.positions);
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.4/vue.min.js"></script>
<pre id="app">positions = {{ positions }}</pre>
Can you try this trick? See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this
var self = this;
axios.get('/config').then(function(response) {
self.$set(self.positions, "positions", response.data[0].dragedPositions);
});
By the way, It seems that you should initialize your positions as an object instead of an array.