shadcn Form

Hello im having two forms made with shadcn components and react-hook-from Controller for validation The idea is when u fill the first form and submit it. The second form takes the first one place. I added a cancel button to take the user back to the the first one . I want it with all the fields filled up with the previous data but idk how to do it through the controller. That's a code snippet.
<FormField
control={form.control}
name="Nom"
render={({ field }) => (
<FormItem>
<FormControl>
<div className="flex flex-col space-y-1.5">
<Label
htmlFor="Nom"
className="text-lg flex justify-between"
>
Nom
<FormMessage />
</Label>
<Input
{...field}
id="Nom"
placeholder="John"
className={` ${
form.formState.errors.Nom &&
"border-err placeholder:text-destructives"
} text-md py-5 placeholder:opacity-40 rounded-sm border-[3px] `}
/>
</div>
</FormControl>
</FormItem>
)}
/>
<FormField
control={form.control}
name="Nom"
render={({ field }) => (
<FormItem>
<FormControl>
<div className="flex flex-col space-y-1.5">
<Label
htmlFor="Nom"
className="text-lg flex justify-between"
>
Nom
<FormMessage />
</Label>
<Input
{...field}
id="Nom"
placeholder="John"
className={` ${
form.formState.errors.Nom &&
"border-err placeholder:text-destructives"
} text-md py-5 placeholder:opacity-40 rounded-sm border-[3px] `}
/>
</div>
</FormControl>
</FormItem>
)}
/>
5 Replies
Kseikyo
Kseikyo15mo ago
If I understand what you're trying to achieve, you want a multi step form, there are multiple ways of doing it, by changing routes within a layout, using only one form provider and rendering each step according to some state. This is a simple example generated by chatgpt
import { useState } from 'react';
import { useForm } from 'react-hook-form';

const MultiStepForm = () => {
const { register, handleSubmit, formState: { errors } } = useForm();
const [currentStep, setCurrentStep] = useState(1);
const [formData, setFormData] = useState({});

const onSubmit = (data) => {
// You can handle form submission here, e.g., send data to the server
console.log('Form Data:', data);
};

const nextStep = () => {
setCurrentStep(currentStep + 1);
};

const prevStep = () => {
setCurrentStep(currentStep - 1);
};

const renderStep = () => {
switch (currentStep) {
case 1:
return (
<div>
<label htmlFor="Nom">Nom</label>
<input
{...register('Nom')}
type="text"
id="Nom"
placeholder="John"
className={` ${
errors.Nom && "border-err placeholder:text-destructives"
} text-md py-5 placeholder:opacity-40 rounded-sm border-[3px]`}
/>
</div>
);

// Add more cases for other form steps

default:
return null;
}
};

return (
<form onSubmit={handleSubmit(onSubmit)}>
<h2>Step {currentStep}</h2>
{renderStep()}

<div>
{currentStep > 1 && (
<button type="button" onClick={prevStep}>
Previous
</button>
)}
{currentStep < totalSteps && (
<button type="button" onClick={nextStep}>
Next
</button>
)}
{currentStep === totalSteps && (
<button type="submit">Submit</button>
)}
</div>
</form>
);
};

export default MultiStepForm;
import { useState } from 'react';
import { useForm } from 'react-hook-form';

const MultiStepForm = () => {
const { register, handleSubmit, formState: { errors } } = useForm();
const [currentStep, setCurrentStep] = useState(1);
const [formData, setFormData] = useState({});

const onSubmit = (data) => {
// You can handle form submission here, e.g., send data to the server
console.log('Form Data:', data);
};

const nextStep = () => {
setCurrentStep(currentStep + 1);
};

const prevStep = () => {
setCurrentStep(currentStep - 1);
};

const renderStep = () => {
switch (currentStep) {
case 1:
return (
<div>
<label htmlFor="Nom">Nom</label>
<input
{...register('Nom')}
type="text"
id="Nom"
placeholder="John"
className={` ${
errors.Nom && "border-err placeholder:text-destructives"
} text-md py-5 placeholder:opacity-40 rounded-sm border-[3px]`}
/>
</div>
);

// Add more cases for other form steps

default:
return null;
}
};

return (
<form onSubmit={handleSubmit(onSubmit)}>
<h2>Step {currentStep}</h2>
{renderStep()}

<div>
{currentStep > 1 && (
<button type="button" onClick={prevStep}>
Previous
</button>
)}
{currentStep < totalSteps && (
<button type="button" onClick={nextStep}>
Next
</button>
)}
{currentStep === totalSteps && (
<button type="submit">Submit</button>
)}
</div>
</form>
);
};

export default MultiStepForm;
Lumberjack
Lumberjack15mo ago
Well the multi step form is well handled in my case. I just want to make the first form preserve the data in the input fields. But with the use of shadcn components So when the user hit the cancel button he'll find his previous data filled in the inputs instead of re-typing it
Kseikyo
Kseikyo15mo ago
you're handling with multiple forms, you must be using multiple uses of useForm, in that case, if you're removing the entire form between each step, you can save that form data using local storage and on hit cancel, you get that data from local storage and set to the form. But in my opinion, it would be much easier to just have one form, and change only the inputs of the form on each step. That way, the form will have the data when the user hits cancel, shouldn't require any extra code.
Lumberjack
Lumberjack15mo ago
Well i did it in another way using a useState but idk how to make the data show again in the inputs
Keef
Keef15mo ago
I would avoid doing separate forms for each case and just rely on the useFormContext instead. If you decided to cache them into state or local storage you’ll just have to pass them into defaultValues and that’ll set up the state to be what it was originally
Want results from more Discord servers?
Add your server