Using <input oninput= ... with current value in textbox - javascript

I have an simple HTML input tag inside my React component, defined thusly:
<input type="text" onInput={(value) => {
search(value);
return value;
}}/>
By using oninput, I am hoping to invoke the search method, with the current value in the textbox as an argument, whenever the value in in the textbox is changed. The search method is defined in the same component thusly:
const search = _.debounce((value) => {
doSomething(value);
}, 500);
When I debug in Chrome Dev Tools, I see that value has the following value, instead of the current value in the textbox:
[[Handler]]: Object
[[Target]] : SyntheticEvent
[[IsRevoked]] : false
What am I doing wrong? How can I call search and provide it the current value in the textbox as an argument? Online examples show oninput being used like <input type="text" oninput="myFunction()">, but they don't show how to pass the value in your textbox as input to the function called on the oninput event.

The parameter of your onInput function is a JavaScript Event object. To extract the value of it, you have to first bind the value of the input box to something:
<input
type="text"
value={this.state.value}
onInput={this.handleSearch}
/>
And then in your component methods, extract this value with event.target, which allows you to look at the DOM elements properties (we want the value property):
handleSearch(event) {
this.setState({value: event.target.value});
this.search(event.target.value); // Or wherever your search method is
}
EDIT: renamed search => handleSearch to avoid confusion :)

Related

React event target value in onChange

What is the difference between
onChange={({ target: { value } }) => setInsertedTitle(value)}
and
onChange={setInsertedTitle}
When should one or another be used?
Using onChange={({ target: { value } }) => setInsertedTitle(value)} you are passing the current target value as a parameter.
It is because onChange generates an Event, and you access the value by event.target.value ...
event: {
target: {
value: "string"
}
}
On the other hand, when you use the function like in onChange={setInsertedTitle}, it receives the event.
You can see it here: https://codesandbox.io/s/compassionate-fast-krrib?file=/src/App.js
Look at what each does and spot the differences:
onChange={({ target: { value } }) => setInsertedTitle(value)}
Creates an arrow function (let's call it func)
Whenever onChange/func gets called, e.g. func(event):
It uses destructuring to set value to the value of event.target.value
It calls setInsertedTitle with value (therefore event.target.value)
In the other case:
onChange={setInsertedTitle}
When onChange gets called with event, we directly call setInsertedTitle with event.
Therefore the main difference is whether it passes event.target.value or just event.
The first one passes a function to onChange that, when called, will get the value of the target element of the event (this is probably an input element, so target will be that input element) and pass that value to setInsertedTitle. So when the event occurs, setInsertedTitle gets called with a string (the value of the input).
The second one will directly pass setInsertedTitle to onChange. When the event occurs, setInsertedTitle will get called with an event object rather than the value of the input.
For the avoidance of doubt: The first one is correct, the second one is incorrect. (Even if you wanted to have an event object in your state data — which you almost certainly don't — you can't just keep the one you're passed; you're not allowed to keep them as they get reused [I think that's going to change at some point].)

How do you use onChange in React?

What is the difference between these methods on handling input changes and when should i use one or the other?:
const handleChange = () => {
console.log("hello")
}
// first method
<input
onChange={() => handleChange()}
[...]
// second method
<input
onChange={() => handleChange}
[...]
// third method
<input
onChange={handleChange}
[...]
// fourth method
<input
onChange={handleChange()}
[...]
Note that I'm using functional components.
The first method is the kost correct, except you need the default onChange's arg, which is a native event, so for example: (e) => { e.preventDefault() }. With this method you can assign a function's execution with some non-default args.
The second one is totally incorrect.
The third one would call our function with the default argument(s), so here it's the same as my corrected method one.
The fouth one is also incorrect, as it would execute your function at the moment of React binding it to the element.
first method <input onChange={() => handleChange()} [...]
second method <input onChange={() => handleChange} [...]
fourth method <input onChange={handleChange()} [...]
These all do not use anywhere as per ECMA 6.
if we have only one onChange event which is your third option then we have to just pass our event as a name no need to pass the event object to in the argument as a parameter.
// third method
<input onChange={handleChange} [...]
but, if we need to pass our event as a argument then go for this option as per below[we have more than one event onClick or onchange]:
e.g. <input onChange={(event) => handleChange(event); otherEvent(); }}
and then we can access our handle change value using this method
const handleChange = (event) => {
console.log("hello", event)
}
Use of functions depend on requirement.
First is used when you need to pass something like - event, data for some operation.
Second way isn't correct way.
Third way is recommended to use
<input
onChange={handleChange} />
Fourth way isn't recommended to use because it will call on every page load.
By default, onChange handover change event as a parameter of onChangeHandler.
First Method is used to use custom parameters:
onChange={() => handleChange(customParam1, customParam2)}:
The second method is used to return the handle change function whenever an onChange event occurs.
onChange={() => handleChange} equals to onChange={function handleChange(e){[...]}}
Third method is used to use default onChange event as parameter of handleChange function:
onChange={handleChange} equals to onChange={(e) => handleChange(e)}
The last method is used to use return value of handleChange as onChangeHandler:
onChange={handleChange()} equals to onChange={(e) => handleChange()(e)}
The 2nd and 4th are similar as they use the return value as onChange handler.
Btw, 2nd method is the best one for onChange handling.
You should use the 2nd method as your primary method.
Thank you.

Programmatically assign a value prop to inputs through an object

I want to assign the onChange and value props (controlled input) by passing them in an object through destructuring.
The function getInputProps() returns the onChange and value props
getInputProps = name => {
return {
value: this.state.data[name],
onChange: this.handleInput
}
}
The input element consumes these props through destructuring
<input {...getInputProps('myInput')} />
However, that doesn't work, and I guess it's because the value is being passed as a 'value' and not a 'reference' to the state variable. It works when I put the value directly as a prop. What are my alternatives to pass all the necessary input props in an object?
EDIT: The handleInput function is working, when I omit the 'value' prop everything works as expected. It's the value that is problematic. When it is passed this way, it passes the actual value (which is none) to the HTML5 value parameter, and it is not dynamic anymore. When I omit 'value' in the object, then the user input is correctly set in the state (which is what the handleInput does), but changing the state doesn't change the value of the input.
Guys I found the solution. It is a simple stupid mistake. I was setting the name of the input and the 'name' passed to the function to different values. And the handleInput functions changes the state based on the actual name of the input.

$scope.$watch is not triggered when ng-model is undefined?

Problem:
I am trying to use $scope.$watch method over a ng-model used in a number input with strict attributes like, max, min, maxlength and step.
When the value inserted in the input exceeds any of those attributes, the ng-model retrieves undefined.
So, eventually, what happens is: $scope.$watch is triggered every time we change value in the input. Once the value is undefined, it will only be triggered again when the inserted value is again valid, in other words, following attribute rules (max, min, maxlength and step).
E.g.
user input: -2,4
-> $scope.$watch is triggered, and outputs, newValue as undefined.
user adds a new digit: -2,44
-> $scope.$watch is not triggered anymore, this way.
main.js
$scope.$watch("user.input.base.sphere", function(newValue, oldValue) {
console.log(newValue);
}
**index.html
<input
ng-cloak
type="number"
ng-class="user.settings.input.sphere.class"
autocomplete="off"
required
name="sphere"
id="in-sphere"
title="Sphere"
step="{{user.filter.sphere.step}}"
min="{{user.filter.sphere.min}}"
max="{{user.filter.sphere.max}}"
maxlength="{{user.filter.sphere.maxlength}}"
placeholder="{{user.filter.sphere.placeholder}}"
ng-model="user.input.base.sphere"
select-on-click
sphere>
Question: How can I still let $scope.$watch to be triggered even over a undefined ng-model
You can attach the following function to the ng-keyup directive. This function will get a reference to your form control and read the value that the user has typed in even though the value in the model has not yet been updated.
$scope.changeHandler = function (a) {
var element = angular.element(document.querySelector('#in-sphere'))[0];
console.log(element.value);
}
Attach it to your form control with this:
ng-keyup='changeHandler()'
Here is a working plunker

Why is the `value` attribute empty whereas the `value` property has the correct value?

I have an input field that will cache its value attribute. Example:
$("#signUpEmail").keyup(function(e) {
console.log(e.target.value); // Works
console.log($(this).attr("value")); // Doesn’t work
});
If I log them both in the console, e.target.value will return my input field, but not $(this).attr("value"). Can anyone explain why that is?
Can explain why is that so?
e.target.value accesses the DOM property, which always represents the current value of the input field.
On the other hand, $(this).attr("value") accesses the HTML attribute, which is the value of the input as specified in the HTML markup. It doesn't update when the value is changed by the user.
You could use $(this).prop('value') to access the property via jQuery, but as already mentioned, .val is the usual way to do this.
$(this).attr("value"); //can access only default value
For example,
<input type="text" id="signUpEmail" value="email"/>
$(this).attr("value"); //returns email
Instead use prop()
$(this).prop("value"); //for getting dynamic values
For example:
<input type="text" id="signUpEmail" />
$(this).prop("value"); //returns whatever you press
$(this).attr("value"); //returns undefined
You are fetching the value attribute, which represents the default value not the current value.
Use the val() method instead of attr().
$(this).val()
In jQuery to get text of input field use:
$(this).val();
and for labels:
$(this).text();

Categories