Parent component slots inside children component vue 2.x - javascript

I have a modal that have 2 slots, default slot and buttons slot, in the default slot i will set the content of the modal (in this case i will use an alert) and in buttons slot i will add some buttons (in this case a delete button).
Now i want to create a component that will contain the alert and the delete button mentioned before. but the alert will be in the default slot and the button in the buttons slot of the modal.
If i use the code below in the modal component like this, it will show the modal with the alert
<modal>
<template v-slot:default>
<v-alert type="warning" :value="true">
¿Are you sure you want to delete {{ text }}?
</v-alert>
</template>
<template v-slot:buttons>
<v-btn color="error" #click="clicked">Delete</v-btn>
</template>
</modal>
Now what i want is to be able to just set a component inside the modal like this
<modal :title="title" :show="show" #close="show = false">
<modal-elim :text="'delete something'"></modal-elim>
</modal>
I want to do this, so i can dynamically change the content of the modal in the future, and reuse the same modal layout.
As you can see the modal-elim component will have the alert and the button shown before, but they must apper in the slots of the modal component, i have tried this
<template>
<div>
<template v-slot:default>
<v-alert type="warning" :value="true">
¿Estas seguro que deseas eliminar {{ text }}?
</v-alert>
</template>
<template v-slot:buttons>
<v-btn color="error" #click="clicked">Enviar</v-btn>
</template>
</div>
</template>
<template v-slot> can only appear at the root level inside the receiving the component
When i trie to wrap the elements inside the slot it throw an error
It is posible to add the parent slot iside the child component?
How can i do that?
How else can i do a workaround this?
in the ModalElim component? i have tried this but it throw an error.

Related

Why can't I call a method when clicking on this span text?

Using Vue 3 I am trying to call the handleViewAuditClick method when someone clicks the span.
I have added #click="handleViewAuditClick" event to the span text but clicking the text does not call the method.
If I change it so the text is wrapped in a div instead that works. Although I have no idea why that works. Using a div is also not a good solution for me because it changes the text to be multi-lined which I don't want.
So how do I call the handleViewAuditClick when clicking the span text?
<template>
<v-alert-banner design="positive">
New audit is ready.
<span #click="handleViewAuditClick">
Click here to view.
</span>
</v-alert-banner>
</template>
<script setup>
import VAlertBanner from 'src/components/VAlertBanner.vue';
const handleViewAuditClick = () => {
console.log('clicked');
};
</script>
And this is what the child v-alert-banner component looks like:
<template>
<q-banner dense rounded :class="classValue" class="full-width">
<template #avatar>
<q-icon :name="iconNameValue" size="sm" />
</template>
<slot></slot>
</q-banner>
</template>

Adding #click events dynamically inside v-for loop

I have an array passed as a prop to fill in a v-for loop for a v-menu in vuetify. The menu items need to have #click events assigned and the names of the functions are passed in the array as a string (one example is the "CanResolve" event which you see in the parent component) and then inserted into the v-on:click="item.clickFunctions" for each menu button. I am currently storing the functions in the child component and it is not working but ultimately I would like to store the functions in the parent component and have the #click events call those if possible. The one example is the myButtonEventHandler method stored in the parent component which is suppose to be triggered by the CanResolve event in the child theme. For some reason this event is not even being triggered when dynamically created like this in the v-for and #click.
Child component which has the following menu which needs click events filled from array passed as prop
<v-menu bottom
right>
<template v-slot:activator="{ on, attrs }">
<v-btn light
icon
v-bind="attrs"
v-on="on">
<v-icon>mdi-dots-vertical</v-icon>
</v-btn>
</template>
<v-list>
<template v-for="(item,index) in menus">
<v-list-item v-if="item.isActive" :key="index" link>
<v-list-item-title #click="$emit(item.clickFunction)">{{item.title}}</v-list-item-title>
</v-list-item>
</template>
<v-list-item :href="docxLocation(filedir)" download link>
<v-list-item-title>Download</v-list-item-title>
</v-list-item>
</v-list>
</v-menu>
Component implemented in parent component:
<embeddedPDF #CanResolve ="myButtonEventHandler" v-bind:filedir="pdfLocation(item.Draft_Path)" v-bind:canvasid="'draft-canvas-'+item.Round" :menus="menuItemsArray[item.Round-1].menus"></embeddedPDF>
You need to add emit event in the child component and pass whatever you want to send to the parent as the second param.
Then in the parent component, you receive that even and assign to a function.
Child component
`
<div v-for="{ item, idx } in items" :key="item.id">
<button #click="$emit('handleItemClick', idx)">{{ item }}</button>
</div>
`
parent component template
<div>
<ChildComponent #handleItemClick="handleChildItemClick" />
</div>
parent component methods
methods: {
handleChildItemClick(idx) {
console.log(idx);
},
},

Converting "[object SVGGElement]" to HTML Vue3

I want to reactively call a custom bootstrap popover component based on which svg the user is hovering over throughout the page. It is called by:
<template>
<popover v-if="node != null">
<template #content>
Reached
</template>
<template #caller>
{{node}}
</template>
</popover>
</template>
However, {{node}} is returning "[object SVGGElement]" rather than the expected html object.
If I use {{node.outerHTML}} it returns a string literal: "svg id="test"></svg"
Any suggestions to have it return as an html object? For example:
...
<template #caller>
<svg id="test"></svg>
</template>
...
The Svg is an SVGGElement. I suggest capturing the mouse mouseover event to set the Popover position.

How to pass class attribute to child from parent in vue?

talents. I want to create beautiful button for vue. But I have a problem. I want to pass class attribute to child from parent component easily.
Parent component is like this:
<!-- parent component -->
<template>
<custom-element class="wanted-class">
<span slot="custom-body">
Some Effects or text
</span>
</custom-element>
</template>
and "custom-element" component is
<template>
<div id="custom-element">
Some elements or text
<slot name="custom-body">
Some default text
</slot>
</div>
</template>
<script>
export defatult{ ...
I really want the root element in child ( $("#custom-element") for jQuery expression) to have "wanted-class" from parent. Is it possible? or it's too easy?

Is there a way to 'pipe-together' slots in nested components in Vue?

Let's say I'm developing an enhanced popper.js for Vue and I'm about to give it some additional functionality. This is how the very (child) component looks like:
<popper>
<div :is="tag" class="popper">
{{ content }}
</div>
<button class="btn btn-primary" slot="reference">
Reference Element
</button>
</popper>
As you can see, for it to work it requires defining reference element right beneath the ".popper" div with a slot="reference" attribute.
Question:
How to turn my enhanced-popper component into a re-usable entity, aka be able to pass slotted data indirectly - from
<enhanced-popper> //referenced element// </enhanced-popper> so that it has the slot="reference" attribute inside the child (popper.js-based) component?
What did not work:
Employing slots and having the attribute in a component passed in by the parent component does not yield desired results, as it does not get rendered at all.
<popper>
<div :is="tag" class="popper">
{{ content }}
</div>
<slot></slot>
</popper>
To ensure having the attribute out there I also tried to replace said button in the child component with a named slot inside a slot and go like this in my enhanced-popper:
<slot name="reference">
<slot></slot>
</slot>
That way the first slotted component has the attribute - and it almost works, but since there are two "slot-layers" (no idea how to call it), the referenced component is not the first one as a child, and popper gets mis-positioned.
Cheers,
Paco

Categories