Reputation: 2654
Let's say we have a component <my-cp :list="list"></my-cp>
With this kind of template:
<div class="container">
<slot></slot>
<my-cp2 v-for="li in list" :my-data="li.data"></my-cp2>
</div>
My question: Is it possible to initialise my component my-cp
either with list as an array or using HTML?
I mean having both possibilities. In this case, the HTML would look like this:
<my-cp>
<my-cp2 my-data="foo">
<my-cp2 my-data="bar">
</my-cp>
I am trying to analyze the content of the slot before it is mounted but it seems I can only access the element once the child component is already mounted.
Upvotes: 3
Views: 1639
Reputation: 82489
Put your default content inside the slot in your component. If the user adds slot content, their content will show. Otherwise, the slot content will show.
<div class="container">
<slot>
<my-cp2 v-for="li in list" :my-data="li.data"></my-cp2>
</slot>
</div>
Here is an example.
After further discussion in the comments, I believe I understand what you want to do. To clarify for future readers, as I understand it, @Nabab wants to be able to initialize his component using either data coming from a property, or from components rendered in the HTML in the slot for the component. Additionally the component should be able to modify the existing data to add more items to it's list.
You can do this using a render function.
Vue.component("my-cp",{
props:["list"],
data(){
return {
internalList: this.list
}
},
render(h){
let workingList = []
// Examine the default slot, and if there are any parse
// them and add the data to the workingList
if (this.$slots.default){
for (node of this.$slots.default)
// May want to check here if the node is a myCp2,
// otherwise, grab the data
workingList.push(node.componentOptions.propsData.myData)
}
// Add any items that came from the property/internal data
workingList = workingList.concat(this.internalList)
// Create a list of myCp2 vnodes with the correct data
const list = workingList.map(n => h(myCp2, {props:{myData:n}}))
// Create a button to add list items
const btn = h("button", {on:{click:() => this.internalList.push({bar: true})}}, "Add")
//Render
return h("div", [list, btn])
},
})
Here is an example.
Upvotes: 4