i have in my parent a custom tag <datatable> with slot references in it:
<datatable>
<div slot="week"> 5</div>
<div slot="day"> monday</div>
</datatable>
Is it possible to get an array of the slot names?
tried: document.querySelectorAll('[slot]');
But all i get is an empty nodelist.
You can get the array like this (https://v2.vuejs.org/v2/api/#vm-slots):
<datatable ref="comp">
<div slot="week"> 5</div>
<div slot="day"> monday</div>
</datatable>
console.log(Object.keys(this.$refs.comp.$slots));
Related
While I was reviewing headlessui's menu component, I saw the use of 2 components that are nested like the following: (see: https://headlessui.dev/vue/menu)
<template>
<Menu>
<MenuButton>More</MenuButton>
<MenuItems>
<MenuItem v-slot="{ active }">
// some content
</MenuItem>
</MenuItems>
</Menue>
</template>
So as you may see, there is a MenuItem component inside of the MenuItems component. And I need something similar to that so I can use a template and put another component's result into that template.
Here the example of what I am trying to do:
<!-- HeadingComponent.vue -->
<div class="group">
<div class="head">
{{ title }} <button>Create New</button>
</div>
<div class="content">
<!-- I want to put some component's rendered content here -->
</div>
</div>
And this is, let's say, a page where I want to use the common component.
<!-- Blog.vue -->
<HeadingComponent :title="Posts">
<BlogPostsComponent :post="someArray"/> <!-- Some other component which may vary -->
</HeadingComponent>
The question
What kind of changes do I need to do in the component HeadingComponent.vue so it works as I expected?
Slots are a good way to add a component to another or even simple html
docs : https://fr.vuejs.org/v2/guide/components-slots.html
<h1>Vue JS Slots Application</h1>
<div id="app">
<slots>
<template slot="slotA"><pre>Slot A Content from parent.</pre></template>
<template><i>Parent Component Content.</i></template>
</slots>
<hr/>
<slots>
<template slot="slotB">Replace Slot B Default Content</template>
<template><b>Replace Default Slot Content.</b></template>
</slots>
</div>
<template id="aside">
<div>
<h3>My Slots App</h3>
<slot>Default Slot Content</slot><br>
<slot name="slotA"></slot><br>
<slot name="slotB"></slot><br>
</div>
</template>
Example of codepen :
https://codepen.io/brian_kim/pen/NpWKGe
Just in a short time, I found something like slots in VueJS which is definitely what I was looking for.
Here is the guide page:
https://v2.vuejs.org/v2/guide/components-slots
What I did in my problem is that I put <slot></slot> tags inside div whose class is content, and then the last sample I gave (Blog.vue) has worked.
<!-- HeadingComponent.vue -->
<div class="group">
<div class="head">
{{ title }} <button>Create New</button>
</div>
<div class="content">
<!-- I want to put some component's rendered content here -->
<slot></slot>
</div>
</div>
I do have a for loop and inside i want to have a modal for each image
<div class="col pb-3" v-for="(item, index ) in img" :key="index" style="width: 300px;height:auto;">
<img v-b-modal="'modal-'+index" :ref="'image'" #mouseover="mouseOver" #mouseleave="mouseOut" /><br>
<b-modal :id="'modal-'+index" title="BootstrapVue">
<p class="my-4">Hello from modal - {{index}}</p>
<img :ref="'imagex'" />
</b-modal>
<div class="progress pt-2 mt-1" style="width: 100px;margin: 0 auto;">
<div class="progress-bar " :style="[{'width':width[index]+'px'}]" role="progressbar"
aria-valuenow="0" ref="'progress'" aria-valuemin="0" aria-valuemax="100"></div>
</div>
</div>
In methods i am giving src value to each image that has :ref="'image'" and i can actually give a src to them its work fine but, i also want be able to give src value images in modal. Its called :ref="'imagex'" but its undefined.
this.$refs.image[i].src = event.target.result //works
this.$refs.imagex[i].src = event.target.result //undefined
What is the problem an is there anyway to solve it ?
When used on elements/components with v-for, the registered reference will be an Array containing DOM nodes or component instances.
An important note about the ref registration timing: because the refs themselves are created as a result of the render function, you cannot access them on the initial render - they don’t exist yet! $refs is also non-reactive, therefore you should not attempt to use it in templates for data-binding.
.
can use it in events and only at mounted function.
https://v2.vuejs.org/v2/api/#ref
In my first example, I have in my component's template:
<div id="hello">hello world</div>
When console.log(this.$refs['hello']) is called in myMethod(), I get undefined in the console.
In my second example, I have:
<div v-for="item in data">
<div :id="'hello-'+item.id">hello {{ item.id }}</div>
</div>
When console.log(this.$refs['hello-1']) is called in myMethod(), I also get undefined in the console.
What's wrong in my code ?
You cannot get element with refs by giving that element id. You should bind ref to that element. Here is an example:
<div v-for="item in data" :key="item.id">
<div :id="'hello-'+item.id" :ref="'hello-'+item.id">hello {{ item.id }}</div>
</div>
And also don't forget to bind key to your iterating elements with v-for
I have a vue component with a structure like this:
<transition name="fade">
<div>
<div v-if="false">
</div>
<div v-else="">
<div>
<div>
<div>no matter what content</div>
</div>
<div>
</div>
</div>
</transition>
it works fine until i add a 4th div inside, even without content as it will throw:
DOMException: Failed to execute 'insertBefore' on 'Node': The node before which the new node is to be inserted is not a child of this node.
If I remove the transition tag... it no longer throws the error
so I'm just curious... is there a limit in allowed depth for vue?
No. There's no limit. You can nest any number divs. But I saw your v-else condition and that might be the issue.
Replace this:
<div v-else="">
With this:
<div v-else>
I'd like to create a custom element that loops through an array and applies the to each item in the array. For example, the view template of the custom element would contain something like:
<div repeat.for="i of items">
<div with.bind="i">
<slot></slot>
</div>
</div>
When I remove the repeat.for and with.bind attributes, the slot displays a single time. Is there a way to make it repeat for each item in the list?
No, you cannot use slots with repeat.for or bind today. To do this you have to use replaceable parts. For example:
<div repeat.for="i of items">
<div with.bind="i">
<template replaceable part="content"></template>
</div>
</div>
Usage:
<my-component>
<template replace-part="content">Some Content - ${somePropertyOfI}</template>
</my-component>
Runnable example: https://gist.run/?id=29aa1c1199f080c9ba0e72845044799b