I am struggling with the current situation:
I have 1 single input where I paste data like this:
96 101 115 145 191 276 412 551 511 552
I convert it into an array and save to Database.
Would love to refactor it in 11 different inputs because is way easier to modify.
How could I paste all thoose numbers into the first input and fill all of them splitting in the space?
My first attemp was this:
import { useState } from "react"
const MultipleInputs = () => {
const [form, setForm] =useState({})
const handleForm = (e) => {
setForm({...form, [e.target.name]:e.target.value})
}
const splitOnCopy = (e) => {
const data = e.target.value
const newArray = data.trim().split(/\s/)
setForm({
y1: newArray[0],
y2: newArray[1],
y3: newArray[2],
y4: newArray[3],
y5: newArray[4],
y6: newArray[5],
y7: newArray[6],
y8: newArray[7],
y9: newArray[8],
y10: newArray[9],
ttm: newArray[10]
})
}
return (
<div className="input-container">
<input onPaste={splitOnCopy} onChange={handleForm} value={form.y1} type="text" name="y1"></input>
<input onChange={handleForm} type="text" value={form.y3} name="y3"></input>
<input onChange={handleForm} type="text" value={form.y4} name="y4"></input>
<input onChange={handleForm} type="text"value={form.y5} name="y5"></input>
<input onChange={handleForm} type="text" value={form.y6} name="y6"></input>
<input onChange={handleForm} type="text" value={form.y7} name="y7"></input>
<input onChange={handleForm} type="text" value={form.y8} name="y8"></input>
<input onChange={handleForm} type="text" value={form.y9} name="y9" ></input>
<input onChange={handleForm} type="text" value={form.y10} name="y10"></input>
<input onChange={handleForm} value={form.ttm} name="ttm" type="text"></input>
</div>
)
}
export default MultipleInputs
It almost work but I am sure there must be multiple better ways to achieve that.
Thanks
CodePudding user response:
A little bit better:
import React, { useRef, useState } from 'react';
const MultipleInputs = () => {
const [form, setForm] = useState({});
const lastRef = useRef();
const handleForm = (e) => {
setForm({ ...form, [e.target.name]: e.target.value });
};
const splitOnCopy = (e) => {
const data = e.target.value;
const newArray = data.split(' ');
let formData = {};
newArray.forEach((c, i) => (formData[`y${i 1}`] = c));
formData['ttm'] = newArray[newArray.length - 1];
setForm(formData);
lastRef.current.focus();
};
//96 101 115 145 191 276 412 551 511 552 32
return (
<div className="input-container">
<input onChange={splitOnCopy} value={form.y1} type="text" name="y1"></input>
<input onChange={handleForm} type="text" value={form.y3} name="y3"></input>
<input onChange={handleForm} type="text" value={form.y4} name="y4"></input>
<input onChange={handleForm} type="text" value={form.y5} name="y5"></input>
<input onChange={handleForm} type="text" value={form.y6} name="y6"></input>
<input onChange={handleForm} type="text" value={form.y7} name="y7"></input>
<input onChange={handleForm} type="text" value={form.y8} name="y8"></input>
<input onChange={handleForm} type="text" value={form.y9} name="y9"></input>
<input onChange={handleForm} type="text" value={form.y10} name="y10"></input>
<input ref={lastRef} onChange={handleForm} value={form.ttm} name="ttm" type="text"></input>
</div>
);
};
export default MultipleInputs;
I added a ref to the last input so that after pasting the focus goes to the last input simulating the user typing. You can also add ref to all the input elements and capture input value length for each component and change focus to the next one as user types.
I hope I can help you.
CodePudding user response:
I did a minimal working example:
import { useState } from "react";
function App() {
const INPUT_COUNT = 11;
const [form, setForm] = useState({});
const handleForm = (e, i) => {
setForm({ ...form, [i]: e.target.value });
};
const splitOnCopy = (e) => {
const data = e.clipboardData.getData("text/plain");
const newArray = data.trim().split(/\s/g);
const newForm = { ...newArray };
setForm(newForm);
e.preventDefault();
};
return (
<div className="input-container" style={{ padding: "2rem" }}>
<p>96 101 115 145 191 276 412 551 511 552 32</p>
{Array.from({ length: INPUT_COUNT }).map((_, i) => (
<input
key={i}
onPaste={splitOnCopy}
onChange={(e) => handleForm(e, i)}
value={form[i] || ""}
type="text"
name={`input_${i}`}
></input>
))}
</div>
);
}
export default App;
This creates all inputs dynamically and assign their index as their id, which allows you set the input count as you wish.