I'm trying to add more than one slot to a custom component, in this case a Navbar...
When I use only one, and without a name, it works perfectly. When I include a slot name, it stops working.
Calling the navbar...
<CustomNavbar title="USERS.NAME">
<div slot="first">HELLO</div>
<div slot="second">GOODBYE</div>
</CustomNavbar>
And here is the navbar template, simplified...
<ion-toolbar color="primary">
<ion-buttons slot="start">
<slot name="first"></slot>
</ion-buttons>
<ion-title>{{title}}</ion-title>
<ion-buttons slot="primary">
<slot name="second"></slot>
</ion-buttons>
</ion-toolbar>
I'm using Ionic v6 with Vue.js 3.
I cant make it work... any ideas???
Did you try with:
<template #first>HELLO</template>
or
<template v-slot:first>HELLO</template>
Related
I have a global confirmModal.vue which looks like this:
<template>
<Transition
appear
enter-from-class="opacity-0"
enter-to-class="opacity-100"
leave-from-class="opacity-100"
leave-to-class="opacity-0"
>
<div
#click="$emit('cancel')"
class="bg-black/50 z-50 fixed inset-0 flex justify-center items-center transition duration-300 ease-in-out p-8 cursor-pointer"
>
<Transition appear enter-from-class="scale-50" enter-to-class="scale-100">
<div
#click.stop
class="flex flex-col gap-4 shadow-2xl p-8 rounded min-w-[300px] max-w-[480px] bg-lf-white transition duration-300 ease-in-out cursor-auto"
>
<h3 class="font-medium text-2xl">{{ title }}</h3>
<p>{{ text }}</p>
<div class="flex justify-end gap-2">
<Button #click="$emit('cancel')" variant="white">Annuler</Button>
<Button #click="$emit('confirm')">Supprimer</Button>
</div>
</div>
</Transition>
</div>
</Transition>
</template>
The first transition adds a fade in effect to the backdrop while the nested transition adds a smooth apparition effect for the modal itself.
It works fine but what I don't understand is that when I close the modal, the leave part of the transition does not trigger at all.
This is what the component calling this modal looks like:
<ConfirmModal
v-if="showConfirmModal"
title="Suppression"
text="Êtes-vous sûr de vouloir supprimer cet article ?"
#cancel="handleHideConfirmModal"
#confirm="handleConfirmAction"
/>
Here's a gif of what it's currently looks like:
EDIT: I achieved the wanted result by wrapping ConfirmModal.vue with Transition from the parent component, like this:
<Transition
enter-from-class="opacity-0"
enter-to-class="opacity-100"
leave-from-class="opacity-100"
leave-to-class="opacity-0"
>
<ConfirmModal
v-if="showConfirmModal"
title="Suppression"
text="Êtes-vous sûr de vouloir supprimer cet article ?"
#cancel="handleHideConfirmModal"
/>
</Transition>
I don't understand why I have to do this and why in this exemple the person doesn't need to do that though, they use Transition from inside the child component and the transition works fine
It's also not ideal because every time I use this component I will have to think to wrap it inside this transition for it to fully work
It's probably caused by the use of different versions of Vue.
Your question is tagged vuejs3, so you are very likely using Vue 3, but, in the example you linked, vue version 2.6.4 is being used.
In vue 3, at least, you must use the directives v-if or v-show in the root element inside the Transition component for it to trigger the changes whenever the root component inside appears and disappears.
you can read more about transitions here
I am using Navbar component within Boostrap-Vue and would like to add an avatar, the picture of which comes from a variable in the app. The problem is that I cannot bind a variable to the avatar component inside a slot, as it tells me this is null. Is it possible to make this work?
Currently, I have the following code:
<b-navbar>
<b-navbar-brand href="#">Dashboard</b-navbar-brand>
<b-navbar-toggle target="nav-collapse"></b-navbar-toggle>
<b-collapse id="nav-collapse" is-nav>
<b-navbar-nav class="ml-auto">
<b-nav-item-dropdown
class="navbar-right"
toggle-class="nav-link-custom"
right
>
<template #button-content>
<b-avatar :src="this.avatar" size="sm"></b-avatar>
</template>
<b-dropdown-item to="profile">Profile</b-dropdown-item>
<b-dropdown-item to="support">Support</b-dropdown-item>
<b-dropdown-item to="logout">Logout</b-dropdown-item>
</b-nav-item-dropdown>
</b-navbar-nav>
</b-collapse>
</b-navbar>
The error is:
TypeError: this is null
You do not (and should not) need to use the this keyword inside your <template>.
So you should just write :src="avatar".
I have built a user-defined component (async-select) on top of another component (vue mutliselect) like this:
https://jsfiddle.net/2x7n4rL6/4/
Since the original vue-multiselect component offers a couple of slots, I don't want to loose the chance to use them. So my goal is to make these slots available from inside my custom component. In other words, I want to something like this:
https://jsfiddle.net/2x7n4rL6/3/
But that code oes not work.
However, if I add the slot to the child component itself, it works just fine (which you can see from the fact that options become red-colored).
https://jsfiddle.net/2x7n4rL6/1/
After surfing the web, I have come across this article, but it does not seem to work
Is there any way in VueJS to accomplish this ?
Slots can be confusing!
First, you need a template element to define the slot content:
<async-select :value="value" :options="options">
<template v-slot:option-tmpl="{ props }">
<div class="ui grid">
<div style="color: red">{{ props.option.name }}</div>
</div>
</template>
</async-select>
Then, in the parent component, you need a slot element. That slot element itself can be inside of another template element, so its contents can be put in a slot of its own parent.
<multiselect
label="name"
ref="multiselect"
v-model="localValue"
placeholder="My component"
:options="options"
:multiple="false"
:taggable="false">
<template slot="option" slot-scope="props">
<slot name="option-tmpl" :props="props"></slot>
</template>
</multiselect>
Working Fiddle: https://jsfiddle.net/thebluenile/ph0s1jda/
I have what I think is a basic question for Vue, but I'm trying to run a method on click while also running a v-for loop on a component.
I'm not sure why but I can't get anything to run on that click handler but I see nothing in the Vue documentation saying that this isn't possible. Right now I'd settle for getting my console log running.
<IconBox
v-for="step in steps"
:key="step.slug"
:step="step"
:formData="formData"
#click="console.log('click')"
/>
Here is the template for IconBox.vue:
<template>
<div class="icon-box">
<div
class="icon-holder"
:style="{ backgroundImage: 'url(' + step.image + ')' }"
>
</div>
<div class="text">
<div class="inner">
<h5>{{ step.name }}</h5>
<p v-if="step.description">{{ step.description }}</p>
{{ isSelected }}
</div>
</div>
</div>
</template>
I could run the click in the component itself but I need the parent well aware of what's happening to handle a selected boolean.
To use native events in component tags you should add .native modifier
<IconBox #click.native="yourMethod"/>
Check this guide.
To check it I suggest you to create a method and add console.log() inside it.
I have been playing around with Vue lately, and here's how I solved a similar problem in my project
<IconBox
v-for="step in steps"
:key="step.slug"
:step="step"
:formData="formData"
#click="console.log('click')"
/>
Changes to
<template v-for="step in steps">
<IconBox
:key="step.slug"
:step="step"
:formData="formData"
#click="console.log('click')"
/>
</template>
I have a responsive-menu component which I want to use named slots inside of this up my template markup:
<template>
<div class="responsive-menu">
<div class="menu-header">
<slot name="header"></slot>
</div>
</div>
</template>
Whenever I try my named slot like this it work perfectly fine:
<responsive-menu>
<h3 slot="header">Responsive menu header</h3>
</responsive-menu>
However as soon as I wrap it with a class nothing shows up anymore.
<responsive-menu>
<div class="container">
<h3 slot="header">Responsive menu header</h3>
</div>
</responsive-menu>
What is going on here? Shouldn't I just be able to wrap the named component? Which does it appear that my named slots need to be direct children of my Vue component?
It does not work because your "wrapped slot" isn't direct child of responsive-menu tag.
try something like that:
<responsive-menu>
<div class="container" slot="header">
<h3>Responsive menu header</h3>
</div>
</responsive-menu>
jsfiddle
It works with Vue >= 2.6. Just upgrade vue and vue-template-compiler.