Giter Site home page Giter Site logo

forms's People

Contributors

eecolor avatar peeke avatar rickheere avatar

Stargazers

 avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

forms's Issues

Duplicate field names when using `useArrayFormField`

Removing an array item through the helper method returned by useArrayFormField can lead to duplicate field names.

This happens when:

  1. You have 2 array form field children
  2. You remove the first one
  3. You add another one

Both child fields will now have the name form1.arrayfield[1]

Checkbox and showError on blur

Is it possible to show a validation error of a checkbox on blur?

See the following test case:

import { useBooleanFormField, useForm } from '@kaliber/forms'

function needsToBeChecked(x) {
  return x !== true && { id: 'needsToBeChecked' }
}

export function Form() {
  const { form: { fields }, submit } = useForm({
    initialValues: { tos: false },
    fields: { tos: needsToBeChecked },
    onSubmit: x => { console.log(x) },
  })

  return (
    <form onSubmit={submit}>
      <FormCheckbox label='I agree with the Terms of Service' field={fields.tos} />
      <button type='submit'>Submit</button>
    </form>
  )
}
function FormCheckbox({ label, field }) {
  const { name, state, eventHandlers } = useBooleanFormField(field)
  const { showError, error, value } = state
  console.log(showError, error)
  return (
    <>
      <div>
        <label htmlFor={name}>{label}</label>
        <input id={name} type='checkbox' checked={value || false} {...{ name }} {...eventHandlers} />
      </div>
      {showError && <p>{error.id}</p>}
    </>
  )
}

I would expect the error to be shown as soon as we uncheck the checkbox. However,showError is always false until we submit the form.

Checkbox and required

I try to make a form with a required checkbox, for example 'I agree with the terms of service'. See the reduced test case below:

import { useBooleanFormField, useForm } from '@kaliber/forms'
import { required } from '@kaliber/forms/validation'

export function Form() {
  const { form: { fields }, submit } = useForm({
    initialValues: { tos: false },
    fields: { tos: required },
    onSubmit: x => { console.log(x) },
  })

  return (
    <form onSubmit={submit}>
      <FormCheckbox label='I agree with the Terms of Service' field={fields.tos} />
      <button type='submit'>Submit</button>
    </form>
  )
}
function FormCheckbox({ label, field }) {
  const { name, state, eventHandlers } = useBooleanFormField(field)
  const { showError, error, value } = state
  console.log(showError, error)
  return (
    <>
      <div>
        <label htmlFor={name}>{label}</label>
        <input id={name} type='checkbox' checked={value || false} {...{ name }} {...eventHandlers} />
      </div>
      {showError && <p>{error.id}</p>}
    </>
  )
}

However this will not work, because the required validation function explicitly allows false as a value. Meaning that there will never be an error.

We could solve this by writing our own validation function:

function needsToBeChecked(x) {
  return x !== true && { id: 'needsToBeChecked' }
}

export function Form() {
  const { form: { fields }, submit } = useForm({
    initialValues: { tos: false },
    fields: { tos: needsToBeChecked },
    onSubmit: x => { console.log(x) },
  })
 ...

Is this the correct way to deal with this?

Hook into changed form state

Say I want to do something effectful with the formState, every time it changes (e.g. store the values in localStorage, so the form can be restored on a reload). What would be the best way to do this?

The initial thought may be to use useFormFieldValue(form), but this will of-course re-render the whole form onChange (which is what this library explicitly wants to prevent.

Right now, we made a separate component, which uses this hook and calls a callback prop whenever the value changes. Maybe it would make sense to add an onChange property to the useForm config?

Example:

const { form: { fields }, submit } = useForm({
    initialValues: {}
    fields: {},
    // handle form change
    onChange: handleChange,
    // handle form submit
    onSubmit: handleSubmit,
  })

Cannot use props from outside render function scope, due to useMemo

I'm running into problems using the FormFieldValid component with the following setup:

function NewsletterForm({ form, formSubmitting, onSubmit }) {
  const { fields } = form

  return (
    <form {...{ onSubmit }}>
      <Fields {...{ fields }} />
      <FormFieldValid field={form} render={valid => (
        <Button 
          type="submit" 
          disabled={formSubmitting || !valid} 
          loading={formSubmitting}
        >
          Meld je aan
        </Button>
      )} />
    </form>
  )
}

In the code changes in formSubmitting are never picked up, because the render result is memoized based on the validity.

All fixes I could think of have some kind of drawback:

  • Allow user to pass extra props to the FormFieldValid:
export function FormFieldValid({ field, props = [], render }) {
  const { invalid } = useFormFieldSnapshot(field)
  return React.useMemo(() => render(!invalid, ...props) || null, [invalid, ...props])
}

Seems unelegant. Might be difficult if the render component return a big portion of form which uses a lot of props.

  • Require user use a useCallback for render and include the render function as a memo dependency:
export function FormFieldValid({ field, render }) {
  const { invalid } = useFormFieldSnapshot(field)
  return React.useMemo(() => render(!invalid) || null, [invalid, render])
}

I think this would make it impossible to render the whole form in one place, because the useCallback cannot be done inline.

  • Remove the useMemo. Also suboptimal because the component would rerender a lot more often.

@EECOLOR What do you think?

Perfomance inprovement for validity

const { invalid } = useFormFieldSnapshot(field)

FormFieldValid is now implemented with useSnapshot which means it will render on keystrokes. We could add another hook that prevents these unneeded renders, something like this:

function useFormFieldInvalid(field) {
  const [formFieldInvalid, setFormFieldInvalid] = React.useState(() => snapshot.get(field).invalid)

  React.useEffect(
    () => {
      setFormFieldInvalid(snapshot.get(field).invalid)
      return snapshot.subscribe(field, x => setFormFieldInvalid(x.invalid))
    },
    [field]
  )

  return formFieldInvalid
}

Duplicate form id's when using multiple forms on same page (PHP)

When using two or more forms on the same page in PHP, I'm getting the following message:

Warning: Prop `id` did not match. Server: "form1.email" Client: "form2.email"
    in input (created by FormFieldText)
    in div (created by FormFieldText)
    in FormFieldText (created by EmailForm)
    in form (created by EmailForm)
    in EmailForm (created by NewsletterFormApp)
    in div (created by NewsletterFormApp)
    in NewsletterFormApp

[DOM] Found 2 elements with non-unique id #form1.email:

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.