Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Question]: v-model not updating input value in Shadcn-vue Input component inside a Form #771

Open
2 tasks
SAntoineS opened this issue Sep 18, 2024 · 6 comments
Labels
question Further information is requested

Comments

@SAntoineS
Copy link

SAntoineS commented Sep 18, 2024

Reproduction

https://stackblitz.com/edit/1d3tzs-zd6u8m?file=src%2FApp.vue

Describe the bug

Description:

I am experiencing an issue with the v-model binding not updating the input value in the Input component from Shadcn-vue inside a Form. Even though the value changes in the parent component, the input field in the child component doesn't reflect the updated value.

Steps to reproduce:

  1. Parent component:
  • I pass a reactive object uniteLocale with an ide property to the Input component using v-model.
  • When I update uniteLocale.ide programmatically, the change is reflected in other parts of the template (e.g., a ), but not in the Input field.
<Input v-model="uniteLocale.ide" />
<span>IDE: {{ uniteLocale.ide }}</span>
  • The span reflects the change correctly, but the input field does not.
  1. Child component (Input.vue):
  • I am using default Input component from Shadcn-vue.

Expected behavior:

The input field should update its value when uniteLocale.ide is modified programmatically.

Actual behavior:

The value in the input field does not update even though the value of uniteLocale.ide changes.

What I’ve tried:

  • I removed the passive: true option from useVModel.
  • I verified that uniteLocale.ide is being updated correctly by logging it and displaying it in a <span>.
  • I added a manual watch to observe changes to modelValue and emit update:modelValue accordingly.

Despite these changes, the input field does not reflect the updated value.

Additional context:

  • The useVModel from @vueuse/core appears to work in other components, but here it doesn't update the input value as expected. The span displaying uniteLocale.ide is updated correctly, but not the input field.

Thanks !

System Info

System:
    OS: Windows 10 10.0.19045
    CPU: (12) x64 13th Gen Intel(R) Core(TM) i5-1345U
    Memory: 20.89 GB / 31.64 GB
  Binaries:
    Node: 20.17.0 - C:\Program Files\nodejs\node.EXE
    npm: 10.8.2 - C:\Program Files\nodejs\npm.CMD
  Browsers:
    Edge: Chromium (127.0.2651.98)
    Internet Explorer: 11.0.19041.4355
    @vueuse/core: ^11.0.3 => 11.0.3
    radix-vue: ^1.9.5 => 1.9.5
    vue: ^3.5.4 => 3.5.4

Contributes

  • I am willing to submit a PR to fix this issue
  • I am willing to submit a PR with failing tests
@SAntoineS SAntoineS added the bug Something isn't working label Sep 18, 2024
@SAntoineS SAntoineS changed the title [Bug]: v-model not updating input value in Shadcn-vue Input component [Bug]: v-model not updating input value in Shadcn-vue Input component inside a Form Sep 18, 2024
@SAntoineS
Copy link
Author

It seems to work if I bind the v-model on the FormField and not directly on the Input.

@sadeghbarati
Copy link
Collaborator

Don't create new ref for values, componentField slotProp already have model-value and @update:model-value (v-model).

Instead use initialValues (useForm) option or :initial-values (Form) prop

https://stackblitz.com/edit/1d3tzs-8cmpb1?file=src%2FApp.vue

@sadeghbarati sadeghbarati removed the bug Something isn't working label Sep 19, 2024
@SAntoineS
Copy link
Author

SAntoineS commented Sep 19, 2024

Don't create new ref for values, componentField slotProp already have model-value and @update:model-value (v-model).

Instead use initialValues (useForm) option or :initial-values (Form) prop

https://stackblitz.com/edit/1d3tzs-8cmpb1?file=src%2FApp.vue

Oooh ok cool !

So I can access to the values via values.uniteLocale.idea, like :

watch(() => values.uniteLocale.ide,
  (newValue) => {
    console.log('New Value: ', newValue);
  }
);

And it works!

Thanks a lot !

Another question

How can I pass the values to child component, it's like a ref ?

Because in my context I have a stepper (with two steps) inside the form and each steps is a component.

It's a form application with fields into the steps.

@sadeghbarati sadeghbarati added the question Further information is requested label Sep 19, 2024
@SAntoineS SAntoineS changed the title [Bug]: v-model not updating input value in Shadcn-vue Input component inside a Form [Question]: v-model not updating input value in Shadcn-vue Input component inside a Form Sep 19, 2024
@sadeghbarati
Copy link
Collaborator

In Stepper it's better to use Form component instead of useForm composable just like this link

https://www.shadcn-vue.com/docs/components/stepper.html#form

So you could access the Form context wherever you want with passing props or using inject or using vee-validate utilities

@SAntoineS
Copy link
Author

SAntoineS commented Sep 19, 2024

In Stepper it's better to use Form component instead of useForm composable just like this link

https://www.shadcn-vue.com/docs/components/stepper.html#form

So you could access the Form context wherever you want with passing props or using inject or using vee-validate utilities

I am sorry but I can't understand how to do this...

This is my Form :

<Form v-slot="{ meta, values, validate }" as="" keep-values
              :validation-schema="toTypedSchema(formSchema[stepIndex - 1])">
          <Stepper v-slot="{ isNextDisabled, isPrevDisabled, nextStep, prevStep }" v-model="stepIndex"
                   class="block w-full">
            <form @submit.prevent="HandleSubmit(meta, values, validate)">
              <div class="flex w-full flex-start gap-2">
                <StepperItem
                    v-for="step in steps"
                    :key="step.step"
                    v-slot="{ state }"
                    class="relative flex w-full flex-col items-center justify-center"
                    :step="step.step">
                  <StepperSeparator
                      v-if="step.step !== steps[steps.length - 1].step"
                      class="absolute left-[calc(50%+20px)] right-[calc(-50%+10px)] top-5 block h-0.5 shrink-0 rounded-full bg-muted group-data-[state=completed]:bg-primary"/>

                  <StepperTrigger as-child>
                    <Button
                        :variant="state === 'completed' || state === 'active' ? 'default' : 'outline'"
                        size="icon"
                        class="z-10 rounded-full shrink-0"
                        :class="[state === 'active' && 'ring-2 ring-ring ring-offset-2 ring-offset-background']"
                        :disabled="state !== 'completed' && !meta.valid">
                      <Check v-if="state === 'completed'" class="size-5"/>
                      <component v-if="state === 'active' || state === 'inactive'" :is="step.icon" class="w-4 h-4"/>
                    </Button>
                  </StepperTrigger>

                  <div class="mt-5 flex flex-col items-center text-center">
                    <StepperTitle
                        :class="[state === 'active' && 'text-primary']"
                        class="text-sm font-semibold transition lg:text-base">
                      {{ step.title }}
                    </StepperTitle>
                    <StepperDescription
                        :class="[state === 'active' && 'text-primary']"
                        class="sr-only text-xs text-muted-foreground transition md:not-sr-only lg:text-sm">
                      {{ step.description }}
                    </StepperDescription>
                  </div>
                </StepperItem>
              </div>

              <div class="flex flex-col gap-4 mt-20">
                <step-inscription v-if="stepIndex === 1"/>
                <step-responsable v-if="stepIndex === 2"/>
              </div>

              <!-- Step Actions -->
              <div class="flex items-center justify-between mt-4">
                <Button :disabled="isPrevDisabled" variant="ghost" size="sm" @click="prevStep()">
                  Précédent
                </Button>
                <!-- Next or Submit Actions -->
                <div class="flex items-center gap-3">
                  <Button variant="informationTonal" v-if="stepIndex !== 2" :type="meta.valid ? 'button' : 'submit'"
                          :disabled="isNextDisabled"
                          size="sm" @click="meta.valid && nextStep()">
                    Suivant
                  </Button>
                  <Button variant="successTonal"
                          v-if="stepIndex === 2" size="sm" type="submit">
                    Soumettre
                  </Button>
                </div>
              </div>
            </form>
          </Stepper>
        </Form>

How can I use inject from vue with values (Inside the Form)

I want to modify / access (like watch()) values in my child components.

I can't pass with this :

<step-inscription v-model="values" v-if="stepIndex === 1"/> cause Vue don't want v-slot scope variable in v-model.
Like this error :
Internal server error: v-model cannot be used on v-for or v-slot scope variables because they are not writable.

@sadeghbarati
Copy link
Collaborator

Can you share a minimal demo of your Stepper component

I can't help in this way

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants