I´m trying to create a nested dynamic form using react that is able to generate dynamic input fields based on already generated dynamic input fields.
What am I trying to do?
User should be able to create a playlist that consists of
- Playlistname (1:1/ only once per form)
- YoutubeURL (As much as the user wants can be added
- StartTime/ EndTime (As much as the user wants can be added to EACH youtubeURL)
This is the starting form
I´m already able to add new Start/End-Time fields to a youtubeURL
But if I afterwards click on "add new fields" and generate a new input for youtubeURL, the generated Start/End time already share the state of the previous entered Start/end from the old youtubeURL.
I don't get where I´m doing this wrong.
And also overall the form doesn't feel like beeing really stable right now... If someone has an idea how I can improve this form and also fix my shared state issue, would be great.
Here is my code:
import React, { useState } from "react";
import Form from "react-bootstrap/Form";
import Button from "react-bootstrap/Button";
const PlaylistForm = () => {
const [formPlaylistName, setFormPlaylistName] = useState("");
const [formPlaylistYoutubeUrl, setFormPlaylistYoutubeUrl] = useState([
{ youtubeUrl: "" },
]);
const [formPlaylistYoutubeUrlPlayTimes, setFormPlaylistYoutubeUrlPlayTimes] =
useState([{ start: 0, end: 0 }]);
// start formPlaylistYoutubeUrl
let handleChangePlaylistYoutubeUrl = (i: any, e: any) => {
let newFormValues = [...formPlaylistYoutubeUrl];
// @ts-expect-error: Let's ignore a compile error like this unreachable code
newFormValues[i][e.target.name] = e.target.value;
setFormPlaylistYoutubeUrl(newFormValues);
};
let addFormFieldsPlaylistYoutubeUrl = () => {
setFormPlaylistYoutubeUrl([...formPlaylistYoutubeUrl, { youtubeUrl: "" }]);
};
let removeFormFieldsPlaylistYoutubeUrl = (i: any) => {
let newFormValues = [...formPlaylistYoutubeUrl];
newFormValues.splice(i, 1);
setFormPlaylistYoutubeUrl(newFormValues);
};
// end formPlaylistYoutubeUrl
//start formPlaylistYoutubeUrlPlayTimes
let handleChangePlaylistYoutubeUrlPlayTimes = (i: any, e: any) => {
let newFormValues = [...formPlaylistYoutubeUrlPlayTimes];
console.log(e.target.value);
// @ts-expect-error: Let's ignore a compile error like this unreachable code
newFormValues[i][e.target.name] = e.target.value;
setFormPlaylistYoutubeUrlPlayTimes(newFormValues);
};
let addFormFieldsPlaylistYoutubeUrlPlayTimes = () => {
setFormPlaylistYoutubeUrlPlayTimes([
...formPlaylistYoutubeUrlPlayTimes,
{ start: 0, end: 0 },
]);
};
let removeFormFieldsPlaylistYoutubeUrlPlayTimes = (i: any) => {
let newFormValues = [...formPlaylistYoutubeUrlPlayTimes];
newFormValues.splice(i, 1);
setFormPlaylistYoutubeUrlPlayTimes(newFormValues);
};
//end formPlaylistYoutubeUrlPlayTimes
let handleSubmit = (event: any) => {
event.preventDefault();
alert(formPlaylistName);
alert(JSON.stringify(formPlaylistYoutubeUrl));
alert(JSON.stringify(formPlaylistYoutubeUrlPlayTimes));
};
return (
<form onSubmit={handleSubmit}>
<label>Playlist name</label>
<Form.Control
type="text"
name="playlistName"
value={formPlaylistName}
onChange={(e) => setFormPlaylistName(e.target.value)}
/>
{formPlaylistYoutubeUrl.map((element, index) => (
<div className="form-inline" key={index}>
<label>Name</label>
<Form.Control
type="text"
name="youtubeUrl"
value={element.youtubeUrl || ""}
onChange={(e) => handleChangePlaylistYoutubeUrl(index, e)}
/>
{index ? (
<button
type="button"
className="button remove"
onClick={() => removeFormFieldsPlaylistYoutubeUrl(index)}
>
Remove
</button>
) : null}
{formPlaylistYoutubeUrlPlayTimes.map((element1, index1) => (
<div className="form-inline" key={index1}>
<label>Start time</label>
<Form.Control
type="text"
name="start"
value={element1.start || ""}
onChange={(e) =>
handleChangePlaylistYoutubeUrlPlayTimes(index1, e)
}
/>
<label>End time</label>
<Form.Control
type="text"
name="end"
value={element1.end || ""}
onChange={(e) =>
handleChangePlaylistYoutubeUrlPlayTimes(index1, e)
}
/>
{index1 ? (
<div>
<button
type="button"
className="button remove"
onClick={() =>
removeFormFieldsPlaylistYoutubeUrlPlayTimes(index1)
}
>
Remove
</button>
</div>
) : null}
<button
type="button"
className="button add"
onClick={() => addFormFieldsPlaylistYoutubeUrlPlayTimes()}
>
Add time
</button>
</div>
))}
</div>
))}
<div className="button-section">
<Button
variant="primary"
type="button"
onClick={() => addFormFieldsPlaylistYoutubeUrl()}
>
Add new Field
</Button>
<Button variant="primary" type="submit">
Create new shorturl
</Button>
</div>
</form>
);
};
export default PlaylistForm;
from Nested dynamic form creation - State shared for dynamic added fields



No comments:
Post a Comment