skip to Main Content

I have a process which have many steps. Each one is implemented in a different component.

Initially I had this 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, in order to make the code more readable, I tried to change to:

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

But it doesn’t work.

I also tried:

<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')),
};

But neither get any result.

I don’t want to register these components in main.ts. Is there any way to do what I am trying to do?

2

Answers


  1. You need to use a computed properties which will act as 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')),
    };
    
    // replace with your real 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>
    
    
    Login or Signup to reply.
  2. is value should be component object itself, it won’t resolve a string like :is="'Step0'" to a component automatically.

    It is:

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

    Step0, etc can be defineAsyncComponent for lazy loading, but this is not necessary.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search