vue.js 2 how to properly nest components - vue.js

Can you please tell me how to properly add components to other components?
The example below does not work. The child component is not displayed inside the parent.
<div id="app">
<parent>
<child></child>
</parent>
</div>
<template id='child'>
<div>child component</div>
</template>
<template id='parent'>
<div>parent component</div>
</template>
<script>
var child = {
template: '#child',
data: function () {
return {}
}
};
var parent = {
template: '#parent',
data: function () {
return {}
}
};
new Vue({
el: '#app',
components: {
'parent': parent,
'child': child
}
})
</script>
sample: https://jsfiddle.net/05gc05sk/1/
how to properly nest components?

Your code does work.
Only add <slot> (Content Distribution with Slots) to your parent component.
<template id='parent'>
<div>
parent component
<slot></slot>
</div>
</template>

Related

how to substitute named slot from parent to child to grandchild with Vuejs

I am faced with a situation to render a third party date picker and also get the value from the third party component. since it is a third party i can't define a prop on it. However, the third party component provides an ability to pass variable in v-model.
So the design of my components requires me to be able to pass named slot from parent to child to grandchild.
for example;
//============ enter-or-upload-task.js =============
Vue.config.productionTip = false;
const sourceoftruth = {orderdate:''};
Vue.component('upload-by-csv',{
template:
`<div><input type="file" /></div>
`
});
//here i want to use the date picker
Vue.component('enter-task-by-form',{
data:function(){
return {
sourceoftruth
};
},
methods:{
getOrderDate: function(){
console.log(sourceoftruth.orderdate);
}
},
template:
`<div>
<label>Order Date:</label>
<!--Hoping to get datepicker component displayed here -->
<slot name="picker"></slot>
<input type="submit" #click.prevent = "getOrderDate()" />
</div>
`
});
const EnterTaskOrUploadByCSV = {
template:
`<div>
<upload-by-csv></upload-by-csv>
<enter-task-by-form>
<!-- wish to pass this named slot to this component -->
<slot name="picker"></slot>
</enter-task-by-form>
</div>
`
}
new Vue({
el:"#app",
data:{
sourceoftruth
},
components:{
'datepicker':vuejsDatepicker,
'enter-form-or-csv':EnterTaskOrUploadByCSV
}
})
// ===========================================================
The index.html is
<script src="./js/lib/vue.js></script>
<script src="./js/lib/vuejs-datepicker.js"></script>
<div id="app">
<enter-form-or-csv>
<datepicker v-model="sourceoftruth.orderdate" slot="picker">
</datepicker>
</enter-form-or-csv>
</div>
<script src = "./js/components/enter-or-upload-task.js"></script>
I have tried passing the named slot to the appropriate position but couldn't get it working. Please I need help on how to solve this.
Glad it's working now. The changes I made that it to work
in EnterTaskOrUploadByCSV i added a template slot to hold the datepicker component going to be received from the parent. then the grandchild component would be expecting the template named slot.
const EnterTaskOrUploadByCSV = {
template:
`<div>
<upload-by-csv></upload-by-csv>
<enter-task-by-form>
<template slot="passpicker">
<slot name="picker"></slot>
</template>
</enter-task-by-form>
</div>
`
}
The grandchild component expecting the template named slot.
Vue.component('enter-task-by-form',{
data:function(){
return {
sourceoftruth
};
},
methods:{
getOrderDate: function(){
console.log(sourceoftruth.orderdate);
}
},
template:
`<div>
<label>Order Date:</label>
<!-- Datepicker will show now -->
<slot name="passpicker"></slot>
<input type="submit" #click.prevent = "getOrderDate()" />
</div>
`
});

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>

Vue: remove a component when other is completely loaded

<template>
<div id="app">
<Loading></Loading>
<Content></Content>
</div>
</template>
<script>
import Loading from './Loading.vue'
import Content from './Content.vue'
export default {
name: 'App',
components: {
Loading,
Content
}
}
</script>
What is the best and elegant way to handle a loading component and remove it (or vue component or change styles) when all page is loaded?
I tried with v-cloack, but I think its not working beyond data stuff.
I tried with mounted, but doesn't seems to work.
v-cloak is to hide un-compiled mustache bindings until the Vue instance is ready. So you can use v-if to show/hide loading component.
var child1 = Vue.extend({
template: "<div>Loading...</div>"
});
var child2 = Vue.extend({
template: "<div>After Component loaded</div>",
});
var app = new Vue({
el: "#vue-instance",
data: {
loading: true
},
mounted() {
var vm = this;
setTimeout(function() {
vm.loading = false;
}, 1000);
},
components: {
child1,
child2
},
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.1/vue.js"></script>
<div id="vue-instance">
<child1 :name="name" v-if="loading"></child1>
<child2 :name="name" v-if="!loading"></child2>
</div>

How to pass props using slots from parent to child -vuejs

I have a parent component and a child component.
The parent component's template uses a slot so that one or more child components can be contained inside the parent.
The child component contains a prop called 'signal'.
I would like to be able to change data called 'parentVal' in the parent component so that the children's signal prop is updated with the parent's value.
This seems like it should be something simple, but I cannot figure out how to do this using slots:
Here is a running example below:
const MyParent = Vue.component('my-parent', {
template: `<div>
<h3>Parent's Children:</h3>
<slot :signal="parentVal"></slot>
</div>`,
data: function() {
return {
parentVal: 'value of parent'
}
}
});
const MyChild = Vue.component('my-child', {
template: '<h3>Showing child {{signal}}</h3>',
props: ['signal']
});
new Vue({
el: '#app',
components: {
MyParent,
MyChild
}
})
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<div id="app">
<my-parent>
<my-child></my-child>
<my-child></my-child>
</my-parent>
</div>
You need to use a scoped slot. You were almost there, I just added the template that creates the scope.
<my-parent>
<template slot-scope="{signal}">
<my-child :signal="signal"></my-child>
<my-child :signal="signal"></my-child>
</template>
</my-parent>
Here is your code updated.
const MyParent = Vue.component('my-parent', {
template: `<div>
<h3>Parent's Children:</h3>
<slot :signal="parentVal"></slot>
</div>`,
data: function() {
return {
parentVal: 'value of parent'
}
}
});
const MyChild = Vue.component('my-child', {
template: '<h3>Showing child {{signal}}</h3>',
props: ['signal']
});
new Vue({
el: '#app',
components: {
MyParent,
MyChild
}
})
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<div id="app">
<my-parent>
<template slot-scope="{signal}">
<my-child :signal="signal"></my-child>
<my-child :signal="signal"></my-child>
</template>
</my-parent>
</div>
The release of Vue 2.6 introduces a unified v-slot directive which can be used for normal or scoped slots. In this case, since you're using the default, unnamed slot, the signal property can be accessed via v-slot="{ signal }":
<my-parent>
<template v-slot="{ signal }">
<my-child :signal="signal"></my-child>
<my-child :signal="signal"></my-child>
</template>
</my-parent>
I added this code inside of <v-data-table></v-data-table>
<template
v-for="slot in slots"
v-slot:[`item.${slot}`]="{ item }"
>
<slot
:name="slot"
:item="item"
/>
</template>
And I added a props called slots. When I call the component I send a slots like:
<my-custom-table-component :slots="['name']">
<template v-slot:name="{ item }">
{{ item.first_name + item.last_name}}
</template>
</my-custom-table-component>
You may try this technique.
In this example.
Let assume a parent component wants to share prop foo with value bar.
Parent component
<parent>
<template v-slot:default="slotProps">
// You can access props as object slotObjects {foo"bar"}
<p>{{slotProps.foo}}</p>
</template>
<parent>
Child
<template>
<div class="parent">
<slot :foo="bar" />
</div>
</template>
Got the idea from this video
I hope it helped you accomplish your tasks.

How can I compile the inner component as a child in Vue.js?

I know that normally all components are compiled globally and as siblings to each other. But I'm wondering how can I use the property of parent component? For example:
Vue.component('parent',{
template: '#parent',
props:['tab']
});
Vue.component('child',{
template: '#child',
props:['scope']
});
new Vue({
el: 'body',
data: function(){
return {
tab: "global"
}
}
});
<parent tab="parent">
<child slot="child" :scope="tab"></child>
</parent>
<template id="parent">
<h1>Parent</h1>
<slot name="child"></slot>
</template>
<template id="child">
<p>Compiled in {{scope}}</p>
</template>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/1.0.26/vue.min.js"></script>
In this case i'd use local registration for the child component. Instead of making it global you can register it locally like:
// extend and register in one step
Vue.component('my-component', {
template: '<div>A custom component!</div>'
})
// also works for local registration
var Parent = Vue.extend({
components: {
'my-component': {
template: '<div>A custom component!</div>'
}
}
})
You don’t have to register every component globally. You can make a component available only in the scope of another component by registering it with the components instance option:
http://vuejs.org/guide/components.html#Local-Registration