10
votes

I would like to integrate vuetify's v-stepper with vue router. My requirements are as follows:

  • Each step has its own route (e.g. /myform/step1, /myform/step2, /myform/step3, etc)
  • Each step is component on its own which is dynamically loaded (lazy-load).
  • Each step is dynamically created (e.g. via a loop).

This is more of a 'what is the best approach' kind-of-question. I've tried multiple solutions but none fit my requirements.

  • I've tried creating nested routes and placing a router-view in v-stepper-content. Example below. The issue I faced here was that it's impossible to synchroniously update position (see v-stepper element) and the route. So you'll always see the route updating before the step is updated.
<v-stepper v-model="position" vertical>
  <template v-for="(item, index) in steps">

          <v-stepper-step :complete="position > index + 1" :step="index + 1">
            <h2>
              {{item.title}}
            </h2>
          </v-stepper-step>

          <v-stepper-content :step="index+1">
            <router-view></router-view>
          </v-stepper-content>

  </template>
</v-stepper>
  • Another solution I tried is loading the components async/dynamically directly (so without router). However, then I lose the beautiful ability to navigate through my v-stepper using the browser's back and next buttons.

In my experience, the biggest pitfall is that (contrary to e.g. v-tab), is that every step has to have its own v-stepper-content. If I were to do this with tabs, I would just create one tab-item and update the view. I can't do that with v-stepper, because it wouldn't continue to the next 'step'.

Would anyone have a creative approach?

2
How do you plan to process situations when user enters second / third steps directly? Which component to load? Where the data comes from?AndrewShmig
Validation on submit will require all steps to be completed. Which component to load is based on the route prop. Data is hardcoded in the components.Frank
any solution to this yet?Rakibul Haq
I use <component :is=""> right now and manually push routes with parameters to vue router (so you'd get ?step=1, ?step=2, etc). But that's not a real solution.Frank

2 Answers

7
votes

I was able to achieve this by doing the following:

<v-stepper-step @click="goToRoute('step1')">

with

goToRoute(name) {
   this.$router.push({'name': name})
}

You should be able to do this:

<v-stepper-step @click="$router.push({'name': name})">
3
votes

As an additional answer to @tmfmaynard, in order to align the correct highlighted stepper with your current route after a page refresh, here is the code.

 <v-stepper v-model="e1" alt-labels non-linear>
    <v-stepper-header class="elevation-0">
      <v-stepper-step 
        step="1" 
        class="caption" 
        editable
        @click="$router.push({name: 'name'}).catch(err => {})" 
      >
      </v-stepper-step>
    </v-stepper-header>

    <v-stepper-items>
      <v-stepper-content step="1">
        <router-view />
      </v-stepper-content>
    </v-stepper-items>
  </v-stepper>

<script>
export default {
  data () {
    return {
      e1: 1
    }
  },

  created() {
    this.getStepper()
  },

  methods: {
    getStepper() {
      const path = this.$route.path.split('/')
      if(path[path.length-1].toLowerCase() === 'your-router-path') {
        this.e1 = 1
        // this.e1 = 1 = <v-stepper-step step="1" />
        // this.e1 = 2 = <v-stepper-step step="2" />
        // and so on.
      }
    }
  }
}