Leveraging v-for within a component that incorporates the <slot/> element to generate a versatile and interactive Tab menu

Currently, I am in the process of developing a dynamic tab menu using Vue 3 and slots. Successfully implementing tabs, I have created BaseTabsWrapper and BaseTab components. The challenge lies in using v-for with the BaseTab component inside a BaseTabsWrapper Component like so:

<section
    id="content"
    class="w-full mx-2 pr-2"
    v-if="incomingChatSessions && incomingChatSessions.length"
>
    <BaseTabsWrapper>
        <BaseTab
            v-for="chatSession in incomingChatSessions"
            :key="chatSession.id"
            :title="chatSession.endUser.name"
        >
            <p>{{ chatSession }}</p>
        </BaseTab>
    </BaseTabsWrapper>
</section>

An important note is that the incomingChatSessions object is asynchronous and sourced from a websocket. Tests confirm that this object works as intended and never returns empty.

In the BaseTabsWrapper template, key parts are:

<template>
    <div>
        <ul
            class="tag-menu flex space-x-2"
            :class="defaultTagMenu ? 'default' : 'historic'"
            role="tablist"
            aria-label="Tabs Menu"
            v-if="tabTitles && tabTitles.length"
        >
            <li
                @click.stop.prevent="selectedTitle = title"
                v-for="title in tabTitles"
                :key="title"
                :title="title"
                role="presentation"
                :class="{ selected: title === selectedTitle }"
            >
                <a href="#" role="tab">
                    {{ title }}
                </a>
            </li>
        </ul>
        <slot />
    </div>
</template>

The script includes:

<script>
import { ref, useSlots, provide } from 'vue'
export default {
    props: {
        defaultTagMenu: {
            type: Boolean,
            default: true,
        },
    },
    setup(props) {
        const slots = useSlots()
        const tabTitles = ref(
            slots.default()[0].children.map((tab) => tab.props.title)
        )
        const selectedTitle = ref(tabTitles.value[0])
        provide('selectedTitle', selectedTitle)
        provide('tabTitles', tabTitles)
        return {
            tabTitles,
            selectedTitle,
        }
    },
}
</script>

This represents the Tab component template:

<template>
    <div v-show="title === selectedTitle" class="mt-4">
        <slot />
    </div>
</template>

<script>
import { inject } from 'vue'
export default {
    props: {
        title: {
            type: String,
            default: 'Tab Title',
        },
    },
    setup() {
        const selectedTitle = inject('selectedTitle')
        return {
            selectedTitle,
        }
    },
}
</script>

A problematic segment in my script causing issues is:

const tabTitles = ref(
    slots.default()[0].children.map((tab) => tab.props.title)
)

Despite fetching multiple title elements via API, upon page load, the array tabTitles only contains one element. Interestingly, triggering a re-render results in the correct number of elements in tabTitles and the corresponding tabs on the menu display correctly. While confirming data flow from the websocket to hydrate the "incomingChatSessions" array functions accurately, the issue persists where tabTiles remains limited to one element.

Answer №1

Here is a possible solution:

computed(   
    () => slots.default()[0].children.map((tab) => tab.props.title) 
) 

This code snippet ensures that the computed property gets updated whenever there are changes in the component, such as slot modifications.

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

What is the process of connecting JSON keys to one another?

I am currently brainstorming a solution to link two distinct JSON formats with their respective keys. Here are the two formats: { "price": [ 511, 499, 419, 312 ], "paid": "OK", "contract": "year", "begindate": "01/01/2018", " ...

Persisted state in Vuex fails to retain data after the page is refreshed

I recently added persisted state to my Vue application using the command npm install --save vuex-persistedstate. After that, I configured my Vuex store.js file in the following way: import Vue from 'vue' import Vuex from 'vuex' import ...

Using AJAX, FLASK, and JavaScript to send an existing array to an endpoint

Having trouble POSTing the array songFiles generated by the getTableData() function (inside an ajax request) to the /api/fileNames endpoint, and then handling it in the postFileNames() callback function. Any assistance or alternative approaches would be gr ...

What is the process of invoking a JavaScript function from Selenium?

How can I trigger a JavaScript function from Selenium WebDriver when using Firefox? Whenever I am logged into my website, I typically utilize this command in Firebug's Command Editor to launch a file upload application: infoPanel.applicationManager. ...

Creating unique sizes for each quad in Three.js using InstancedBufferGeometry and ShaderMaterial

I'm working on creating a visually dynamic scene filled with points of varying widths and heights. The challenge I'm facing is figuring out how to manipulate the vertices in the vertex shader to achieve customized sizes for each point. Here' ...

Can the dropbox option be automatically updated when input is entered in another text field?

I'm working on a form with a dropdown containing category names and a text field for entering the category code. What I need is for selecting a category name from the dropdown to automatically display the corresponding category code in the text field, ...

Encountering an undefined value from state when implementing useEffect and useState

One issue I am facing is that the state of my projects sometimes returns as undefined. It's puzzling to me why this happens. In the useEffect hook, I have a function that fetches project data from an API call to the backend server. This should return ...

Date Range Selection Widget malfunctioning when used within a popup modal

Having trouble with integrating the rsuite daterangepicker and antd's daterangepicker into a React Material UI Dialog/Modal. The date picker popup seems to either not show up or appear outside of the modal window. Take a look at the image below: Clic ...

A guide to merging two JSON objects into a single array

Contains two different JSON files - one regarding the English Premier League stats for 2015-16 season and the other for 2016-17. Here is a snippet of the data from each file: { "name": "English Premier League 2015/16", "rounds": [ { "name": ...

Guide to Wrapping Inner or Wrapping All Elements Except for the Initial Div Class

I am looking to enclose all the elements below "name portlet-title" without including other elements within the "div class name portlet-title". I have attempted the following methods: 1) $("div.item").wrapAll('<div class="portlet-body"></div ...

Improving the innerHTML syntax

I am looking for the correct syntax to add content to an element using innerHTML. Here is an example that isn't working as expected: openNewWindow: function(content) { popupWin = window.open(content, 'open_window', 'menubar, ...

Stopping a file transfer in case of browser closure or upload cancellation

When working on uploading a file asynchronously using HTML5 in MVC3, a common issue arises when dealing with large files such as 1GB. If the upload process is cancelled or the browser is closed at 50% completion, a 500MB file still gets saved in the target ...

"Execute asynchronous tasks in Javascript and receive the returned

Currently, I am utilizing JSF ajax within my application and unfortunately, we are unable to make any changes to that. In the process of waiting for user action, I find it necessary to prompt the user before executing the ajax method. Specifically, I need ...

Obtain information through ajax using an asynchronous function

When fetching data in the first example using ajax with XMLHttpRequest, everything works smoothly. example 1 let req = new XMLHttpRequest(); req.open( "GET", "https://raw.githubusercontent.com/freeCodeCamp/ProjectReferenceData/master/global-tempe ...

Refreshing a section of a webpage using AJAX and PHP

After creating a RESTful API in PHP, I can easily register information by accessing the address . This registration process involves sending a POST request. Below is an overview of my method: File: api.php <?php /* File: api.php */ private function ...

Navigate within the div by scrolling in increments of 100%

I am facing an issue with a div that contains multiple children set to 100% height. My goal is to scroll exactly the height of one child (which is also 100%) on each scroll. However, I am struggling to prevent scrolling multiple steps at a time. I have tri ...

Questions about clarifying JS promises and async-await functions

After doing some reading on promises in JavaScript, I have come across conflicting information which has left me with a few basic questions. I have two specific questions that need clarification: Is it necessary for every function in JavaScript to be ca ...

What is the best way to establish a default search query within the vue-multiselect component?

I have incorporated vue-multiselect into my project. You can find more information about it here. This is a snippet of my template structure: <multiselect v-model="value" :options="options" searchable="true"></multiselect> When I open the mu ...

Creating smooth animations in JavaScript without relying on external libraries such as jQuery

Is there a way in JavaScript to make a <div> slide in from the right when hovered over, without relying on jQuery or other libraries? I'm looking for a modern browser-friendly solution. const div = document.querySelector('.fro ...

Troubleshooting: React is not defined in Rollup + React 17 with updated JSX Transform

I'm currently working on prototyping a microfrontend architecture using Rollup and multiple create-react-app applications. However, when I try to locally yarn link my external app with the container app, I am encountering the following error: The err ...