10

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?

Frank
  • 1,374
  • 2
  • 16
  • 34
  • 1
    How do you plan to process situations when user enters second / third steps directly? Which component to load? Where the data comes from? – AndrewShmig Jan 31 '19 at 20:19
  • 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 Feb 01 '19 at 09:09
  • any solution to this yet? – Rakibul Haq Feb 07 '19 at 07:19
  • I use `` 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 Feb 07 '19 at 09:04

2 Answers2

8

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})">
Cave Johnson
  • 6,499
  • 5
  • 38
  • 57
TMFMaynard
  • 81
  • 1
  • 3
  • I tried this and it works but I noticed that when you refresh the page, the stepper will go back to it's default (stepper 1) but the page loaded is still last stepper you clicked. How do we set the current stepper as active if we refresh the page? – Jim E Russel May 26 '20 at 07:29
  • Figured it out. I'll just post a supplemental answer to this one. – Jim E Russel May 26 '20 at 08:24
5

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.
      }
    }
  }
}
Jim E Russel
  • 457
  • 10
  • 31