Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamically integrate Vuetify v-stepper with Vue router

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?

like image 955
Frank Avatar asked Jan 22 '19 16:01

Frank


1 Answers

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.
      }
    }
  }
}
like image 65
Jim E Russel Avatar answered Oct 18 '22 19:10

Jim E Russel