Vuetify Stepper Content Fix

User
<script>
import { ref,shallowRef } from "vue";
import { useForm, useField } from 'vee-validate'
import IconLoading from '../components/icons/IconLoading.vue';
import SingleColumn from '../layouts/SingleColumn.vue';


const otp = shallowRef('')
const { handleSubmit, handleReset, values } = useForm({
    validationSchema: {
      name (value) {
        if (value?.length >= 2) return true

        return 'Name needs to be at least 2 characters.'
      },
      email (value) {
        if (/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}$/i.test(value)) return true

        return 'Must be a valid e-mail.'
      },
      password (value) {
        if (value?.length >= 6) return true

        return 'Password needs to be at least 6 characters.'
      },
      confirmPassword (value) {
        if (value === values.password) return true;
       
        return 'Passwords do not match.';
      }

    },
  })
  const modelValue = ref('1');
  const name = useField('name')
  const email = useField('email')
  const password = useField('password')
  const confirmPassword = useField('confirmPassword');
  const submit = handleSubmit(values => {
    alert(JSON.stringify(values, null, 2))
    modelValue.value = '2';
  })

const user = ref({
  username: "",
  email: "",
  password: "",
});
const loading = ref(false);
const message = ref("");
const showPassword = ref(false);
const createUser = async () => {
    loading.value = true;
  const apiUrl = "https://autohauslange.carmar.digital/wp-json/wp/v2/users";
  const adminUsername = "plstr-admin";
  const applicationPassword = "MrYNs0r68Hb7ywed01JmiX7d";

  // Encode credentials for Basic Auth
  const authHeader = `Basic ${btoa(`${adminUsername}:${applicationPassword}`)}`;

  try {
    const response = await fetch(apiUrl, {
      method: "POST",
      headers: {
        "Authorization": authHeader,
        "Content-Type": "application/json",
      },
      body: JSON.stringify(user.value),
    });

    const result = await response.json();

    if (response.ok) {
      message.value = `User ${result.username} created successfully!`;
    } else {
      message.value = `Error: ${result.message}`;
    }
  } catch (error) {
    message.value = `Request failed: ${error.message}`;
    loading.value = false;
  } finally {
    loading.value = false;
  }
};
</script>

Register

submit

clear

Verify Your Account

We sent a verification code to john..@gmail.com

Please check your email and paste the code below.

Didn't receive the code? Resend

otp step form showing under first sterp

Assistant
The issue is likely due to how `v-stepper-content` is being used. The `value` prop of `v-stepper-content` should match `modelValue`, but Vuetify 3's `v-stepper-content` uses a scoped slot instead of `value`.

### Solution:
Use the `:step` prop inside `v-stepper-content` instead of `value`. Update your “ components as follows:

<v-stepper-content :step="1">

### Updated Code:
Modify your “ like this:

<v-stepper-content :step="1">
  <v-sheet class="mx-auto mt-4 mb-4" max-width="600">
    <form @submit.prevent="submit">
      <v-text-field
        v-model="name.value.value"
        :counter="10"
        :error-messages="name.errorMessage.value"
        label="Name"
      ></v-text-field>

      <v-text-field
        v-model="email.value.value"
        :error-messages="email.errorMessage.value"
        label="E-mail"
      ></v-text-field>

      <v-text-field
        v-model="password.value.value"
        :type="showPassword ? 'text' : 'password'"
        :error-messages="password.errorMessage.value"
        prepend-inner-icon="mdi-lock"
        :append-inner-icon="showPassword ? 'mdi-eye-off' : 'mdi-eye'"
        @click:append-inner="showPassword = !showPassword"
        label="Password"
      ></v-text-field>

      <v-text-field
        v-model="confirmPassword.value.value"
        :type="showPassword ? 'text' : 'password'"
        :error-messages="confirmPassword.errorMessage.value"
        prepend-inner-icon="mdi-lock"
        :append-inner-icon="showPassword ? 'mdi-eye-off' : 'mdi-eye'"
        @click:append-inner="showPassword = !showPassword"
        label="Confirm Password"
      ></v-text-field>

      <v-btn class="me-4" type="submit">
        Submit
      </v-btn>

      <v-btn @click="handleReset">
        Clear
      </v-btn>
    </form>
  </v-sheet>
</v-stepper-content>

<v-stepper-content :step="2">
  <v-card class="py-8 px-6 text-center mx-auto ma-4" elevation="12" max-width="400" width="100%">
    <h3 class="text-h6 mb-4">Verify Your Account</h3>

    <div class="text-body-2">
      We sent a verification code to john..@gmail.com <br>
      Please check your email and paste the code below.
    </div>

    <v-sheet color="surface">
      <v-otp-input v-model="otp" type="password" variant="solo"></v-otp-input>
    </v-sheet>

    <v-btn
      class="my-4"
      color="purple"
      height="40"
      text="Verify"
      variant="flat"
      width="70%"
    >
      Verify
    </v-btn>

    <div class="text-caption">
      Didn't receive the code? <a href="#" @click.prevent="otp = ''">Resend</a>
    </div>
  </v-card>
</v-stepper-content>

<v-stepper-content :step="3">
  <!-- Login Step Content -->
</v-stepper-content>

### Explanation:
1. Replace `value="1"`, `value="2"`, and `value="3"` with `:step="1"`, `:step="2"`, and `:step="3"`.
2. Ensure `modelValue` updates correctly when moving between steps.

Now, the OTP step should correctly display under the second step instead of appearing in the first step. ๐Ÿš€

User
<script>
import { ref,shallowRef } from "vue";
import { useForm, useField } from 'vee-validate'
import IconLoading from '../components/icons/IconLoading.vue';
import SingleColumn from '../layouts/SingleColumn.vue';


const otp = shallowRef('')
const { handleSubmit, handleReset, values } = useForm({
    validationSchema: {
      name (value) {
        if (value?.length >= 2) return true

        return 'Name needs to be at least 2 characters.'
      },
      email (value) {
        if (/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}$/i.test(value)) return true

        return 'Must be a valid e-mail.'
      },
      password (value) {
        if (value?.length >= 6) return true

        return 'Password needs to be at least 6 characters.'
      },
      confirmPassword (value) {
        if (value === values.password) return true;
       
        return 'Passwords do not match.';
      }

    },
  })
  const modelValue = ref('1');
  const name = useField('name')
  const email = useField('email')
  const password = useField('password')
  const confirmPassword = useField('confirmPassword');
  const submit = handleSubmit(values => {
    alert(JSON.stringify(values, null, 2))
    modelValue.value = '2';
  })

const user = ref({
  username: "",
  email: "",
  password: "",
});
const loading = ref(false);
const message = ref("");
const showPassword = ref(false);
const createUser = async () => {
    loading.value = true;
  const apiUrl = "https://autohauslange.carmar.digital/wp-json/wp/v2/users";
  const adminUsername = "plstr-admin";
  const applicationPassword = "MrYNs0r68Hb7ywed01JmiX7d";

  // Encode credentials for Basic Auth
  const authHeader = `Basic ${btoa(`${adminUsername}:${applicationPassword}`)}`;

  try {
    const response = await fetch(apiUrl, {
      method: "POST",
      headers: {
        "Authorization": authHeader,
        "Content-Type": "application/json",
      },
      body: JSON.stringify(user.value),
    });

    const result = await response.json();

    if (response.ok) {
      message.value = `User ${result.username} created successfully!`;
    } else {
      message.value = `Error: ${result.message}`;
    }
  } catch (error) {
    message.value = `Request failed: ${error.message}`;
    loading.value = false;
  } finally {
    loading.value = false;
  }
};
</script>

Register

submit

clear

Verify Your Account

We sent a verification code to john..@gmail.com

Please check your email and paste the code below.

Didn't receive the code? Resend

all step form showing in one step first

Assistant
It looks like your `v-stepper-content` components are not being properly controlled by `v-model="modelValue"` in “. The issue is likely due to the incorrect usage of `:step` in `v-stepper-content`. Vuetify's “ expects the `value` attribute instead of `:step`.

### **Fix**
Replace:

<v-stepper-content :step="1">

With:

<v-stepper-content value="1">

Do this for all steps.

### **Updated Code**
Modify your “ like this:

<v-stepper-content value="1">
  <!-- Step 1: Registration Form -->
</v-stepper-content>

<v-stepper-content value="2">
  <!-- Step 2: Verification -->
</v-stepper-content>

<v-stepper-content value="3">
  <!-- Step 3: Login -->
</v-stepper-content>

### **Final Check**
Make sure `modelValue` is correctly updated on form submission:

const submit = handleSubmit(values => {
  alert(JSON.stringify(values, null, 2));
  modelValue.value = '2'; // Moves to the next step
});

This should ensure only one step is shown at a time, and the navigation works as expected. Let me know if you need further adjustments! ๐Ÿš€

User
still not work
Assistant
It looks like the issue is with the `v-model` binding on your “ component. In Vuetify 3, `v-model` should be bound to a **number** rather than a string. Since `modelValue` is currently defined as `ref('1')`, it is a string instead of a number, which is causing all steps to be shown at once.

### Fix:
Change this:

const modelValue = ref('1');

To:

const modelValue = ref(1); // Make it a number

And in your “ components, ensure that the `:step` prop matches the correct numeric value:

<v-stepper-content :step="1">
  ...
</v-stepper-content>

<v-stepper-content :step="2">
  ...
</v-stepper-content>

<v-stepper-content :step="3">
  ...
</v-stepper-content>

### Explanation:
– `v-model="modelValue"` should be a **number** (`1`, `2`, `3`), not a string (`"1"`, `"2"`, `"3"`).
– “ should match `modelValue = 1` correctly.

After making this change, your stepper should correctly show only one step at a time. ๐Ÿš€ Let me know if you need further assistance!

Leave a Comment

Your email address will not be published. Required fields are marked *