What is the best way to dynamically render components using Vue 3?

I am facing a challenge with a process that involves multiple steps, each implemented in a different component.

Initially, I had the following code:

<template>
  <template v-if="process.currentStep === 0">
    <Step0 />
  </template>
  <template v-else-if="process.currentStep === 1">
    <Step1 />
  </template>
  <template v-else-if="process.currentStep === 2">
    <Step2 />
      :
      :
</template>

<script setup>
import Step0 from "@/views/components/steps/step0.vue";
import Step1 from "@/views/components/steps/step1.vue";
import Step2 from "@/views/components/steps/step2.vue";
  :
  :

However, to enhance readability, I attempted to switch to:

<template>
  <component :is="`Step${process.currentStep}`" />

Unfortunately, this approach did not yield the desired outcome.

I also experimented with:

<component :is="stepComponent" />

import { defineAsyncComponent } from 'vue';

const stepComponent = ref(); // Adjust the initial value as needed
const stepComponents = {
  Step0: defineAsyncComponent(() => import('@/views/components/steps/step0.vue')),
  Step1: defineAsyncComponent(() => import('@/views/components/steps/step1.vue')),
  Step2: defineAsyncComponent(() => import('@/views/components/steps/step2.vue')),
};

However, neither method produced any favorable results.

I prefer not to register these components in main.ts. Is there an alternative way to achieve what I am attempting?

Answer №1

is value must be the component object itself, it will not automatically convert a string like :is="'Step0'" into a component.

This is important:

<script setup>
import Step0 from "@/views/components/steps/step0.vue";
...
const stepComponents = { Step0, ... }
...
<component :is="stepComponents[`Step${currentStep}`]"

Step0, etc can also be loaded dynamically using defineAsyncComponent for lazy loading, but it is not mandatory.

Answer №2

To achieve dynamic component loading, utilize computed properties as a component loader

<template>
  <!-- Dynamically load the component based on the current step -->
  <component :is="componentLoader" />
</template>

<script setup>
import { defineAsyncComponent, computed } from 'vue';

// Define async components for each step
const stepComponents = {
  Step0: defineAsyncComponent(() => import('@/views/components/steps/step0.vue')),
  Step1: defineAsyncComponent(() => import('@/views/components/steps/step1.vue')),
  Step2: defineAsyncComponent(() => import('@/views/components/steps/step2.vue')),
};

// Customize this to match your actual process object
const process = reactive({
  currentStep: 0,
});

// Compute the current component based on the current step
const componentLoader = computed(() => {
  const stepKey = `Step${process.currentStep}`;
  return stepComponents[stepKey] || null; // Return null if the step is not found
});
</script>

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

Oops! It seems like there's a problem with reading the 'strEmail' property of undefined. Do you have any ideas on how to fix this issue

Currently, I am working with Express.js to create a straightforward login post request. Here is the code snippet: app.post("/login", (req, res) => { res.send( { isUserRegistered: userLogin(req.body.strEmail, req.body.strPassword), ...

Guide to retrieving RabbitMQ queue messages in Vue.js application

I am currently working on a project using Spring Boot to publish messages to RabbitMQ and then push them to a queue. I also have a Vue.js frontend application that needs to consume these messages from the RabbitMQ queue. Despite searching online, I haven ...

Variations in status brought about by alternative programming functions (excluding React)

I am currently dealing with incorporating two different classes into my project. One class is a React component, while the other is a standard validation class. Within the Validation class, it is added as an element in the React state using the following ...

A VueJS Vee Validate Implementation for Repeating Multiple Text Fields

In my project, I am using a repeater for multiple text fields with veevalidate. However, I have encountered an issue where if the first field contains errors, it affects the other fields as well and they inherit the same error when adding a new field. Che ...

Is it possible to create two sticky headers with varying heights?

Looking to develop a website featuring two sticky elements at the top of the page - a sticky header and a sticky toolbar. Utilizing Bootstrap's Affix for the toolbar and sticky.js for the header. Encountering an issue where setting {topSpacing:0} cau ...

Error message: The Liferay JavaScript Function has not been defined

I am a newcomer to Liferay and have been attempting to utilize Ajax within my scripts, but unfortunately, the code does not seem to load correctly in the browser. I even tried testing it by simply adding an alert. Every time I try, I encounter the "functi ...

Keycloak Node is still prompting for login even when a bearer token is provided

After numerous attempts to integrate Keycloak into my node/express server for bearer token authentication, I find that every protected request I make returns an HTML login page. Here is a snippet of my simple index.js file: const express = require(&a ...

What is causing my function to not wait for the resolution of the Promise?

checkout.ts updateGlobalValue(){ updateShadowDomButton(); let globalValue = fetchGlobalValue() } web_component_render.ts let globalValue; async fetchData() { let booleanFromApi = await callToExternalAPI(); return booleanFromApi; } functi ...

What is the most efficient way to store arrays created within for loops into an empty array located outside of the loop structure?

(I have looked at similar questions that were asked before, but I couldn't find a satisfactory answer... my apologies!) Hey everyone, I am currently using a nested for-loop which is resulting in new arrays being created. Each time the inner loop ex ...

Verify the visibility status of Bootstrap Modal

I want to integrate the Keypress plugin with Modal dialogs in Bootstrap. I found a helpful answer on Stack Overflow that explains how to check if the modal is open or closed using jQuery. My challenge now is to ensure that Keypress only runs when the moda ...

Tips for designing a hyperlink insertion modal while preserving text selection

I am working on a React website that utilizes Slate-React () for creating a rich text input field. Currently, Slate uses the browser's prompt() function to add hyperlinks to selected text. However, I need to customize the styling of the prompt modal a ...

Upon selecting a checkbox, I desire for a corresponding checkbox to also be marked

I am looking to enhance my current project by incorporating a feature that allows the user to simply check a checkbox with specific content once. For example, I have a recipes page where users can select ingredients they need for each recipe while planning ...

"Exploring the process of unsubscribing or disposing of an interval observable based on a certain condition in Angular2 or

I am embarking on the journey into Rx and reactive programming, facing a situation that requires me to continuously monitor a hardware's status by sending a POST request to its REST API every 500ms. The goal is to stop the interval observable once the ...

Displaying random characters in place of Angular 6 font awesome icons

Recently, I started a new project with the angular cli and incorporated font-awesome 4.7.0. After that, I included it as a dependency in my angular.json file. "styles": [ "./node_modules/font-awesome/css/font-awesome.min.css", "./node ...

Utilizing the spread operator to map an array within another array

Exploring the spread operator inside an array to map values from another array has led to unexpected behavior. When attempting to return 2 objects using map within the array, only the last object is being returned. Below is the code snippet: const cats = [ ...

Access the URL with personalized request headers

Our team manages a collection of primary web pages that cater to various organizations. These pages undergo changes in appearance (fonts, images, etc.) depending on the organization accessing them. This customization is done through a unique HTTP Request H ...

The host on your screen is unable to render the map generated using JavaScript

I recently came across this workshop document on openlayers. The example provided can be accessed at the following link: https://openlayers.org/workshop/en/basics/. Upon trying to run the example using the commands npm start and npm run build, both execut ...

Make sure to run the ajax function once more after the Complete function has finished

I'm having trouble re-executing the function with a different parameter in the complete callback. It works fine on the initial call, but subsequent calls only trigger the test alert twice and do not actually execute the function again. My goal is to r ...

What techniques can I use to create a three-dimensional appearance for my cube?

Is there a way to achieve a stunning 3D lighting effect similar to the one in this image on my cube below? https://i.sstatic.net/xjCoD.png When I switch from using BasicMaterial to MeshPhongMaterial or any other material, I end up with a black cube instea ...

how to choose the :after pseudo-element with jQuery

Below are the codes I have tried. When this popup appears, I want to be able to close the entire popbox using the close button. CSS code .bigdiv{ display:none; background-color:#efefef; box-shadow: 10px 10px 10px 100000px rgba(0, 0, 0, 0.4); ...