Ho to update custom form component value programmatically in QWIK?

183 views Asked by At

Issue Description:

In the Counter component, the displayed value of the input element updates correctly when using the +/- buttons. However, when submitting the form, the field.value for the corresponding form field remains the same as the default value and does not reflect the updated value.

Steps to Reproduce:

  1. Use the Counter component within a form.
  2. Set an initial value (e.g., 99) for the Counter.
  3. Click the "-" button to decrement the value.
  4. Observe that the input field's displayed value updates correctly.
  5. Submit the form.
  6. Check the value of the field.value associated with the Counter component.
  7. Observe that field.value remains the same as the default value (99), not reflecting the updated value.

Expected Result:

When submitting the form, the field.value should reflect the updated value of the Counter component, not the default value.

Actual Result:

The field.value associated with the Counter component retains the default value when submitting the form, even though the displayed value in the input field is correctly updated.

import { $, component$, useSignal } from '@builder.io/qwik';
import {routeLoader$, z } from "@builder.io/qwik-city";
import { useForm, type InitialValues, formAction$, zodForm$ } from "@modular-forms/qwik";
import type { SubmitHandler } from "@modular-forms/qwik";

interface CounterProps {
  name?: string;
  value?: number;
  attributes?: any
}

export const Counter = component$<CounterProps>((props) => {
  const { value = 0, attributes, name } = props;
  const count = useSignal<number>(value);

  const setValue = $((value: number) => {
    count.value = value;
  });

  return (
    <div>
      <button
        type="button"
        onClick$={() => setValue(count.value - 1)}>
        -
      </button>
      <input
        type="number"
        name={name}
        value={count.value}
        {...attributes}
        onChange$={(e) => setValue(parseInt(e.target.value))}
      />
      <button
        type="button"
        onClick$={() => setValue(count.value + 1)}>
        +
      </button>
    </div>
  );
});

const formSchema = z.object({
  availability: z
    .object({
      daily: z.number().optional()
    })
    .optional()
});

type myForm = z.infer<typeof formSchema>;

export const useFormLoader = routeLoader$<InitialValues<myForm>>(() => ({
  availability: {
    daily: undefined
  }
}));

export const useFormAction = formAction$<myForm>(async (form) => {

  console.log('form: ', form);

}, zodForm$(formSchema));

export default component$(() => {

  const [, { Form, Field }] = useForm<myForm>({
    loader: useFormLoader(),
    action: useFormAction(),
    validate: zodForm$(formSchema),

  });

  const handleSubmit = $<SubmitHandler<myForm>>((values) => {
    console.log('handleSubmit.values: ', values);
  });

  return (
    <Form onSubmit$={handleSubmit}>
     {[
          'daily'
        ].map(name =>
          <Field key={availability-${name}-k} name={availability.${name as 'daily'}}>
          {(field, props) => (
            <Counter
                id ={availability-${name}}
                name ={availability.${name}}
                label ={${name} limit}
                value ={field.value}
                attributes ={props}
                error ={field.error}
            />
          )}
        </Field>
        )}
        <button type="submit" >
          SAVE 
        </button>
    </Form>
  );
});

0

There are 0 answers