Reputation: 2252
In the code below I have parent/child components where some data (I'm just using literals) is passed from the root context (data1) whilst other data is applied to the slot
inside the parent
component (data2). The output shows that data1 is available but data2 is not.
Why is the data2 literal not passed to the child component? I've google'd and seen references to using template
with a scope but I don't understand why that would work when I'm not using v-bind
in this example.
I suspect I've misunderstood something but would certainly appreciate some help!
Vue.component(
'child', {
props: ['data1', 'data2'],
template: `
<div>
<p>The child component - data1: "{{data1}}", data2: "{{data2}}"</p>
</div>`
}
)
Vue.component(
'parent', {
template: `
<div>
<p>The parent component</p>
<slot data2="data from parent component"/>
</div>`
}
)
new Vue({
el: '#el',
template: `
<div>
<parent>
<child data1="data from root"></child>
</parent>
</div>`
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.js"></script>
<div id="el" />
Update 04/JAN
I have an alternative use case where I'm trying to encapsulate Bootstrap syntax within a component. Given this is a more concrete example it may be easier to consider. Here I want all the Bootstrap specifics inside the form-group
component but I can't seem to define class="form-control"
on the slot
instead of the template being passed in.
I have to admit that given what @collapsar has said I think this may be a different problem but I'm still in the process of getting my head around this!
Vue.component('formGroup', {
props: ['label'],
template: `
<div class="form-group">
<label for="inputEmail3" class="col-sm-2 control-label">{{label}}</label>
<div class="col-sm-10">
<!-- I'd like to see this the class defined here merged with the template as described
in https://v2.vuejs.org/v2/guide/class-and-style.html#With-Components although admittedly
that's for components and not slots -->
<slot class="form-control"/>
</div>
</div>`
})
new Vue({
el: '#el',
template: `
<div class="container">
<form class="form-horizontal">
<form-group label="Email">
<!-- I don't want the class defined on this control but added by the form-group instead -->
<input type="email" class="form-control" id="inputEmail3" placeholder="Email">
</form-group>
</form>
</div>
`
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.js"></script>
<div id="el">
</div>
Upvotes: 0
Views: 3152
Reputation: 17238
You appear to conceptualize the slot mechanism in a slightly wrong way:
slot
element comes into play: its attributes instantiate the parameters
The rationale for why these placeholders exist in the first place might be that they are to be computed by the child component.See it in code:
Vue.component(
'child', {
props: ['data1', 'data2'],
template: `
<div>
<p>The child component</p>
<p>
<span>Passed through parent: {{data1}}</span><br/>
<span>Passed from parent: {{data2}}</span><br/>
<slot data3="Data from the child template funnelled into a parent-defined slot"/>
</p>
</div>`
}
)
Vue.component(
'parent', {
props: ['data1'],
template: `
<div>
<p>The parent component</p>
<child
:data1="data1"
:data2="'data from parent'"
>
<template slot-scope="mixme">
<span>{{mixme.data3}}</span><br/>
</template>
</child>
</div>`
}
)
//
// Vue instance
// The template references the component 'parent' only.
// As 'child' is embedded into 'parent', this component will be referenced in _parent_'s template.
//
// Also note that 'data1' is passed down as a genuine property instead of a DOM attribute.
//
new Vue({
el: '#el',
template: `
<div>
<parent
:data1 = "'data from root'"
/>
</div>`
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.js"></script>
<div id="el" />
Upvotes: 2