Lets say, I have the following vuejs structure:
<!-- MainComponent.vue -->
<template>
<childcomponent></childcomponent>
</template>
<!-- ChildComponent.vue -->
<template>
<div>
<grandchild></grandchild>
</div>
</template>
<!-- GrandchildComponent.vue -->
<template>
<div>
FooBar
<slot name="actions"></slot>
</div>
</template>
If I want to set a value for the grandchild-slot "actions" in the child-component, I have to do this:
<!-- ChildComponent.vue -->
<template>
<div>
<grandchild>
<template slot="actions">Actions from ChildComponent</template>
</grandchild>
</div>
</template>
But how to bypass "actions" from the MainComponent? I tried this, but thats not working:
<!-- MainComponent.vue -->
<template>
<childcomponent>
<template slot="actions" slot-scope="props">
Actions from MainComponent
</template>
</childcomponent>
</template>
<!-- ChildComponent.vue -->
<template>
<div>
<grandchild>
<slot name="actions">
<template slot="actions" slot-scope="props">
Actions from ChildComponent
</template>
</slot>
</grandchild>
</div>
</template>
After a lot of research, I think the only possible way of doing it, is only over the render function (https://v2.vuejs.org/v2/guide/render-function.html).
The main idea behind it is to write instead of html templates for ChildComponent.vue and GrandchildComponent.vue custom render functions.
A complete tutorial for a similar usecase can be found here:
https://github.com/ratiw/vuetable-2-tutorial/wiki
Related
I´m struggeling with passing properties into a slots component.
Here some code to explain my problem:
App template:
<template>
<ModalContainer v-model="visibleModal">
<create-dir-modal />
</ModalContainer>
</template>
ModalContainer:
<template>
<div class="modal-container" v-if="modelValue" #click.self="close">
<slot :close="close" />
</div>
</template>
(close is a defined method here)
CreateDirModal:
<template v-slot="slot">
<div class="create-dir-modal-container">
<i class="button" #click="slot.close">close</i>
<div>
<i>folder</i>
<input placeholder="Name" v-model="name" />
<span></span>
<i class="button">done</i>
</div>
</div>
</template>
I am trying to execute the close method from the ModalContainer in the CreateDirModal.
Here is my problem: slot is not defined in CreateDirModal template.
Am I just using it wrong or is there a way to fix my problem?
Passing a header component as a named slot into router-view. But router-view not exactly displaying it. Normally this was work in vue 2. But it's not with vue 3. Is the way doing it changed or is it impossible to do it now?
header component
<template>
<header id="g-header">
<figure>
<img id="logo"
src="#/assets/images/logo.jpg"
alt="The beautiful MDN logo.">
</figure>
<nav id="g-nav" class="flex justify-space-between">
<a v-for="(link, idx) in links" :key="idx"
class="flex justify-center align-center capitalize"
:href="link.val">{{ link.text }}</a>
</nav>
</header>
</template>
router-view component
<template>
<div id="moduleA" class="modules">
<router-view class="moduleA-children">
<template #header>
<app-header></app-header>
</template>
</router-view>
</div>
</template>
children view component
<template>
<div id="step1">
<slot name="header"></slot>
<div class="row">the named slot OR default slot not showing</div>
</div>
</template>
Is there a way to accomplish this? Or do I missing something here?
In Vue Router 4, <router-view> exposes the component to render as a v-slot prop, named Component, which would be used with the built-in <component> tag. You could pass any slots to the component within that <component> tag:
<router-view v-slot="{ Component }">
<component :is="Component">
<template #header>
<app-header></app-header>
</template>
</component>
</router-view>
demo
I am trying to create a wrapper component around an existing component (q-table from the quasar-framework).
<!-- MyTable.vue -->
<template>
<q-table :title="title" ...>
<template v-slot:top="props">
...
</template>
<template v-slot:body="props">
<q-tr :props="props">
...
</q-tr>
</template>
</q-table>
</template>
<template v-slot:body="props"> and <template v-slot:top="props"> are slots of the q-table component.
How to overwrite these slots in the App.vue:
<!-- App.vue -->
<template>
<div>
<my-table>
???
</my-table>
</div>
</template>
For example:
If in file component1.vue is included component2:
<template>
<div>
<app-component2 />
</div>
</template>
In component2.vue is included component3:
<template>
<div>
<app-component3 />
</div>
</template>
And in component3 is link:
<template>
<div>
<nuxt-link to="">Abc</nuxt-link>
</div>
</template>
How to include component4 instead of component2 in component1 after click on link Abc?
I have a template that needs to be rendered slightly differently depending on a boolean prop. If it's true, the wrapper needs to be outside the child elements, if false, it needs to be wrapping just one of the child elements.
The only way I can think of to do this is to duplicate the child elements in the template like this:
<template>
<div>
<template v-if="flag">
<div class="wrapper">
<component-a />
<component-b />
<component-c />
</div>
</template>
<template v-if="!flag">
<component-a />
<div class="wrapper">
<component-b />
</div>
<component-c />
</div>
</template>
</div>
</template>
Is there any way to do this without duplicating the component-[a/b/c] declarations, which may contain large numbers of props for instance.
How about conditional class binding, ref Class and Style Bindings
<template>
<div :class="{ wrapper: flag}">
<component-a />
<div :class="{ wrapper: !flag}">
<component-b />
</div>
<component-c />
</div>
</template>
Alternative with named slots (untested)
Assuming it's worth the trouble of splitting your template into parent and child, I think you can use named slots with the same name in multiple places, provided you use v-if to compile-in only one instance at a time.
Ref: Conditional slots, is it possible
child
<template>
<div>
<template v-if="flag">
<div class="wrapper">
<slot name="component-a">
<slot name="component-b">
<slot name="component-c">
</div>
</template>
<template v-if="!flag">
<slot name="component-a">
<div class="wrapper">
<slot name="component-b">
</div>
<slot name="component-c">
</div>
</template>
</div>
</template>
parent
<child>
<component-a slot="component-a" />
<component-b slot="component-b" />
<component-c slot="component-c" />
</child>