Using Vue.js to send a slot to a child component in a nested structure

Check out this interesting modal component configuration

//modal setup
<template>
   <slot></slot>
   <slot name='buttons'></slot>
</template>

Imagine using it like a wizard

//wizard setup
<template>
   <modal>
      <step1-state v-if='step === 1'/>
      <step2-state v-if='step === 2'/>
   </modal>
</template>

Can the steps consume the buttons slot?

This current approach doesn't seem to be working as expected

//step1-state configuration
<template>
   <div>
       <span>Is it functioning properly?</span>
       <div slot='buttons'>
          <button>yes</button>
          <button>no</button>
       </div>
   </div>
</template>

Answer №1

Through my exploration, I discovered that achieving this was not possible by default. I managed to make it work using custom render functions.

child-slot component - This component should be placed within the parent slot content in order to format the child component's content. Multiple child-slots can be added to combine with parent content. It is essential to define a distinct ref attribute for each one.

use-slot component - This component is used to specify the content to be passed to the parent as the content of the child-slot. The content will be enclosed within a span element. It requires named and container attributes.

named - Name of the slot where the content will be placed

container - ref value of the associated child-slot

use-slot will automatically locate the first parent slot named according to the specified named attribute regardless of how deep the child component is nested

child-slot

<script>
    export default {
        render(createElement) {
            return createElement('span', {}, this.content);
        },
        data() {
            return {
                nodesToRender: {}
            }
        },
        computed: {
            content() {
                var result = [];
                for (var node in this.nodesToRender) {
                    result = result.concat(this.nodesToRender[node] || []);
                }
                return result;
            }
        }
    }
</script>

use-slot

<script>
    export default {
        abstract: true,
        props: {
            named: {
                type: String,
                required: true
            },
            container: {
                type: String,
                required: true
            }
        },
        render() {
            var parent = this.findParentOfSlot();
            var content = this.$slots.default;
            var self = this;
            this.$parent.$nextTick(function () {
                if (parent && parent.$refs && parent.$refs[self.container], parent.$refs[self.container].nodesToRender) {
                    Vue.set(parent.$refs[self.container].nodesToRender, self.$vnode.tag, content);
                }
            });
        },
        methods: {
            findParentOfSlot() {
                var parent = this.$parent;
                while (parent) {
                    if (parent.$slots && parent.$slots[this.named]) {
                        return parent.$parent;
                    }
                    parent = parent.$parent;
                }
                return parent;
            }
        }
    }
</script>

Answer №2

Currently, it doesn't seem possible and may not be practical because it can lead to confusion and make the code difficult to follow. Just imagine having to revisit this nested slot code after several months of initially writing it. If both step components need access to the buttons slot, it's best to place it as a sibling next to them and pass props whenever changes are made to the buttons content.

On another note, there is a wizard component available at https://github.com/cristijora/vue-form-wizard, created unintentionally by myself 😄)

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Sequelize - issue with foreign key in create include results in null value

When using the create include method, the foreign key is returning null, while the rest of the data is successfully saved from the passed object. This is my transaction model setup: module.exports = (sequelize, DataTypes) => { const Transaction = ...

Using JavaScript to retrieve and compare element values for a total sum

Given two arrays, the goal is to determine if any two numbers in the array add up to 9. The function should return either true or false. For example: array1 [1, 2, 4, 9] has no pair that sums up to 9, so it returns false array2 [1, 2, 4, 5] does have a ...

Encountered an error searching for module 'autoprefixer' while executing the npx tailwindcss init -p command

I am currently working with Vue 3 and attempting to integrate tailwindcss by following this helpful tutorial: https://tailwindcss.com/docs/guides/vue-3-vite#install-tailwind-via-npm I have successfully installed the necessary dependencies using the comman ...

Retrieve information using PHP with AJAX without revealing it on the screen

Is it feasible to fetch data using Ajax in PHP and store them in a JS variable without displaying it? I require this data for date manipulation but do not want to show it. When I attempted to merely return the data without echoing it, the Ajax data in JS ...

I am experiencing difficulties with the state updates, as they are not displaying my products correctly when I select them from

When updating the states setProductsShow and setSelectedCategories, it is important to note that setSelectedCategories is updated before setProductsShow. This sequence is crucial for rendering products correctly. I have come across numerous solutions rega ...

How to transform an array into a collection of objects using React

In my React project, I encountered the following data structure (object of objects with keys): const listItems = { 1:{ id: 1, depth: 0, children: [2,5] }, 2:{ id: 2, depth: 1, children: [3,4], parentIndex: 1, disable ...

Exploring the concept of multiple inheritance using ES6 classes

My research on this topic has been primarily focused on BabelJS and MDN. However, I acknowledge that there may be more information out there regarding the ES6 Spec that I have not yet explored. I am curious about whether ES6 supports multiple inheritance ...

Handling exceptions in AngularJS router-ui resolve functionality

In my app, I have the parent route listed below: .state('app',{ url: '/app', templateUrl: 'views/app.html', resolve: loadSequence('modernizr','moment'), ...

Using VueJS, an object property containing spaces is causing issues with setting up a watcher

I have a formdata object with a property called "Accounting changing". I successfully display and manipulate the property in console. However, when attempting to add a watcher to the formdata object's property "formData.Accounting Changing", an error ...

VueJS: What is the easiest way to create a new instance of a div with just a click of a button?

Is there a way to create a function that will generate a new instance of a specific div (.container in the template) when a button (#addDiv) is clicked, with the button being the only visible element on the webpage initially? I have heard about using docum ...

Merge the elements of one array with the elements of another array simultaneously

Can a function be created that combines each value from two arrays, even if the arrays are of different lengths? For example: arr1 = ["apple", "banana", "cherry"]; arr2 = ["pear", "kiwi", "orange"] mergedArr= ["applepear", "applekiwi", "appleorange", " ...

What is the best way to assign JSON data to a Class variable within Angular?

In my code, I have a class called Projects export class Projects { project_id: number; project_name: string; category_id: number; project_type: string; start_date: Date; completion_date: Date; working_status: string; project_info: string; area: string; add ...

Having trouble with installing the most recent versions of React App dependencies

After cloning a project from GitHub, I attempted to install dependencies using npm install, but encountered an error: npm ERR! code ERESOLVE npm ERR! ERESOLVE unable to resolve dependency tree npm ERR! npm ERR! While resolving: <a href="/cdn-cgi/l/email ...

Error loading Azure Active Directory web form: Server returned a 401 status code for the requested resource

I recently made changes to my web site (incorporating a web form and entity framework) to use AAD connection, following the guidance in this insightful blog post. However, I am encountering an issue where scripts and css files are not loading properly. Th ...

Instantly refreshing the Angular DOM following data modifications and retrieval from the database

I am currently working on a Single Page Application that uses Angular 8 for the frontend and Laravel for the backend. This application is a CRUD (Create, Read, Update, Delete) system. The delete functionality is working as expected, deleting users with spe ...

Best return type for a webservice triggered using jQuery but not requiring any data to be returned

I am currently working on a web service that utilizes several methods. These methods do not have significant impact on the client side as I call them using jQuery/ajax. My main concern is regarding the recommended return type. Typically, I would return JS ...

implementing one active line item at a time in Vue

Within my Vue template, I have a small unordered list: <ul style="border-bottom:none !important; text-decoration:none"> <li class="commentToggle" v-bind:class="{active:commentActive}" v-on:click="setInputName('new')">New Comment ...

Endless repetition occurs when invoking a function within a v-for loop

I've encountered an issue while trying to populate an array using a method, leading to redundant data and the following warning message: You may have an infinite update loop in a component render function. Below is the code snippet in question: ...

The translation of popups using ngx-translate in Javascript is not functioning properly

When I click on my request, the content "Are you sure?" is not changing to the required language. This issue is located in list.component.html <button type="button" (click)="myrequest(item.Id)">Request View</button> The fu ...

jQuery unable to locate elements or update class following AJAX response

My jQuery.on() event functions are working great when bound to specific elements like "a.my-link". However, I have one function that is bound to the document or body and then traverses multiple elements with the same class attribute. Certain lines in this ...