npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

use-formidable

v2.6.0

Published

Handle big nested forms and use live modifiers and validators with a simple react hook

Downloads

131

Readme

use-formidable

What does it do

  • It handles deeply-nested complex data structure in a dead-easy declarative way,
  • It handles any kind of inputs (it turns checkboxes into booleans and handles files input),
  • It comes with a set of live modifiers and validators, and it lets you use custom validators,
  • Types are included for typescript, it is lightweight and has no dependencies,
  • Use it with use-wizard to handle complex multi-path, multi-steps nested forms

Get started 🚀

Install it

npm i use-formidable

Call it

const useForm = require('use-formidable');

or

import {useForm} from "use-formidable";

Initialize your form data

Declaring an initialForm is not mandatory, you can pass an empty object, it will be updated on the go.

const initialForm = {
    identity: {
        firstName: "",
        lastName: "",
        dateOfBirth: "",
        description: "",
    },
    contact: {
        email: "",
        phone: "",
        location: {
            country: "",
        },
    },
    subscribedToMailingList: false,
    numberOfAnything: 0,
};

Declare useForm like you would declare any other hook

const [form, updateForm, formidable] = useForm(initialForm);

You get 3 objects:

  • form holds the values of your form
  • updateForm is used to update the form's data (check bellow)
  • formidable holds specific methods (check bellow)

And finally just declare your managed components

Call updateForm() to update the form. You can pass an object to enable live modifiers (check doc bellow).

<!-- Text inputs -->
<input type={"text"} name={"identity.firstName"} onChange={updateForm()} value={form.identity.firstName} />

<!-- Number inputs -->
<input type={"number"} name={"numberOfAnything"} onChange={updateForm()} value={form.numberOfAnything} />

<!-- Date inputs -->
<input type={"date"} name={"identity.dateOfBirth"} onChange={updateForm()} value={form.identity.dateOfBirth} />

<!-- A textarea -->
<textarea name={"identity.description"} onChange={updateForm()} value={form.identity.description}>
</textarea>

<!-- A select -->
<select name={"contact.location.country"} onChange={updateForm()} value={form.contact.location.country}>
    <option value={""} disabled={true}>-- Choose one --</option>
    <option value={"France"}>France</option>
    <option value={"Finland"}>Finland</option>
</select>

<!-- Checkboxes (the beloved) -->
<input type={"checkbox"} name={"subscribedToMailingList"} onChange={updateForm()} value={form.subscribedToMailingList} />

<!-- Radios -->
<!-- Email -->
<!-- Password -->
Examples are comming, but principle is exactly the same as aboove

You can also call updateForm yourself in a function like this:

updateForm()({target: {type: "custom", name: "name", value: "value"}});

Check further rules in the doc

Doc 🔖

  • Live modifiers: live modifiers change the input before updating form data. To use them, set them to true in the brackets when calling updateForm({}).

    • toLowerCase: true will apply toLowerCase()
    • toUpperCase: true will apply toUpperCase()
    • toCapitalized: true will capitalize the string
    • toNumber: true will extract numbers and '.' from a string to turn it into a number
    • toKeepNumbers: true will only keep numbers in a string
    • maximumLength: 130 will prevent user from typing more than n characters
    • custom: (input: any) => any allows you to pass a custom modifier (must return the new value)
  • Validators: Validators help you to give a real-time feedback to your users on what's missing / wrong about their data. They are part of the formidable object.

    • isEmail(value) checks if a value is an email
    • isLengthAbove(value) checks if a value is above or equal to minimum length
    • isLengthUnder(value) checks if a value is under or equal to a maximum length
    • isFileMime(file, ["jpeg", "gif"]) checks if a file MIME TYPE is in the array (accepted values to check are: "pdf" | "jpeg" | "png" | "gif" | "svg" | "doc" | "docx" | "odt" | "xls" | "xlsx" | "ods" | "csv")
    • isFileSmallerThan(file, size) checks file size in bytes
    • isCustomRegex(value, regex) checks if a value matches a custom regex (your function must have two parameters: the value to check and the regex)
    • isCustomValidator(value, (value) => boolean) checks if a value matches a custom function (your function must have the "value" parameter and return a boolean)
  • Displayers: Displayers are specific modifiers. They help you to modify a value when it is displayed.

    • displayerSpacesToThousands(value) adds spaces in a number (or a string), all 3 numbers (1234 will become 1 234). It returns a string.
  • Other methods: They are part of formHandler object.

    • getInitialForm returns the initial state
    • reset resets all values
    • set sets a new state for the form (useful for data fetching)
    • cancel cancel the last input that was modified <-- not available yet
  • Which inputs are handled ?

    • checkbox
    • color
    • date
    • datetime-local
    • email
    • file
    • hidden
    • month
    • number
    • password
    • radio
    • range
    • text
    • textarea
    • search
    • select-one
    • tel
    • time
    • url
    • week
    • To use a custom input, just call
        // Be carefull, there are () twice
        updateForm()({target: {type: "custom", name: "name", value: "value"}});
  • What you should be carefully about regarding components

    • Your input must always have a name
    • If the data you want to update is nested, declare the name as the path separated by '.' like in the examples above

Go further

  • Use it with use-wizard to build multi-paths, multi-steps wizards

Great alternatives

You have more robust battle-tested solutions out there

  • Formik helps you to declare form components, this is a great solution, but I like keeping control over my components
  • react-hook-form is a React hook, which makes it closer to this one