How to use setTimeout in react for if statement? - javascript

I like to use only placeholder without label for inputs/forms. Therefore i created a onClick -> set type from text to date.
But if someone has a bad memory and dont know what date to fill in, I created a onMouseleave -> set type from date to text, if its empty.
But if someone want to fill his birthday and the mouse leaves accendently, they will give me a text instead of a date.
Therefore I want to use a setTmeout but it doesn't work as planned.
const [type, setType] = useState("text")
const handleDate = () => {
setType("date")
}
const handleText = () =>{
if(values.birthday === ""){
setType("text")}
}
<input
onChange={handleChange}
value={values.birthday}
type={type}
name="birthday"
placeholder="birthday"
onClick={handleDate}
onMouseLeave={setTimeout(handleText, 3000)}/>
by using onMouseLeave={setTimeout(handleText, 3000)}/> the input field is deselected and i can't type anything in.
I want that the if-query will be checked after 3 seconds and am able to type something in

try this:
<input
onChange={handleChange}
value={values.birthday}
type={type}
name="birthday"
placeholder="birthday"
onClick={handleDate}
onMouseLeave={() => setTimeout(handleText, 3000)}/>
the way you're doing currently it is immediately calling the setTimeout on render, you need to put it as a function

This is very weird UX design, I doubt your users will like it. No one expects that moving the mouse out of the input would replace the contents of the input a few seconds later. And did you consider that people may use a touch screen? Or move to the next input with the Tab key?
How about using a more conventional UX, for example title if you don't want labels?

Related

JS set input value by regex

I have simple input on my html and i want to when user putting text value in the input value was automatically set by my regex pattern
Example: I have time picker input
and I want the user when he enters numbers, the value is automatically formatted in the input.
How to do it with regex and replace function ?
I tried to do it this way, but in the end I just get the string that I enter.
console.log(value.replace(/^(([0-9]{1})|([0-1]{1}[0-9]{1})|([2]{1}[0-3]{1}))(([:]{1})?)(([0-5]{1}[0-9]?)?)$/g, ''));
If you are using a UI framework, refer to their documentation they would probably have a plugin to do it for you. Or if you want to do it on your own:
From the HTML side you can use type="time" attribute (please check the browser support for this).
And from JavaScript you can use something like ^([01]\d|2[0-3]):?([0-5]\d)$ on form submission for example.
const TIME_REGEX = /([01]\d|2[0-3]):?([0-5]\d)$/;
const myTimeElm = document.getElementById('myTime');
const outputElm = document.getElementById('output');
let timer;
outputElm.addEventListener('click', () => {
if (TIME_REGEX.test(myTimeElm.value)) {
outputElm.innerText = myTimeElm.value;
} else {
outputElm.innerText = "Error!"
}
});
#output {
cursor: pointer;
}
<input type="time" id="myTime" value="00:00">
<span id="output">click here!</span>
If you don't want to use HTML's type="time", consider using a mask for your input where you record the user's input and render the formatted output in a different component.
Since using the RegEx alone won't achieve the same user experience as you may want to workout the input's cursor position.
Or simple use a library that does that for you (Cleave.js for example)

React onKeyPress Render Issue

I'm attempting to make a component which acts as a sort of bullet list. There's an input field held in an unordered list item (acting as the first bullet point, which by default will always be there). The field has an onKeyPress function that checks whether or not the user presses the return (or Enter) key to create a new bullet point. When that happens, the function adds another identical input field to the bulletList array, which is then rendered on the page using the .map() JS function.
The issue I'm having is the following: On the default (first) input field that is always there, the enter functionality works perfectly. The user can press enter, and a new input field is created below it. The problem happens here: On the second (newly-created) input field, the enter functionality partly works. It logs to the console what it needs to log as a test (indicating it's being triggered) but doesn't render a new input field below. What could be the issue here? Thanks!
The original input field:
<input onKeyPress={(e) => handleAdd(e)} autoFocus />
The adder function:
const handleAdd = (e) => {
if (e.key == "Enter") {
setBulletList([...bulletList, (<input onKeyPress={(e) => handleAdd(e)} autoFocus />)]);
console.log("Worked?");
console.log(bulletList);
}
};
You don't have anything that differentiates the first one from the second one so React is getting confused when there's more than one. React will often warn you to make sure each element has it's own unique keys. If they don't have unique keys/identifiers then React won't update the virtual dom. The virtual dom is what React uses to identify changes that were made.
Give each one it's own class and that should work.
You should add the input value, not the input HTML tag, like this:
const handleAdd = (e) => {
if (e.key == "Enter") {
setBulletList([...bulletList, e.target.value]);
console.log("Worked?");
console.log(bulletList);
}
};

ReactJS Element focus() not firing

I have a number input field that I'm trying to focus on after receiving input from a bar-code scanner. In reality the scanner is just a pseudo keyboard that I watch for the tab key to get pressed.
In Edge the input receives focus as expected, but in all other browsers tested (Chrome/Firefox) the input doesn't gain focus. Safari has not been testes since I'm on a PC.
// I'm using a lifecycle method to watch for a change to the components props.
// The onInputFocused will unset the value, but I've disabled to this
// to eliminate any possible race cases?!
componentDidUpdate() {
if (this.props.detail.shouldFocus) {
setTimeout(() => {
this.qtyInput.focus();
}, 250);
// this.props.onInputFocused(this.props.detail);
}
}
render(){
return (
...
<input type="number" className="form-control" min="0" name="qty_received" value={detail.ReceiptQuantityReceived}
ref={(input) => { this.qtyInput = input }}
onChange={(e) => { onQtyReceivedChange(e, detail) }}
onBlur={() => { onReceiveShipmentRowBlur(detail) }} />
);
}
I originally was calling focus without a setTimeout, but attempted the timeout based on some suggestions online. I have also attempted to change the input to text, but that didn't have any effect either.
Doing a console.log on this.qtyInput outputs the expected element.
The only other thing I can think of is that the modal that a user scans in to gains it's focus via a similar function, but it has been removed by the time the focus call should be happening.
To add to the weirdness, I've added a console.log to the input's onBlue event and it is getting fired even though you can't type in the field or have any visual indication of focus.
one thing you must try is add this attribute for your INPUT element
(input autoFocus ..)
this attribute may help you

How do I go from one field to the next (without using TAB) in Redux-form 6?

I've got a form with three fields that make up a phone number input. It looks something like this:
<form>
<Field id="areaCode" name="areaCode" component={areaCode} max={3} type="text" />
<Field id="firstThree" name="firstThree" component={firstThree} max={3} type="text" />
<Field id="lastFour" name="lastFour" component={lastFour} max={4} type="text" />
</form>
The component for each Field looks like this (they are similar so I'll just show one to illustrate my point)
const areaCode = (field) => (
<input
{...field.input}
maxLength={field.max}
type="text"
onChange={(value) => {
// switch to next field (firstThree)
// after this field's length is >= 3
}}
/>
)
I want to automatically switch to the second field after the user has inputted 3 numbers in the first field. How does one switch to the next field programmatically?
I'm not sure how to reference the second field in the form to switch to when they blur away from the first field.
Am i doing this the right way? Should I be using Fields instead of Field?
Edit: To automatically switch to the next field upon hitting the maxLength, you could use onChange() and ref. The onChange() handler checks if the current input is at its max length. If it is, focus() on the next ref'd input on your react page.
Example: jsfiddle.net/4np9u17g/11
You should not need any sort of onBlur() function or have code to handle switching to the next input upon clicking tab. The browser will automatically focus on the input upon clicking tab.
It looks like you are using redux-form's Field correctly - you have defined a separate component for each part of the phone number, so you should use Field for each component (as you have already done). If, instead, you wanted to combine all of these inputs into one component, then you would need to use Fields. But, as you are now, you should be good.

How to set cursor to input box in Javascript?

document.getElementById(frmObj.id).value="";
document.getElementById(frmObj.id).autofocus;
document.getElementById("errorMsg").innerHTML = "Only numeric value is allowed";
In the above code the value of the form object is perfectly setting to "" but there is no cursor in the text box. I want a cursor to be there. focus() only focuses that input box but does not actually set the cursor.
In JavaScript first focus on the control and then select the control to display the cursor on texbox...
document.getElementById(frmObj.id).focus();
document.getElementById(frmObj.id).select();
or by using jQuery
$("#textboxID").focus();
I realize that this is quite and old question, but I have a 'stupid' solution to a similar problem which maybe could help someone.
I experienced the same problem with a text box which shown as selected (by the Focus method in JQuery), but did not take the cursor in.
The fact is that I had the Debugger window open to see what is happening and THAT window was stealing the focus. The solution is banally simple: just close the Debugger and everything is fine...1 hour spent in testing!
Sometimes you do get focus but no cursor in a text field. In this case you would do this:
document.getElementById(frmObj.id).select();
One of the things that can bite you is if you are using .onmousedown as your user interaction; when you do that, and then an attempt is immediately made to select a field, it won't happen, because the mouse is being held down on something else. So change to .onmouseup and viola, now focus() works, because the mouse is in an un-clicked state when the attempt to change focus is made.
This way sets the focus and cursor to the end of your input:
div.getElementsByTagName("input")[0].focus();
div.getElementsByTagName("input")[0].setSelectionRange(div.getElementsByTagName("input")[0].value.length,div.getElementsByTagName("input")[0].value.length,"forward");
Inside the input tag you can add autoFocus={true} for anyone using jsx/react.
<input
type="email"
name="email"
onChange={e => setEmail(e.target.value)}
value={email}
placeholder={"Email..."}
autoFocus={true}
/>
You have not provided enough code to help
You likely submit the form and reload the page OR you have an object on the page like an embedded PDF that steals the focus.
Here is the canonical plain javascript method of validating a form
It can be improved with onubtrusive JS which will remove the inline script, but this is the starting point:
function validate(formObj) {
document.getElementById("errorMsg").innerHTML = "";
var quantity = formObj.quantity;
if (isNaN(quantity)) {
quantity.value = "";
quantity.focus();
document.getElementById("errorMsg").innerHTML = "Only numeric value is allowed";
return false;
}
return true; // allow submit
}
#errorMsg { color:red }
<form onsubmit="return validate(this)">
<input type="text" name="quantity" value="" />
<input type="submit" />
</form>
<span id="errorMsg"></span>
In my experience
document.getElementById(frmObj.id).focus();
is good on a browser running on a PC.
But on mobile if you want the keyboard to show up so the user can input directly then you also need:
document.getElementById(frmObj.id).select();

Categories

Resources