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

All menus effortlessly sliding out simultaneously

I'm having an issue with my navigation bar. I want each link to slide its corresponding DIV up or down when clicked. However, all the DIVs are sliding and when clicking on the same link everything slides up. How can I fix this problem? This is my HT ...

Updating NPM packages versions is currently restricted

I'm in the process of creating a Next.JS application using create-next-app. However, I've noticed that in the package.json file it lists the following dependencies: "eslint": "8.43.0", "eslint-config-next": &quo ...

Configuring the Port for NodeJS Express App on Heroku

Currently, I am in the process of hosting my website on Heroku and configuring everything to ensure my app is up and running smoothly. However, each time I attempt to submit the form, undefined errors occur. For more details on the Undefined Errors and Co ...

Incorporating a new textfield in Codeigniter through a button/link activation

Currently, I am working on designing a request form for my website. I am facing an issue with creating a button that can dynamically add new input fields when clicked. Unfortunately, I am unsure of how to resolve this problem. Picture this: [ button ] A ...

Tips for generating various series using dx-Chartjs

Trying to visualize ratings based on their type is proving to be difficult as I can't seem to figure out how to group the series according to types. The available chart options are: $scope.chartOptions = { dataSource: data, c ...

I am encountering some difficulties with the functionality of the angularjs dialog

I've been attempting to integrate an AngularJS dialog feature into my application by following the examples provided on material.angularjs.org. However, despite copying everything accurately, I am unable to get it to function. Can anyone help identify ...

Incorporating Meteor js into an established user system

I'm completely new to the world of Meteor and I am looking to integrate it with my current system that relies on a MongoDB database. As I explore Meteor, I have discovered that there are packages like accounts-facebook and accounts-twitter which assis ...

tips for accessing a PHP variable within an AJAX success function and setting it as a JavaScript variable

How can I access a PHP back end variable in a front-end AJAX success callback function? Here is my PHP code: if($_POST["action"] == 'check_ot_count') { $totaltime = 0; $ot_hours = $_POST["test"]; $month = $_P ...

Issue encountered with dynamic localizations in Vue-i18n when fetching from an HTTP request

My goal is to load localization dynamically through an HTTP call rather than packaging it with the application for better management. However, I encountered an issue where the language does not load on initial render but updates properly when changing rout ...

Sinon's fakeTimers failing to trigger

I'm encountering an issue with sinon's fakeTimers while working in a setup that includes Marionette.js, underscore, and chai test runner. Strangely, when I place a breakpoint in Chrome and step through the code, my timer functions as expected. Ho ...

Verify the type of email domain (personal or corporate)

Here's an example: isPersonalEmail("<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="c0aea1ada580a7ada1a9aceea3afad">[email protected]</a>") // true isPersonalEmail("<a href="/cdn-cgi/l/email- ...

The process of handling state in React when it goes live in production

Currently, I am delving into the world of ReactJS as a novice. The intricacies of state management have captivated my interest. A pressing question has surfaced in my mind regarding this topic. Let's consider a scenario - I have developed a React appl ...

Modify the initial header tag within the document to be <h1> instead of <h2>, <h3>, ... <h6>

In the event that the <h1> tag is not present, the script will search for the first header tag in the document (either <h2> through <h6>). If the text within this tag matches the title text, it will be converted to <h1 class="heading1" ...

How can I increase the element by $100 using a dropdown selection in JavaScript?

Hey there! Looking to create a dropdown list with two shipping options: Special Shipping Normal Shipping <select> <option>Special Shipping</option> <option>Normal Shipping</option> </select> If the user selects Speci ...

The iteration of an ajax POST handler, looping endlessly

Attempting to implement a basic ajax submit handler for modifying a form as part of a lesson on CSRF vulnerabilities, but encountering an issue with the page looping. Below is the code snippet being worked on, inspired by http://api.jquery.com/jQuery.post/ ...

The AJAX request is not triggered before the postback when using a LinkButton in ASP

I am facing an issue with running an insert statement using a button in my application. Although it is functional, I have noticed that whenever I click the button, the Page_Load function runs before the ajax statement executes. How can I ensure that the a ...

Switching between rows in a table once information has been added to an array | Vue

I'm currently working on creating a table with rows that toggle when a 'View' button is clicked. The table is generated using a for loop for an array. I've successfully implemented the toggling functionality for preloaded data, but enco ...

Transforming a React Class Component into a React Functional Component

After struggling for a day with multiple failed attempts, I have been unsuccessful in converting a React Class Component. The original class component code is as follows: class NeonCursor extends React.Component { constructor(props) { super(props); ...

NodeJS: The module failed to automatically register itself

Exploring the capabilities of IBM Watson's Speech to Text API, I encountered an issue while running my NodeJS application. To handle the input audio data and utilize IBM Watson's SpeechToText package, I integrated the line-in package for streami ...

Only when the user has successfully completed the reCAPTCHA and checked the checkbox, Vue will be able to

For my new project developed with VueJs, I am implementing a Single Page Application (SPA). The objective is to incorporate a simple if statement functionality. When the user checks a checkbox and successfully solves the reCaptcha, Vue should send an email ...