Giter Site home page Giter Site logo

bearstudio / formiz Goto Github PK

View Code? Open in Web Editor NEW
391.0 7.0 50.0 11.38 MB

🐜 React forms with ease! Composable, headless & with built-in multi steps

Home Page: https://formiz-react.com/

License: MIT License

JavaScript 0.38% TypeScript 85.94% CSS 1.54% MDX 12.14%
react forms wizard multi-step-form form-validation form-validation-react formiz hacktoberfest form typescript

formiz's Introduction

Formiz

Documentation | Examples

npm install @formiz/core

πŸ‘‰ Getting Started

Features

  • πŸ— Composable API and validations
  • πŸ§™β€ Built-in multi steps
  • πŸ’… Headless, build your own UX!
  • πŸ“‹ Turn everything into fields
  • βš›οΈ Built with Typescript & hooks
  • πŸ“± React Native compatible

Concept

The idea behind Formiz is to allows you to build advanced forms with multiple steps, complex validations and a good UX without pain.

The main idea is to build fields as independent reusable components. Fields can be anything, not just inputs. Once you have built your fields, you can use them everywhere.

When you use a field built with Formiz, you can apply validations on it. Only the mounted fields will apply their validation to the current step and to the form.

// Field Example
<MyField
  name="email"
  type="email"
  required="Email is required"
  validations={[
    {
      handler: isEmail(),
      message: "Not a valid email",
    },
  ]}
/>

Contributing

Installation

Requirements

pnpm install

Development

pnpm dev

Sponsors

Thanks to our sponsors. Become one of them.

formiz's People

Contributors

acampbell12 avatar byeze avatar d-campbell-bs avatar decampsrenan avatar dependabot[bot] avatar doriandel avatar dylanflandrin avatar fabienessid avatar gregoire-bearstudio avatar hugoperard avatar ivan-dalmet avatar yoannfleurydev avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

formiz's Issues

Hydration - SSR

Hey guys,

First, thanks for this repo. I find it quite easy and straightforward. Wizzard forms are easy to do now.
But unfortunately, I run with SSR issues while loading the form.

Capture d’écran 2023-04-11 aΜ€ 20 30 01

I have another question, are you guys planning on releasing the v2 soon?

thanx

Using state values outside of Formiz

Is it possible to use state values outside of Formiz? Now, when component mounts Formiz is getting initial value of state but not subsequent changes. I tried to add changing variables in dependency array but that didn't help. Let me know if you need a code example.

Allow the message object in validations prop to be a function

Is your feature request related to a problem? Please describe.
I need to get the error from a useField wrapped component (CardElement from react stripe). This component has only the onChange event, regarding there was an error or not. The only way to get the error is to get the value returned from this component

Describe the solution you'd like
I would like the message string in validations array to be a function that return a string, or a string. So i can use it like this:

<StripeCardInput
  label="Card Informations"
  name="cardInfos"
  validations={[
    {
      rule: isRequired(),
      message: 'You need to fill your card infos',
    },
    {
      rule(value) {
        return !(value && value.error);
      },
      message: (value) => value.error,
    },
  ]}
/>

Describe alternatives you've considered
Know i'm trying to use the form.invalidateFields inside a useEffect

const form = useForm();
const { values, invalidateFields } = form;
const { cardInfos } = values;

useEffect(() => {
  if (cardInfos && cardInfos.error) {
    invalidateFields({ cardInfos: cardInfos.error.message });
  }
}, [cardInfos, form, invalidateFields]);

Formiz v2 - React 18

The v2 of Formiz is under heavy developments! πŸŽ‰

This v2 is focusing on performances, React 18 and internal code simplification for better contributions.
The BearStudio team is on the subject to release this new version as soon as possible. But we want to make sure that all the majors features of v1 will be supported and if not, to provide a migration guide. We hope to share an alpha with you before this summer 🀞

Follow this issue if you want updates about future alpha, beta and rc πŸ™‚

Async initialValues didn't work with useCollection

Hello, I'm testing Formiz v2 beta and I have some issues with useCollection hook.

Issue

It works fine with static data like:

const form = useForm({
    onValidSubmit(values, form) {
        console.log(values)
    },
    initialValues: {
        members: [
            { name: 'user1', email: '[email protected]' },
            { name: 'user2', email: '[email protected]' },
        ],
    },
})

const collection = useCollection({ connect: form, name: 'members' })

Thats ok, i got 2 items in collection.keys

But it doesn't work when I fetch data:

const { data, isLoading, isFetched } = useGroupQuery({ id: 1 })

const form = useForm({
    onValidSubmit(values, form) {
       console.log(values)
    },
    ready: isFetched,
    initialValues: data,
})

const collection = useCollection({ connect: form, name: 'members' })

collection.keys is empty

My returned data object looks like:

{
    group: { id: 1, name: 'group1' },
    members: [
        { name: 'user1', email: '[email protected]' },
        { name: 'user2', email: '[email protected]' },
    ],
}

I've seen that you remove the initialValues params from useCollection()

Did i missed something or Am i doing something wrong ?

Use of keepUnmounted and keepPristine in same setFieldsValues

Describe the bug

When I do the following code

setFiedsValues(values, { keepUnmounted: true, keepPristine: false });

the pristine state do not change, it's stay to true

CodeSandbox

https://codesandbox.io/s/lucid-curran-fzy8qq?file=/src/App.tsx

To Reproduce

  1. Have a form with pristine true
  2. Make a setFieldsValues with keepUnmounted: true and keepPristine: false
  3. Look at the form pristine value

Expected behavior

keepPristine: false should allow form isPristine value to be false after setFieldsValues

Desktop (please complete the following information)

  • OS: macos
  • Browser: Arc
  • Version 0.74.1

FEAT: maxLength/minLength options on useCollection

Is your feature request related to a problem? Please describe.
This feature can avoid to manually do some check if we want to build a collection with some length condition, for example with at least one element, or/and with 10 elements max

const collection = useCollection("collection");
...
{collection.length > 1 && <button>Remove item</button>
...
{collection.length < 10 && <button>Add item<button>}

Describe the solution you'd like
I'm thinking about two new states on the collection, with no name defined, that should transform previous to this :

const collection = useCollection("collection", { maxLength: 10, minLength: 1 });
...
{collection.canRemove && <button>Remove item</button>}
...
{collection.canAdd && <button>Add item</button>}

Access Form Values with Field's "name" String

Is your feature request related to a problem? Please describe.

Hello! I would like to pick your brain about some potential behavior. I've been using Formiz for a little bit now and love the implementation of nested fields. That being said, it would be awesome if I could extract a field from the form state using the same nested string that I used to create it.

Example:

// Field creation
<FormizWrappedField name="nested.field" defaultValue="Hello!" />

// Form structure
{
  nested: {
    field: "Hello!"
  }
}

// Access Field
const form = useForm();
const valueByObject = form.values.nested.field // Returns field value
const valueByString = form.values["nested.field"] // Always returns undefined

Is there a design choice as to why this is not possible? I figure that this behavior would also be consistent with the behavior of setFieldsValues because setFieldsValues can only set fields using nested strings and not objects, for instance:

form.setFieldsValues({"nested.field": "New Value!"}) // This will set the field's value
form.setFieldsValues({ nested: { field: "New Value!" }} ) // This will not

See the below Code Sandbox for a functional example.

Describe the solution you'd like
I'm not sure. I haven't looked through the source significantly as I wanted to get your thoughts on this first.

The only reason that I could see this not working would be if there was a non-nested field with a "." in it's name, BUT if that is true, then it should be a nested field anyway, right?

Describe alternatives you've considered
None as of yet! Happy to discuss them though!

Additional context
Code Sandbox

This library rocks!

Field errors show up after form reset

Is your feature request related to a problem? Please describe.
Not sure if this is a bug but when I submit my form, if it succeeds, I reset the form. In that case, all the fields errors show up as isSubmitted and isTouched are true and the fields are empty.

Describe the solution you'd like
Resetting the form should also reset the fields to their initial state.

Pristine update on collection remove

Describe the bug

When I arrived on a pristine form and I remove a collection item, the pristine still be at true

To Reproduce

In Formiz examples collection page : https://formiz-examples.vercel.app/collection

  1. In form debug on the right, isPristine is true
  2. Remove an item from the collection clicking on a trash icon button
  3. isPristine still true

Expected behavior

The pristine should be break on a collection removal

Additional context

In the current state of the library, there is no possible solution to do this, because form pristine state is defined by fields pristine state so in this case, pristine stay at true because "updated" (removed) field does not exist anymore.
So fix this bug requires to add somethings to manage this case, maybe a state on the collection or something else

Validate Input File

Hi,

we're trying to use Formiz with React Dropzone. Is there any way to validate the input file field?

Thank you!

Usefield defaultValue

Describe the bug
With react typescript i have a compilation erreur when i try to use defaultValue from useField hook

image (2)

for now i can fix it with any

image (3)

Carry the value of previous input onto next step

I was wondering if it's possible to carry the value of previous input onto the next step's input field as default value? I tried:

defaultValue={ myForm.values.name ] - This doesn't work
defaultValue="Some value here" - This does work

Default value with number 0 is not set

Describe the bug
If my default value is a number 0, the default value is not use

To Reproduce
with 0

<Field name="myField" defaultValue={0}  />

image

with 1

<Field name="myField" defaultValue={1}  />

image

Expected behavior
if defaultValue is init with 0, the default value should be display on field

Using localStorage or sessionStorage?

Is your feature request related to a problem? Please describe.
I'm working on a very long multi-step form with many dozens of conditional fields, and so far Formiz is my favorite solution. But I'm hoping to find a way to persist form state on a page refresh.

Describe the solution you'd like
I'd like a way to maintain form state in localStorage and/or sessionStorage such that the form survives a page refresh.

Describe alternatives you've considered
I've just started considering this and wondering about some approach that would save the entire form.values into local storage, and somehow default to those values if they exist but no idea if this will be possible.

Any thoughts or is this something you've ever considered? Thank you!

**Select only considers when all values are present in available options **A Feature that toggles an input field for user to enter custom option when "other" option is selected

Is your feature request related to a problem? Please describe.
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

Describe the solution you'd like
A clear and concise description of what you want to happen.

Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.

Additional context
Add any other context or screenshots about the feature request here.

File input not updating after first upload

Code

import * as React from 'react';
import { useField } from '@formiz/core';

function Upload(props) {
  const {
    setValue,
    value: fileList,
    isValid,
    isPristine,
    errorMessage,
    isSubmitted,
    id,
  } = useField(props);
  
  const { name, placeholder, icon, autoComplete, maxLength, label } = props;

  const formattedLabel = React.useMemo(() => fileList && fileList.length === 1
    ? fileList[0].name
    : fileList && fileList.length > 1
    ? `${fileList.length} files`
    : label, [fileList, label])
  
  return (
    <div>
      <input 
        type="file" 
        name={name} 
        placeholder={placeholder} 
        id={id} 
        onChange={({ target }) => setValue(target.files)}/>
      <label htmlFor={id}>{formattedLabel}</label>
    </div>
   )
}

// Usage
import { Formiz, useForm } from '@formiz/core';
import Upload from 'components/upload/Upload';

function Profile() {
  const form = useForm();
  
  const handleValidSubmit = (values) => console.log(values);

  return (
    <Formiz onValidSubmit={handleValidSubmit} connect={form}>
      <form noValidate onSubmit={form.submit}>
        <Upload 
           name="files"
           label="Attach files"
        />
      </form>
    </Formiz>
  )
}

Issue

When I first upload a file and submit, it works as expected, but when I upload again without clearing file input and submit I get stale result (always the first upload).

I inspected this with react dev tools, and state for the file input is only being updated on initial upload.

Any help will be appreciated if you have any free time πŸ˜„

Issue with conditional render of <Formiz /> with useForm() and connect

Conditionally rendering the <Formiz> tag has a bug in v1.0.0 sadly :/

The following code is not working as expected in 1.0.0

const Demo = ({ isLoading }) => {
  const form = useForm();
  
  return (
    <div>
       {isLoading ? 'Loading...' : (
          <Formiz connect={form}>
            <form noValidate onSubmit={form.submit}>
              ...
            </form>
          </Formiz>
       )}
    </div>
  )
}

Turn around until the lib is fixed
Just declare the <Formiz> component outside of the condition.

const Demo = ({ isLoading }) => {
  const form = useForm();
  
  return (
    <Formiz connect={form}>
      <div>
         {isLoading ? 'Loading...' : (
           <form noValidate onSubmit={form.submit}>
             ...
           </form>
         )}
      </div>
    </Formiz>
  )
}

I will update this issue when this is fixed.

Dynamic number of form steps?

Is your feature request related to a problem? Please describe.
I'm working on an extremely long and complicated governmental form that requires people to input detailed information about each child they have. The number of children is unknown until a user hits that point in the form.

I originally was using a Repeater field but it became overwhelming if a user has something like 8 children (due to the large amount of fieldsx8 on one screen.) I then switched to an accordion based solution by passing the number of children involved from one step to the next; from here I can create one accordion for each child, which works but also also proved to be a bad UX with a large number of children.

What I am attempting instead is to use one form "step" per child, based on the number of children the user inputs on the previous form step. So for example:

Step 1: How many children to you have? (enter number)

Step 2: Enter the details for Child 1 (enter many fields)

Step 3: Enter the details for Child 2 (enter many fields)

Step 4: Continue with rest of form

and so on, where there is an unknown number of children.

Describe the solution you'd like

I'm looking for a way that Formiz can adjust to this scenario in a clean way.

Describe alternatives you've considered

I have a work-in-progress but it turns out there are some problems as described below. In the main page of my app I define each step roughly as so:

     <MultiStepsLayout
              form={form}
              onValidSubmit={handleSubmit}
              submitLabel="Finish!"
       >
           <PageHeader>My app</PageHeader>
                <InitiateInterview  />
                <BasicInformation />
                <NumberOfChildren />
                <EnterChildren /> --- unknown number of children!
                ...
                <End />
              </>
       </MultiStepsLayout>

I pass the number of children to the EnterChildren step, and from there I have a loop like so:

      {Array.apply(null, { length: numberChildren }).map((e, index) => (
        <FormizStep key={index} name={`EnterOtherChildren` + index}>
          <SectionWrapper>
            <Box mb="8">
              <SectionHeader
                header={`Enter the details for Child ` + (index + 1) + `:`}
              />
            </Box>
             ...many fields
           </SectionWrapper>
        </FormizStep>
      ))}

At first this working just about perfect, until I added any steps AFTER the EnterChildren step.

In the example above, I have an "End" step (in the real world there will be additional steps). When it is there the app goes first to this End step, and then circles back to the EnterChildren step.

What I would love to happen is for the total number of "steps" to adjust based on how many children there are, and for the rest of the app to flow from there.

(Another thing I noticed is that the number to total steps (Step n/n) updates correctly when I select a number of children but if I change that number (say from 4 to 2) it does not adjust accordingly and still thinks there are two additional steps.)

Additional context
I realize I may be pushing this beyond where it was meant to go but I feel like it is very close :)

Validation with Material UI - RadioGroup

Hi,

I'm not sure if you already had this issue or if I'm doing something wrong, but I'm trying to validate a RadioGroup, from Material UI, and the validation goes well, but the first time the user clicks on a radio button, the error message shows up and then hides immediately. By the way, none of the radios are selected by default.

Here's the code:

import { useField } from '@formiz/core';

import FormControlLabel from '@material-ui/core/FormControlLabel';
import RadioGroup from '@material-ui/core/RadioGroup';
import Radio from '@material-ui/core/Radio';
import Box from '@material-ui/core/Box';


const InputRadio = (props) => {

    const {
      id,
      radioOptions
    } = props;
    
    const {
      errorMessage,
      isValid,
      isPristine,
      isSubmitted,
      value,
      setValue
    } = useField(props);

    const handleChange = function(event) {
        setValue(event.target.value);
    }
    
    const showError = !isValid && (!isPristine || isSubmitted);    
      
    return (
      <RadioGroup 
        id={id} 
        name={id} 
        value={value} 
        onChange={handleChange}>
          {radioOptions.map((radioOption, i) => (
            <Box key={i}>
              <FormControlLabel 
                value={radioOption.factor} 
                control={<Radio color='primary' />} 
                label={radioOption.value} 
              />
            </Box>
          ))}
          {showError && (
            <div id={`${id}-error`} className="error-description">
              { errorMessage }
            </div>
          )}
      </RadioGroup>
    )
  }

  export default InputRadio;

I've used Formiz previously but without Material UI, and I've never had this problem...
I hope you can help me out with this.

Thank you!

Step Animations/Transitions

Is your feature request related to a problem? Please describe.
This isn't really related to a problem, curious if there is any plan in the roadmap to implement the ability to add transitions of some sort? I am currently trying to implement Framer Motion to animate the transition between steps and it appears its not possible without some changes to Formiz.

Describe the solution you'd like
After looking through the docs and messing with code, you can only pass a string in the as prop on the formizStep component. I've tried passing a component to the as prop to no avail. It would be nice to be able to do something like the following to accomplish this:

<FormizStep
     name={step.cardTitle}
     isEnabled={checkStepConditional(step)}
     as={
         <motion.div
             initial={{ opacity: 0 }}
             animate={{ opacity: 1 }}
             exit={{ opacity: 0 }}
         />
     }
>
...

useForm is not working as expected.

Describe the bug

When I use useForm in an Expo managed project, I receive an error related to the 'os' module. I can only use the project correctly when I add the 'os' library to my projects

To Reproduce

  1. Install formiz to expo managed app
  2. import & use useForm

Expected behavior

Being able to use formiz without installing an additional module

Screenshots

Screenshot 2024-01-23 at 10 35 08
Screenshot 2024-01-23 at 09 29 30

Smartphone (please complete the following information)

  • Device: iPhone 15 Pro
  • OS: IOS17.2

Add strict max & min number validations

Is your feature request related to a problem? Please describe.
When validating numbers, the current implementations of isMinNumber and isMaxNumber do not support strict inequality, meaning that the limit will always be a valid value.

Describe the solution you'd like
I'd like to have the possibility to declare a strict minimum or maximum value for which the equality will result in an invalid field.

Describe alternatives you've considered
I see two ways of handling this:

  • add a parameter to the current isMinNumber & isMaxNumber. I can see a call to the validation be something like isMinNumber(0, {strict: true}) with the strict mode being set to false by default.
  • add a different validation that will handle this case. It would basically use the same code as the current versions but with a strict inequality instead.

No validation for inputs of type number in firefox

Describe the bug

When using an input of type number, adding validation rules isMaxNumber or isMinNumber won't trigger validation error when the value is not a number.

Code

const MyField = (props) => {
  const { value, setValue, isValid, errorMessage } = useField(props);

  const handleChange = (e) => {
    setValue(e.target.value);
  };
  return (
    <>
      <input type="number" value={value} onChange={handleChange} />
      {!isValid && { errorMessage }}
    </>
  );
};

const Demo = () => {
  const form = useForm();
  return (
    <Formiz autoForm connect={form} onValidSubmit={console.log}>
      <MyField
        name="number"
        validations={[
          { rule: isMinNumber(0), message: 'Too low' },
          { rule: isMaxNumber(100), message: 'Too high' },
        ]}
      />
      <button onClick={() => form.submit}>Submit</button>
    </Formiz>
  );
};

Expected behavior

A validation error should trigger when not number values are used in the field.

Version

  • OS: Linux
  • Browser: Mozilla Firefox 90.0

Additional context

  • The bug won't happen in Chrome because inputs of type number are controlled by the browser to prevent bad values in the field.
  • In Firefox, the values are controlled when submitted. If the value of the field is not a number, the validation will pass, but the value returned by the form will be null.
  • In Firefox, if the value is a valid number, but too high or too low, the validation will trigger.

Wizard Form Transitions

Hi,

Is there a way to create transitions between steps? Currently, I have a custom "submitStep" function to manipulate the visible step. The issue is that it won't work when you trigger the hook "nextStep" with the navigation item, unless with pass some parameters and create some messy js code.

I was wondering if there's an "onChange" hook that is aware of the current and next steps.

Thanks!

Error when submitting step with Enter key press

When I hit the Enter key in an input field, I expect the form step to be submitted but it's not, and an error is thrown in the console.

How to reproduce:
Go to documentation demo page: Click in the input field, and then press enter. The step is not submitted and an error is thrown in console.

Syncing Fields

Is your feature request related to a problem? Please describe.

First of, I recently found this library, and I love it for so many reasons! So thank you for all the work you put in!

I found myself in a situation where I have a field that I would like to show in two places. I have wrapped Material-UI inputs using useField() (see sandbox below) and expected that if I supplied the same name property to useField() that the forms would stay synced since useField() would pull from the same internal state.

For example:

<Formiz connect={form} >
    <CustomField name="syncedField" /> // call this Field1
    <CustomField name="syncedField" /> // call this Field2
</ Formiz>

I have found that not to be the case. Both useField() calls will alter the same state when setField is called, but there is no reactivity. For instance, if Field1 sets the value to "test", the form state changes but the value property returned by useField() in Field2 is not altered. This means that if someone types "a" into Field2 then the form state is altered to "a" but the input of Field1 remains "test"

A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

Describe the solution you'd like

All I'm looking for is guidance on best practices to be able to sync fields with each other. Guidance on how to effectively set fields programmatically would be helpful as well (see below).

Describe alternatives you've considered

When I came across this, I thought that a solution might be to use setFieldsValues() (similar to #18 ) on each change of the field, i.e.

<Formiz connect={form} >
    <CustomField name="syncedField" 
        onChange={ (value) => {
            form.setFieldsValues({"syncedField": value)
        } />
    <CustomField name="syncedField"         
        onChange={ (value) => {
            form.setFieldsValues({"syncedField": value)
        } />
</ Formiz>

While this does keep the two fields in sync, I'm finding that a side-effect of this is that it clears the other fields (see the Address input in the sandbox below) whenever setFieldsValues() is not called. This behavior also confused me a little as I thought setFieldsValues() would patch the form, but perhaps that is intended behavior.

Thanks again for this awesome library. Truly a hidden gem!

Additional context
Code Sandbox

FEAT: Add a Formiz Devtools

Is your feature request related to a problem? Please describe.
The obligation to console log fields or form state to debug

Describe the solution you'd like
A devtools to help development and debug

Additional context
A PR is already open here : #193

Pls expose useFormContext

Im trying to made my own version of the FormStep because I need the inputs to stay in the dom instead of just disappearing (https://github.com/ivan-dalmet/formiz/blob/master/packages/core/src/FormizStep.tsx#L94).

This is my code, its almost the same except for the render part, the error happends on the last import (import { useFormContext } from "@formiz/core/dist/Formiz") because the useFormContext isn't expose at the root:

import { createContext, FC, useContext, useEffect, useRef, useState, RefObject } from "react"
import { Collapse } from "@chakra-ui/react"
import { FormizStepProps, StepState } from "@formiz/core/dist/types/step.types";
import { FormState } from "@formiz/core/dist/types/form.types";
import { useFormContext } from "@formiz/core/dist/Formiz";

// https://github.com/ivan-dalmet/formiz/blob/master/packages/core/src/FormizStep.tsx

export const getFormUniqueId = (): string => `form-${Math.random().toString(36).substr(2, 9)}`;

export const defaultFormState: FormState = {
  id: getFormUniqueId(),
  resetKey: 0,
  isSubmitted: false,
  isValidating: false,
  isValid: true,
  isPristine: true,
  steps: [],
  initialStepName: null,
  navigatedStepName: null,
};


export const StepContext = createContext<any>({});
export const useStepContext = (): any => useContext(StepContext);

export const useRefValue = (value: any): RefObject<any> => {
  const ref = useRef(value);
  ref.current = value;
  return ref;
};

export const FormStep: FC<FormizStepProps> = ({ as: Tag = "div", ...props }) => {

  const {
    formStateRef,
    actions,
    subjects,
  } = useFormContext();

  const [formState, setFormState] = useState(formStateRef?.current ?? defaultFormState);
  const [state, setState] = useState<Partial<StepState>>({
    name: props.name,
    label: props.label,
    isVisited: false,
    order: props.order ?? 0,
  });


  const isActive = formState.navigatedStepName
    ? formState.navigatedStepName === props.name
    : formState.initialStepName === props.name;

  const actionsRef = useRefValue(actions);
  const subjectsRef = useRefValue(subjects);

  useEffect(() => {
    const subscription = subjectsRef.current.onFormUpdate
      .subscription
      .subscribe(setFormState);
    return () => subscription.unsubscribe();
  }, [subjectsRef]);

  useEffect(() => {
    if (isActive && !state.isVisited) {
      setState((prevState) => ({ ...prevState, isVisited: true }));
    }
  }, [isActive, state.isVisited]);

  useEffect(() => {
    actionsRef.current.updateStep({
      ...state,
      isEnabled: props.isEnabled,
    });
  }, [actionsRef, state, props.isEnabled]);

  useEffect(() => () => {
    actionsRef.current.unregisterStep(props.name);
  }, [actionsRef, props.name]);


  return (
    <StepContext.Provider value={{ name: props.name, }}>
      <Tag
        style={{
          ...props.style,
        }}
        {...props}
      >
        <Collapse in={isActive}>
          {props.children}
        </Collapse>
      </Tag>
    </StepContext.Provider>
  );
}

export default FormStep

Delete collection on unmount

Describe the bug

When a collection definition is unmount (the useCollection hook), the collection is not remove from form. That mean if we remount the collection, we keep the keys previous collection keys.

Expected behavior

We want the collection to be delete on useCollection hook unmount.

Form not rendering when page is loaded in time not to make screen jump

Describe the bug
When you load the page with a multi-step form made with Formizi the screen appears to be "jumping"...most likely beause it takes a few miliseconds to render.

To Reproduce
Steps to reproduce the behavior:

  1. Go to https://novo-app-coleta.hyerdev.app/

Expected behavior
I expect it not to 'jump'...or if the is no way around it...a way of knowing if its rendering...So I can for example, make use of Skeleton Loading...

Screenshots
https://user-images.githubusercontent.com/37699234/140548277-295ef7c9-9069-451a-a841-6f65cb76d43f.mp4

Desktop (please complete the following information):

  • OS: Windows
  • Browser: Chrome
  • Version: latest

Multiple renders

Describe the bug
It seems like the forms get rendered multiple times from what I can see in the console ? Why ? Any workaround possible ?

To Reproduce
Steps to reproduce the behavior:

  1. Open console log
  2. Look at console
  3. See 3 renders
  4. Question my existence

Expected behavior
Only render once or explain why it happens

Can't See Steppers Page "previous" Button on Dark Mode

Describe the bug

Bug where the color of the previous botton on the steppers page isn't configured to change when dark mode is on. So it is the same color as the background (white).

Desktop

  • OS: Windows
  • Browser: Edge

Error when hiding step B in Conditional Fields & Steps in Demos

Describe the bug
on the Conditional Fields & Steps in Demos Tab
when on the step B and clicking Hide step B, an error get fired:

TypeError: Cannot read properties of null (reading 'name')

To Reproduce
Steps to reproduce the behavior:

  1. Go to 'https://formiz-react.com/docs/demos/conditional'
  2. Click on 'step B'
  3. Click on 'Hide Step B' Button
  4. See error

Expected behavior
The step B get deleted without any error.

Screenshots
chrome-capture

Desktop :

  • OS: Windows / Ubuntu
  • Browser Edge
  • Version 94.0.992.31

Can't get Checkbox Field to be valid - React Native

Hi Ivan ! Little Newbie here πŸ‘‹

I created a Checkbox component based on the MyField Component example. But I can't quite get it to be valid even if my checkbox is checked. My checkboxes are in a Formiz Step. Here is my code for the Checkbox component :

const MyCheckbox = (props) => {
  const { errorMessage, isValid } = useField(
    props
  );
  const {
    title,
    required,
    name,
    style,
    ...otherProps
  } = props;
  const [isChecked, setChecked] = useState(false);
  const showError = !isValid && !isChecked;

  return (
    <View>
      <CheckBox
        title={title || ""}
        containerStyle={styles.containerStyle}
        checkedIcon="dot-circle-o"
        uncheckedIcon="circle-o"
        checkedColor="#FF8585"
        checked={isChecked}
        required={required}
        onPress={() => setChecked(!isChecked)}
        {...otherProps}
      />
      {showError && <Text style={styles.errorText}>{errorMessage}</Text>}
    </View>
  );
};

The required message is displaying when i don't check the boxes, so that's good. But Formiz doesn't consider my checked boxes as valid...
Am I doing something wrong ? 😳

Best regards,
Prisca

support rtl

thanks for this tools.
Your plugin supports rtl؟

How to capture individual step submissions?

Hey, I was wondering if there is way to capture individual step submissions.
There is onValidSubmit on <Formiz /> that captures the values at the end of steps. I would like to make an API call for each valid step and validate the values on the server as well before moving to the next step.

Is there way to do it like so:

const makeCall = () => {...}
const makeAnotherCall = () => {...}

<FormizStep onValidSubmit={makeCall} />
// fields
<FormizStep onValidSubmit={makeAnotherCall} />

<button type="submit">{myForm.isLastStep ? 'Submit' : 'Next'}</button

I tried adding individual buttons to each step, but it works onClick, not with enter key.
Is there any way I can achieve this with Formiz? Or maybe a workaround?

Thank you for this awesome library. I love it.

formiz wizard with React Native

Hi,

I just discovered Formiz and I love it. I was just wondering if you had a more complete example on how to use the wizard form with react native like this one : Wizard

I understand that we have to put the as={View} on the FormizStep component but there's so much to add I think, like the form surrounding all the steps with the onSubmit button etc.

So if you have that on hand that would be awesome !
Thank you so much for your help,

Prisca

SSR id problem

Little issue when using NextJS with SSR rendering:

It works as expected, but I still get this error in development only

CleanShot 2020-07-03 at 18 42 36@2x

React 18 asyncValidations doesn't work anymore

Hello !
I upgrade to react 18 and the asyncValidations rules doesn't not work anymore.

const { isValidating } = useField(props)

isValidating always return true

I try to find a solution working around react-18-upgrade-guide Promises but I dont really understand where the problem come from.

Thank you for your amazing lib !

Can't access form.values

Describe the bug
Using

const form = useForm({ subscribe: 'form' });

Based on Steppers example, form.values is undefined, is that expected behavior? Shouldn't it be accessible for validations as password confirmation?

Maybe it's all about me and another JS issue because I'm quite bad at it :D.

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.