GithubHelp home page GithubHelp logo

Comments (10)

fabian-hiller avatar fabian-hiller commented on May 22, 2024 1

Thanks again for your commitment to create an issue! I will update zodForm$ so you can pass a function. Then it should work. I will let you know when the update is available.

const productForm = useFormStore<ProductForm>({
  loader,
  validate: zodForm$(() => // Here is the difference
    z.object({
      qty: z.coerce
        .number()
        .min(props.min)
        .max(props.max)
        .multipleOf(props.multipleOf),
    })
  ),
});

from modular-forms.

tuurbo avatar tuurbo commented on May 22, 2024 1

Thanks for the help! I haven't had a chance to work on it again but I will probably go with your second example.

from modular-forms.

fabian-hiller avatar fabian-hiller commented on May 22, 2024

The new version is available. 🎉

from modular-forms.

tuurbo avatar tuurbo commented on May 22, 2024

I updated to the latest version and implemented the code as you wrote in a previous comment but when the validation triggers I get error Error: Code(14): Invoking 'use*()' method outside of invocation context.

import {useLexicalScope} from "/node_modules/.pnpm/@[email protected][email protected]/node_modules/@builder.io/qwik/core.mjs?v=7aacb625";
import {z} from "/node_modules/.pnpm/@[email protected][email protected][email protected]/node_modules/@builder.io/qwik-city/index.qwik.mjs?v=7aacb625";
export const qty_input_component_loginForm_useFormStore_zodForm_uLT58SNrVtg = ()=>{
    const [props] = useLexicalScope(); // <----------- ERROR POINTS HERE
    return z.object({
        qty: z.coerce.number().min(props.min).max(props.max).multipleOf(props.multipleOf)
    });
}

from modular-forms.

fabian-hiller avatar fabian-hiller commented on May 22, 2024

It worked for me. Can you send me your code or a snippet of it?

from modular-forms.

fabian-hiller avatar fabian-hiller commented on May 22, 2024

Did you use component$ for your component?

from modular-forms.

tuurbo avatar tuurbo commented on May 22, 2024

This is the exact code

import { component$, useSignal } from '@builder.io/qwik';
import { zodForm$, Field, useFormStore } from '@modular-forms/qwik';
import { z } from '@builder.io/qwik-city';
import clsx from 'clsx';

interface Props {
  min: number;
  max: number;
  multipleOf: number;
}

type QtyForm = { qty: number };

export default component$<Props>((props) => {
  const loader = useSignal<QtyForm>({
    qty: 1,
  });

  const productForm = useFormStore<QtyForm>({
    loader,
    validate: zodForm$(() =>
      z.object({
        qty: z.coerce
          .number()
          .min(props.min)
          .max(props.max)
          .multipleOf(props.multipleOf),
      }),
    ),
    validateOn: 'input',
  });

  return (
    <>
      <Field of={productForm} name="qty">
        {(field, fieldProps) => (
          <>
            <input
              {...fieldProps}
              value={field.value}
              class={clsx('form-input')}
              type="text"
              inputMode="numeric"
              autoComplete="off"
            />
            <div>Error: {field.error}</div>
          </>
        )}
      </Field>
    </>
  );
});

from modular-forms.

tuurbo avatar tuurbo commented on May 22, 2024
@builder.io/qwik": "0.24.0"
@builder.io/qwik-city": "0.7.0"
@modular-forms/qwik": "^0.4.0"

from modular-forms.

fabian-hiller avatar fabian-hiller commented on May 22, 2024

I have investigated the problem. When a lexically scoped variable is accessed, Qwik executes useLexicalScope under the hood. Since validation can be performed at various points outside of an invocation context, this breaks access to those variables and an error is thrown.

Unfortunately, I don't currently have a solution for this. However, I have two workarounds that may work for you. Instead of accessing props within the formAction$ function, you can pass the whole schema via props.

import { $, component$, type QRL } from '@builder.io/qwik';
import { Field, useFormStore, zodFormQrl } from '@modular-forms/qwik';
import { z, type ZodType } from 'zod';

interface Props {
  schema: QRL<ZodType<any, any, any>>;
}

type QtyForm = { qty: number };

export const YourForm = component$<Props>((props) => {
  const productForm = useFormStore<QtyForm>({
    loader: { value: { qty: 1 } },
    validate: zodFormQrl(props.schema),
    validateOn: 'input',
  });

  return (
    <Field of={productForm} name="qty">
      {(field, fieldProps) => (
        <>
          <input
            {...fieldProps}
            value={field.value}
            class="form-input"
            type="text"
            inputMode="numeric"
            autoComplete="off"
          />
          <div>Error: {field.error}</div>
        </>
      )}
    </Field>
  );
});

export default component$(() => (
  <YourForm
    schema={$(
      z.object({
        qty: z.coerce.number().min(1).max(2).multipleOf(5),
      })
    )}
  />
));

The second workaround is to forego validate in useFormStore with a Zod schema and do the validation via our internal validation functions.

import { component$ } from '@builder.io/qwik';
import {
  custom$,
  Field,
  maxNumber,
  minNumber,
  useFormStore,
} from '@modular-forms/qwik';

interface Props {
  min: number;
  max: number;
  multipleOf: number;
}

type QtyForm = { qty: number };

export const YourForm = component$<Props>((props) => {
  const productForm = useFormStore<QtyForm>({
    loader: { value: { qty: 1 } },
    validateOn: 'input',
  });

  return (
    <Field
      of={productForm}
      name="qty"
      validate={[
        minNumber(props.min, 'Number too small!'),
        maxNumber(props.max, 'Number too big!'),
        custom$(
          (value) => !!value && value % props.multipleOf === 0,
          `Not a multiple of ${props.multipleOf}.`
        ),
      ]}
    >
      {(field, fieldProps) => (
        <>
          <input
            {...fieldProps}
            value={field.value}
            class="form-input"
            type="text"
            inputMode="numeric"
            autoComplete="off"
          />
          <div>Error: {field.error}</div>
        </>
      )}
    </Field>
  );
});

export default component$(() => <YourForm min={2} max={20} multipleOf={5} />);

from modular-forms.

fabian-hiller avatar fabian-hiller commented on May 22, 2024

I am unsure if I should reopen the issue, as I don't currently know if there is a solution to this problem. However, if there is any sign of it, I will definitely reopen it.

from modular-forms.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.