admin管理员组文章数量:1297026
I am trying to create an input box for a timer/OTP styled input.
How to overwrite a current character inside input box w length 1 (OTP inputs) when it is already full?
My problem is that the input is length 1, and we move the cursor/focus to the next only after catching a single character... but once a char is filled, you have to manually backspace and delete the char and then you can refill...
currently inside input box(0) but since it is already filled, I can't overwrite it
Code Sandbox Example
const { useState, useRef } = React;
function App() {
const [time, setTime] = useState(null);
const [running, setRunning] = useState(false);
const [editState, setEditState] = useState(false);
const [hms, setHms] = useState(Array(6).fill(0));
const inputs = useRef([]);
const handleChange = (e, idx) => {
const {value} = e.target;
if (value.match(/^\d$/)) {
const newHms = [...hms];
newHms[idx] = value;
setHms(newHms);
if (idx < 6) {
inputs.current[idx+1].focus();
}
if (value === '') {
if (idx > 0) {
inputs.current[idx - 1].focus();
}
}
}
}
const handleKeyDown = (e, idx) => {
if (e.key === 'Backspace') {
if (hms[idx] != '') {
const newHms = [...hms];
newHms[idx] = '';
setHms(newHms);
return;
}
if (idx > 0) {
inputs.current[idx - 1].focus();
}
}
}
return (
<>
<div id='root' style={{backgroundColor: "#e3b23c", width:"400px", height:"400px"}}>
{true && <div>
{
hms.map((_, idx) => {
return (
<span>
<input
key={idx}
type='text'
maxLength="1"
value={hms[idx]}
onKeyDown={(e) => handleKeyDown(e, idx)}
onChange={(e) => handleChange(e, idx)}
ref={(el) => (inputs.current[idx] = el)}
style={{width: '40px',
height: '40px',
margin: '0 5px',
textAlign: 'center',
fontSize: '18px',
border: '1px solid #ccc',
borderRadius: '4px'}
}
></input>
{(idx == 1 || idx == 3) && <span style={{
fontWeight: 600,
fontSize: "30px"
}}>:</span>}
</span>
);
})
}
</div>}
<div>
Hours : Minutes : Seconds
</div>
</div>
</>
)
}
ReactDOM.render(<App />, document.getElementById("react"));
<script src=".0.1/umd/react.production.min.js"></script>
<script src=".0.1/umd/react-dom.production.min.js"></script>
<div id="react"></div>
I am trying to create an input box for a timer/OTP styled input.
How to overwrite a current character inside input box w length 1 (OTP inputs) when it is already full?
My problem is that the input is length 1, and we move the cursor/focus to the next only after catching a single character... but once a char is filled, you have to manually backspace and delete the char and then you can refill...
currently inside input box(0) but since it is already filled, I can't overwrite it
Code Sandbox Example
const { useState, useRef } = React;
function App() {
const [time, setTime] = useState(null);
const [running, setRunning] = useState(false);
const [editState, setEditState] = useState(false);
const [hms, setHms] = useState(Array(6).fill(0));
const inputs = useRef([]);
const handleChange = (e, idx) => {
const {value} = e.target;
if (value.match(/^\d$/)) {
const newHms = [...hms];
newHms[idx] = value;
setHms(newHms);
if (idx < 6) {
inputs.current[idx+1].focus();
}
if (value === '') {
if (idx > 0) {
inputs.current[idx - 1].focus();
}
}
}
}
const handleKeyDown = (e, idx) => {
if (e.key === 'Backspace') {
if (hms[idx] != '') {
const newHms = [...hms];
newHms[idx] = '';
setHms(newHms);
return;
}
if (idx > 0) {
inputs.current[idx - 1].focus();
}
}
}
return (
<>
<div id='root' style={{backgroundColor: "#e3b23c", width:"400px", height:"400px"}}>
{true && <div>
{
hms.map((_, idx) => {
return (
<span>
<input
key={idx}
type='text'
maxLength="1"
value={hms[idx]}
onKeyDown={(e) => handleKeyDown(e, idx)}
onChange={(e) => handleChange(e, idx)}
ref={(el) => (inputs.current[idx] = el)}
style={{width: '40px',
height: '40px',
margin: '0 5px',
textAlign: 'center',
fontSize: '18px',
border: '1px solid #ccc',
borderRadius: '4px'}
}
></input>
{(idx == 1 || idx == 3) && <span style={{
fontWeight: 600,
fontSize: "30px"
}}>:</span>}
</span>
);
})
}
</div>}
<div>
Hours : Minutes : Seconds
</div>
</div>
</>
)
}
ReactDOM.render(<App />, document.getElementById("react"));
<script src="https://cdnjs.cloudflare/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="react"></div>
Share
edited Feb 11 at 20:09
0stone0
44.3k5 gold badges51 silver badges80 bronze badges
asked Feb 11 at 16:37
M. Varun ReddyM. Varun Reddy
337 bronze badges
1
- 1 Here's a code sandbox preview of the same I am new here and couldnt reproduce the code-snippet on stack-snippets – M. Varun Reddy Commented Feb 11 at 18:09
1 Answer
Reset to default 1Your input is already filled, and unless you select the input value and then update the value, changes will not be triggered and hence onChange
will not be triggered.
So, you have to trigger this change manually, and although onChange
is only called on change, onKeyDown
will be called on every keydown even if there is no actualy change of value.
So, the desired behaviour is achievable with the small tweak of moving all your logic from onChange
handler to onKeyDown
handler.
const handleChange = (e, idx) => {
};
const handleKeyDown = (e, idx) => {
const keyValue = e.key;
if (keyValue === "Backspace") {
if (hms[idx] != "") {
const newHms = [...hms];
newHms[idx] = "";
setHms(newHms);
return;
}
if (idx > 0) {
inputs.current[idx - 1].focus();
}
} else if (keyValue.match(/^\d$/)) {
const newHms = [...hms];
newHms[idx] = keyValue;
setHms(newHms);
if (idx < 5) {
inputs.current[idx + 1].focus();
}
}
};
Here is the codesandbox
本文标签:
版权声明:本文标题:javascript - How to overwrite a current character inside input box (OTP inputs) when it is already full? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741647122a2390251.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论