Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

leyeaa's avatar
Level 1

Inertia Submitting form array and validation in React JS

Hello, Please I am developing an application with React JS, Inertia and Laravel that require users to submit their academic qualifications. I want the user to be able to add additional form row for more qualifications or remove as the case may be and to be able to submit the form as an array of values and as well validate the values in the array when the form is finally submitted to laravel controller. I have only done this before with traditional php/html but couldn't figure out how best to achieve this in React/Inertia

I want to store all the qualifications as array in data.qualifications with keys that correspond to the index of the map. The same for data.institution, data.course and data.date_of_graduation

I also tried this //setData("qualification", data.qualification.map((q,index) =>index === id ? e.target.value : q) in setting the value, but this only work if I set default values for the qualification array in the useForm hook while the data.qualification.splice(id,1,e.target.value) does not work.

I need advise on how best to approach this. Thank you.

0 likes
2 replies
susansiniard's avatar

Hello, I think instead of using splice, which doesn’t trigger a re-render, you can create a new array with the updated values. Use the onChange event to update the specific index in your state. When submitting the form, the data will be automatically structured as an array since you're maintaining it as such in the state.

Here's the updated code:

javascript

Copy import React, { useState } from 'react'; import { useForm } from '@inertiajs/inertia-react'; import { usePage } from '@inertiajs/inertia-react';

const StaffEducation = () => { const user = usePage().props.auth.user; const { data, setData, post, processing, errors } = useForm({ staffid: user.username, qualification: [''], institution: [''], course: [''], date_of_graduation: [''], });

const [educations, setEducations] = useState([0]);

const handleAddEducation = () => {
    setEducations([...educations, educations.length]);
    setData('qualification', [...data.qualification, '']);
    setData('institution', [...data.institution, '']);
    setData('course', [...data.course, '']);
    setData('date_of_graduation', [...data.date_of_graduation, '']);
};

const handleRemoveEducation = (index) => {
    setEducations(educations.filter((_, i) => i !== index));
    setData('qualification', data.qualification.filter((_, i) => i !== index));
    setData('institution', data.institution.filter((_, i) => i !== index));
    setData('course', data.course.filter((_, i) => i !== index));
    setData('date_of_graduation', data.date_of_graduation.filter((_, i) => i !== index));
};

const handleInputChange = (index, field, value) => {
    const updatedArray = [...data[field]];
    updatedArray[index] = value;
    setData(field, updatedArray);
};

const handleSubmit = (e) => {
    e.preventDefault();
    post('/your-submit-route'); // update this with your actual route
};

return (
    <>
        <h5 className="card-title text-center">Education and Qualifications</h5>
        <form onSubmit={handleSubmit}>
            <table className="table">
                <thead>
                    <tr>
                        <th>#</th>
                        <th>Qualification</th>
                        <th>University/College</th>
                        <th>Course/Programme</th>
                        <th>Date of Graduation</th>
                        <th>Action</th>
                    </tr>
                </thead>
                <tbody>
                    {educations.map((_, index) => (
                        <tr key={index}>
                            <th scope="row">{index + 1}</th>
                            <td>
                                <input
                                    type="text"
                                    className="form-control"
                                    placeholder="e.g B.Sc"
                                    value={data.qualification[index] || ''}
                                    onChange={(e) => handleInputChange(index, 'qualification', e.target.value)}
                                />
                            </td>
                            <td>
                                <input
                                    type="text"
                                    className="form-control"
                                    placeholder="University/Institution"
                                    value={data.institution[index] || ''}
                                    onChange={(e) => handleInputChange(index, 'institution', e.target.value)}
                                />
                            </td>
                            <td>
                                <input
                                    type="text"
                                    className="form-control"
                                    placeholder="Course"
                                    value={data.course[index] || ''}
                                    onChange={(e) => handleInputChange(index, 'course', e.target.value)}
                                />
                            </td>
                            <td>
                                <input
                                    type="date"
                                    className="form-control"
                                    value={data.date_of_graduation[index] || ''}
                                    onChange={(e) => handleInputChange(index, 'date_of_graduation', e.target.value)}
                                />
                            </td>
                            <td>
                                {index === 0 ? (
                                    <button type="button" className="btn btn-primary" onClick={handleAddEducation}>
                                        Add
                                    </button>
                                ) : (
                                    <button type="button" className="btn btn-danger" onClick={() => handleRemoveEducation(index)}>
                                        Remove
                                    </button>
                                )}
                            </td>
                        </tr>
                    ))}
                </tbody>
            </table>
            <button type="submit" className="btn btn-success" disabled={processing}>
                Submit
            </button>
        </form>
    </>
);

};

export default StaffEducation;

leyeaa's avatar
Level 1

@susansiniard Thank you so much for your response. Yes, using map over the arrays instead of splice and setting default values resolve the issue.

Your solution and the way you structure it is great. Thank you once again.

Please or to participate in this conversation.