Reactjs which one is better form onChange or input onChange? - reactjs

There are two ways you can get input changes in your React app.
One is by using
<input type="text" onChange={this.handleChange} />
The other was is
<form onChange={this.handleChange} onSubmit={this.handleChange} />
...
</form>
When you should use first one and when the other one.

The reason that there are two ways is because there are more than the two ways. You can do this too:
<div onChange={this.handleChange}>
<form>
<input />
</form>
</div>
I'd argue that the first approach is better because the handler receives the event as early as possible and possibly because the binding between the input and the component state is encoded within the render function, but that depends on what the handler would look like.

Related

regex pattern isn't working in input Reactjs

pattern="[a-zA-Z ]*"
im trying to limit the input to be only letters no numbers or symbols should be allowed
but the given code is not working
<input
name="cardName"
type="text"
required
pattern="[a-zA-Z ]*"
defaultValue={kardName}
/>
i have also tried to use onChange method but it wasn't working too
anyhelp would be highly apperciated
The pattern attribute specifies a regular expression that the element's value is checked against on form submission.
You can see from the snippet below, that if you hit submit, the pattern is checked and it's actually working.
<form>
<input
name="cardName"
type="text"
required
pattern="[a-zA-Z ]*"
/>
<input type="submit" />
</form>
If you want to prevent the user from inserting some character, the pattern attribute won't help you.
What You can do is check the character inside the onKeyDown function, and prevent the insertion there. Something like this:
const onKeyDown = (event) => {
if (!event.key.match(/[A-Za-z ]/)) {
event.preventDefault()
}
...
<input
name="cardName"
type="text"
required
onKeyDown={onKeyDown}
/>

React use form for img radio buttons

I am trying to create a rock, paper and scissor game in react. I would assume that it makes sense to use a form for this, I would atleast use a form haven't it been for react.
I figured that the simplest way of doing this, would be three radio inputs and a submit.
However, since I want to use three pictures as the actual radio buttons. Would it even make sense to use a form since react aims to take the state out of the form. This is the point in my code where i realized that I might be on a sidetrack.
onChangeHandler = (event) => {
this.setState({ [event.target.name]: event.target.value });
}
render() {
return (
<div>
<div>
<form>
<input type="radio" value="Rock" name="gender" onChange={this.onChangeHandler} /> Rock
<input type="radio" value="Paper" name="gender" onChange={this.onChangeHandler} /> Paper
<input type="radio" value="Scissor" name="gender" onChange={this.onChangeHandler} /> Scissor
<input type="submit" value="Submit" onClick = () => {submit()}/>
</form>
</div>
<div>
<img id="r" value="rock" src="http://www.jerrylow.com/demo/rps/rock.svg" alt="a rock" />
<img id="p" value="paper" src="http://www.jerrylow.com/demo/rps/paper.svg" alt="a piece of paper" />
<img id="s" value="scissor" src="http://www.jerrylow.com/demo/rps/scissor.svg" alt="a scissor" />
</div>)
}
Should I use this form, even though the form serves no particular purpose. If yes, how should i integrate it with the img elements?
You have a few ways of going about it. You can forgo the form entirely and attach onClick listeners to each of the images that would modify the state when clicked and then have a button that when clicked would call your submit function.
Or, if you wish to retain the form, you could either wrap the radio buttons and images in labels, hide the radio buttons such that when the image is clicked, it would trigger the onChange. Or, you could specify a for prop on the label that matches the id of a radio button and have the image in that and it would behave as the previously described, something like
<input type="radio" id="myButton" onChange={handleChange} />
<label for="myButton"><img src="img.png" /></label>
I guess it really comes down to the solution you want because either way would be fine. I would personally prefer not using a form for this scenario purely because it's not that necessary and the code would be smaller.

Pass multiple state values into an input with React

Somewhat new to react and having trouble passing multiple state values to an input.
Specifically, state from drop-down menus. I can accomplish this in a p tag by chaining the various state values together.
This works
<p>
{this.state.one}_
{this.state.two}_
{this.state.three}_
{this.state.four}_
{this.state.five}
</p>
This will return
one_two_three_four_five
Whenever I try to pass these same values into a single input I get an error.
This does not work
<label>
Title:
<input
value=
{this.state.one}_
{this.state.two}_
{this.state.three}_
{this.state.four}_
{this.state.five}
type="text" />
</label>
How can one pass multiple state values into a single input?
Template literals with variables :
<input
value={ `${this.state.one}_${this.state.two}` }
/>
You have to pass a single expression to the value attribute. Change to this:
<label>
Title:
<input value={`${this.state.one}_
${this.state.two}_
${this.state.three}_
${this.state.four}_
${this.state.five}`
}
type="text" />
</label>
Note: this is ES6 string interpolation. The ES5 alternative is the regular string concatenation with "+"

Hidden Inputs in AngularJS Form

I have a form where I want to submit a hidden value that is not seen (or editable) by the user.
Originally I was attempting to do it with something like:
<input type="hidden" data-ng-model="data.selfscan" value="true">
But looking into the issue and at previously asked/answered questions here, I learned that hidden input type doesn't work with AngularJS. So instead I needed to do something like this:
<input type="text" data-ng-model="data.selfscan" value="true" data-ng-value="true" data-ng-show="false" />
Unfortunately, that did not work either.
I saw another post about how I should initialize it, so I had
<input type="text" data-ng-model="data.selfscan" data-ng-init="data.selfscan='true'" data-ng-show="false" />
That seemed to do the trick in getting the value to appear in the form (at least when I viewed it by making the box visible), but unfortunately the init seemed to break another part of the form making the entire thing unsubmittable.
I've spent way too much time on what should be a simple thing, so I'm looking towards all of your expertise for help or suggestions of what else to try or what could be going wrong.
Just handle the form submit action in the controller.. like this.
Html:
<form novalidate class="simple-form">
<input type="text" ng-model="user.name" /><br />
<input type="submit" ng-click="updateUser('hidden data')" value="Save" />
</form>
Controller:
$scope.updateUser = function(hidden){
if(hidden){
$scope.user.other = hidden;
}
};
Your first attempt is almost right:
<input type="hidden" data-ng-value="data.selfscan" value="true">
As input hidden is not editable by user it does not implement two-way binding, so you need to do one way value binding.

AngularJS form validation testing

Sometimes forms become very complicated and it is impossible to test every case manually after code changes.
I already have unit testing with karma on the project.
Is there any tools or best practices how to test AngularJS form validation with jasmine and karma?
For example how can I test such form with jasmine and karma automatically?
<form name="appForm" novalidate>
<div>
Username: <input type="text" ng-model="data.username" name="username" ng-maxlength="15" required />
</div>
<div>
Email: <input type="email" ng-model="data.email" name="email" required />
</div>
<div>
Age: <input type="number" ng-model="data.age" name="age" />
</div>
<div>
<button ng-click="submit()" ng-disabled="appForm.$invalid">Submit</button>
</div>
</form>
It depends on what you actually want to make sure when testing form validation.
If you want to be sure invalid form will not be submited, then it is one case. And I don't see problems with this case.
If you want to be sure that appropriate messages are displayed for invalid fields, then, for example, you can make a directive, that is aware of all your possible field restrictions ('required', 'ng-maxlength', 'url', etc.) and is responsible for displaying appropriate error messages. So you will need to create tests only for this directive.
Example:
<input type="text" ng-model="data.username" my-directive name="username" ng-maxlength="15" required />
myDirective is aware of required and ng-maxlength restrictions, that were put on the field, & it is responsible for displaying appropriate error messages for invalid state of the field.

Resources