ReactJS Element focus() not firing - javascript

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

Related

How to use setTimeout in react for if statement?

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?

React Admin - How to disable validation onChange

I'm using react-admin, and I have a huge form, with a bunch of custom validation. It's very slow, even with the build version.
I tried to find a way to disable the validation on change and to have it only on blur or submit. But I have not found a solution or even workaround.
Every time a key is pressed in one of my input text (for example), the validation is triggered multiple times, and it takes a while for the letter to appear.
That's why I want to disable the validation on change.
Here's an example of one of my forms, every letter I write in one of my FormTab, the "validate me" is showing.
export const ThemeCreate: FC = (props: any) => (
<Create {...props} title="ui.themes.create" mutationMode="pessimistic">
<TabbedForm
toolbar={<GenericCreateToolbar />}
validateOnBlur
warnWhenUnsavedChanges
validate={() => {
console.log('validate me!');
}}
>
<MainFormTab />
<TranslationsFormTab />
</TabbedForm>
</Create>
);
You need to use the validateOnBlur={true} prop in the form component.
This prop is from final-form's <Form> component, see the last one in this doc page https://final-form.org/docs/react-final-form/types/FormProps

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);
}
};

How do I add the click event to the input field?

I want to add a button property to an entry. For example;
I have an input field that cannot be edited:
When I press the keyboard button it becomes editable:
When the user clicks on the entry field without the need for a different button, it must run a different function. For example barcode scanner. Can an input that is not editable trigger a function? Or can an editable input trigger any function? How do I do this?
As in this application, the barcode event should be triggered by the input field, not the button.
As mentioned in my comment, the UX of the current approach in the question is highly questionable:
It's missing a signifier. There is no clear indication that only that non-editable field - in contrast to all other non-editable ones - triggers something once clicked.
Users, who'd prefer entering the barcode manually, would need to click on the keyboard-button first to make the input field editable, and then, once again, click on the input field to enter data.
Instead, consider to offer both options (entering manually and triggering the camera to scan) within a single input field via its value-help (F4) action:
sap.ui.getCore().attachInit(() => sap.ui.require([
"sap/ui/core/Fragment"
], async (Fragment) => {
"use strict";
const control = await Fragment.load({
definition: `<form:SimpleForm xmlns:form="sap.ui.layout.form"
xmlns="sap.m"
editable="true"
layout="ColumnLayout">
<Label text="Barcode Number" />
<Input width="12rem"
textAlign="Center"
placeholder="XXXXXXXXX"
showValueHelp="true"
valueHelpIconSrc="sap-icon://bar-code"
valueHelpRequest="alert('Scanner triggered!')"
/>
</form:SimpleForm>`,
});
control.placeAt("content");
}));
<script id="sap-ui-bootstrap"
src="https://openui5.hana.ondemand.com/resources/sap-ui-core.js"
data-sap-ui-libs="sap.ui.core,sap.m,sap.ui.layout"
data-sap-ui-async="true"
data-sap-ui-theme="sap_fiori_3"
data-sap-ui-compatversion="edge"
data-sap-ui-excludejquerycompat="true"
data-sap-ui-xx-waitfortheme="init"
></script>
<body id="content" class="sapUiBody"></body>
The value help icon can be set to a barcode one by assigning "sap-icon://bar-code" to the valueHelpIconSrc property (available since v1.84.0) in sap.m.Input.
This approach is beneficial for both - users and developers - because the behavior is now consistent with common user input scenarios, improving familiarity, and for developers, it highly reduces maintenance costs since there is less customization.
If the target UI5 version is lower than 1.84.0 or if the barcode has a fixed length, the control needs to be extended with the method addEndIcon. I explained this in another answer. Here is an example with an extended sap.m.MaskInput:
See https://embed.plnkr.co/EzlF2tkvalJWvSEn?preview
If your non-editable input is non-editable because it has a disabled attribute, you can't attach mouse events to it. (Actually you can, but it won't fire mouse events.)
If you want to fire a click event, you can add the event listener to a parent element, like a div in my example below.
Although it works in Chrome without it, you also need to set pointer-events to none on the input to make the clicks fall through to the parent element in Firefox.
const parentDiv = document.querySelector("div");
const input = document.querySelector("input");
parentDiv.addEventListener("click", (e) => {
input.removeAttribute("disabled");
input.focus();
// or you can open the barcode scanner, etc.
});
input {
font-size: 2rem;
padding: 0.5rem 1rem;
}
input[disabled] {
pointer-events: none;
}
<div>
<input type="text" value="disabled field" disabled>
</div>
It could also work with label if the label contains the input:
<label>Barkod No:
<input type="text" value="disabled field" disabled>
</label>
Try this, replacing the displayDate funcion with your own enable function:
document.getElementById("myBtn").addEventListener("click", displayDate);
Which then calls the CSS change:
input[type="text"]:enabled {
}
https://www.w3schools.com/js/js_htmldom_eventlistener.asp

ReactJS - Make Click Event fire before onBlur

I am implementing a custom input element similar to React Select. Users will be able to type something into the input element and select a suggestion from a dropdown (in my case, I implemented a component called SuggestionList which serves the same purpose as that dropdown suggestion list).
Currently, the SuggestionList is a sibling React component to the input element that the user types into (I named it CustomInput).
I want SuggestionList to disappear when CustomInput loses focus, so I implemented an onBlur handler which makes SuggestionList either un-mount or have "display" CSS property set to none. However, the problem is that after SuggestionList disappears, its onClick/handleClick event handler doesn't get called, and that event handler is responsible for adding user-selected elements to the selected items list.
Code shown below. There is more explaination after this code.
const AutocompleteInput = ({...}) => {
const [suggestionVisible, setSuggestionVisible] = useState(true);
return (
....
<SystemComponent position="relative">
<SuggestionList p={theme.space[4]}
position="absolute"
visible={suggestionVisible}
value={value}
handleClick={handleSelect}
ref={suggestionBox}
/>
<CustomInput
variant="text"
placeholder={placeholder}
value={value}
onChange={(evt) => handleInputChange(evt.target.value)}
onKeyDown={handleKeyDown}
onFocus={ () => {setSuggestionVisible(true)} }
onBlur={ () => {setSuggestionVisible(false);} }
/>
</SystemComponent>
....
)
}
Therefore, when a user clicks something on the SuggestionList, my CustomInput immediately loses focus, causing SuggestionList to either be unmounted/disappear, and thus its event handler isn't called. As a result, the item the user selects isn't added to the suggestion list.
Having that said, I still want SuggestionList to disappear when the user clicks some other part of the website, thereby causing CustomInput to lose focus. Any suggestions ?
Let's say you are calling onClickHandler() inside your onClick. You can call this inside the onBlur on function.
For example
onBlur={ () => {onClickHandler(); setSuggestionVisible(false);} }

Categories

Resources