Home > Mobile >  Vue - Render new component based on page count
Vue - Render new component based on page count

Time:07-05

I'm working on an onboarding process that will collect a users name, location, job , etc. It needs to be one question per page but as an SPA so I currently have around 20 components to conditionally render.

Atm, I have a counter and Prev/Next buttons that decrease/increase the counter respectively. I'm then using v-if to check what number the counter is on and render the appropriate page.

Is there a better way around this that is less repetitive and bulky?

Any ideas appreciated!

data() {
   return {
      onboardingStep: 0,
   }
},
methods: {
   prevStep() {
      this.onboardingStep -= 1;
   },
   nextStep() {
      this.onboardingStep  = 1;
   }
}
<intro-step v-if="onboardingStep === 0"></intro-step>
<first-name v-if="onboardingStep === 1"></first-name>
<last-name v-if="onboardingStep === 2"></last-name>

...etc.

CodePudding user response:

Suggestion :

You can make your field components to show or hide based on the prev/next state. Dynamic components provide that platform in an efficient and simple way.

Syntax :

<component :is="componentName"></component>

Then, You can create each component instance dynamically by putting a watcher on components array.

watch: {
  components: {
    handler() {
      this.components.forEach(cName => {
        Vue.component(cName, { 
          template: `template code will come here` 
        })
      });
    }
  }
}

Live Demo :

new Vue({
  el: '#app',
  data() {
    return {
      components: [],
      onboardingStep: 0
    }
  },
  mounted() {
    this.components = ['intro-step', 'first-name', 'last-name'];
  },
  watch: {
    components: {
      handler() {
        this.components.forEach(cName => {
          Vue.component(cName, { 
                data() {
                return {
                modelName: cName
              }
            },
            template: '<input type="text" v-model="modelName"/>'
          })
        });
      }
    }
  },
  methods: {
    prevStep() {
      this.onboardingStep -= 1;
    },
    nextStep() {
      this.onboardingStep  = 1;
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <div v-for="(cName, index) in components" :key="index">
      <component :is="cName" v-if="index === onboardingStep"></component>
  </div>
  
  <button @click="prevStep" :disabled="onboardingStep < 1">Prev</button>
  <button @click="nextStep" :disabled="onboardingStep === components.length - 1">Next</button>
</div>

CodePudding user response:

You could create an array with all your component names in the right order.

const components = ['intro-step', 'first-name', 'last-name' ]

And then with a v-for loop set all the components in your template:

<template v-for="(component, index) in components" :key="component">
    <component :is="component" v-if="index === onboardingStep">
</template>

Hope this helps.

  • Related