React - How to get the value form Materialize's Switches? - reactjs

I'm using switches component (designed by Materialize) inside React components, and I'd like to know, how could I get the value when the user has changed the switch (on/of).
<div className="switch right">
<label>
Any
<input type="checkbox" onChange={() => alert('changed')}/>
<span className="lever"></span>
All
</label>
</div>
I tried to set a onChange event to verify if I can, at least, get when it's triggered.

As a start, I would recommend using react-materialize, which has been written into components for react here https://react-materialize.github.io/#/forms.
I guess the problem is that onChange works only for JSX, and from your code it looks like you are using plain HTML?
I have added your onChange event into my JSX and it works as expected.
If you used react-materialize, your code would look something like this:
<Input name='on' type='switch' onLabel='Any' offLabel='All' onChange={() => alert('changed')}/>

Related

Testing radio inputs with React Testing Library - no form control was found associated to that label

I am testing several radio inputs in my form using React Testing Library. Most of them have labels of yes/no so I cannot use findByLabelText.
The full error I am getting is: Found a label with the text of: yes, however no form control was found associated to that label. Make sure you're using the "for" attribute or "aria-labelledby" attribute correctly. .
Here is one of my failing tests:
test('Sealing Properly radio input should exist, be unchecked, and be clickable', async () => {
render(
<Component />
);
const sealingProperlyRadioGroup = await screen.findByTestId('sealingProperly');
const sealingProperlyRadio = await within(sealingProperlyRadioGroup).findByLabelText('yes');
expect(sealingProperlyRadio).toBeInTheDocument();
expect(sealingProperlyRadio).not.toBeChecked();
fireEvent.click(sealingProperlyRadio)
expect(sealingProperlyRadio).toBeChecked();
});
And this is the html that gets outputted after the error:
<div
class="radioGroup mb-3"
data-testid="sealingProperly"
>
<label
class="radio"
for="sealingProperlyYes"
>
<input
id="sealingProperlyYes"
name="sealingProperly"
required=""
type="radio"
value="yes"
/>
Yes
</label>
<label
class="radio ms-5"
for="sealingProperlyNo"
>
<input
id="sealingProperlyNo"
name="sealingProperly"
required=""
type="radio"
value="no"
/>
No
</label>
</div>
I think there are a couple of problems:
The text you are querying is "yes" while in your component it is capitalized. There are ways to ignore case sensitivity in React Testing Library but by default it is case sensitive. You can learn more about it here
In React the for attribute is written slightly differently - htmlFor="your-id" so I think your labels don't get associated with their inputs correctly. source

How to set a state inside form without re-render component

I've got a form, where I wanna set in the state (setEducation for example) incoming value from the input. I use onChange, but this causes the component to be rendered each time I make a change to the input field. What is the right way to fix the problem?
<form id="loginform" onSubmit={onBecomeDoctorRequestHandler} >
<div className="form-group mb-3">
<label>Education</label>
<input
type="text"
className="form-control"
required
this onChange causes the placeholder="Harvard"
component to be rendered onChange={(event) => setEducation(event.target.value.trim())}
/>
<small className="text-danger form-text">
{educationError}
</small>
</div>
As-is all your form elements will re-render when any form element changes because the "value" of onClick is a new function each time the component runs (renders).
To fix that, wrap the onClick function in a useCallback. The useCallback will preserve the "value" of the function across renders, so only the elements that needs to be re-rendered will be.

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.

Reactjs which one is better form onChange or input onChange?

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.

AngularJS Form is not in HTML

I am trying to use AngularJS Validation in order to validate a simple form, however I was having troubles getting my ng-class to show the correct class based off whether or not the input was dirty or not. Then when I looked at the actual HTML of the page, the <form> tags are not even in the document at all!
<form novalidate name="infoForm">
<p>To start, provide some basic information about the project.</p>
<ul class="ulFormGeneral">
<li>
<label>Company name</label>
<input id="CompanyName" ng-class="{ cvError : infoForm.CompanyName.$dirty }" ng-model="form.CompanyName" name="CompanyName" maxlength="100" type="text" required />
</li>
</ul>
</form>
I want the cvError class to be added to this input if it is dirty, but nothing happens when I look at this in the browser. What am I doing wrong that is causing the <form> to just leave the DOM and then not work with my Angular expressions?
Welcome to the Angular world, no forms required! Here, the model is king. It looks like the problem is the ng-model and ng-class are point at different places.
Point everything at form.CompanyName (assuming that is the model name is form in the $scope):
<input id="CompanyName" ng-class="{ cvError : form.CompanyName.$dirty }" ng-model="form.CompanyName" name="CompanyName" maxlength="100" type="text" required />
The ng-model binds to the $scope. When you change the input field, it is automatically updated in the $scope. No form is needed or hitting a submit button to get the data. The $scope is updated with each key stroke.
The controller should do the work of figuring out what to do with the changes in the model. For example, you can add an ng-click to a button that fires a function defined by the controller to save the model.

Resources