1

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?

1
  • 1
    Please don't tag your title question. See How to Ask.
    – isherwood
    Commented Nov 20, 2024 at 20:23

2 Answers 2

3

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.

2

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>

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.