Redux Form, Radio Button Fields, how to support variable values? - reactjs

In my react redux form, I have the following:
<fieldset className="form-group">
<legend>Radio buttons</legend>
{this.props.job_titles.map(jobTitle => (
<div className="form-check" key={jobTitle.id}>
<label className="form-check-label">
<Field
name="job_title_id"
component="input"
type="radio"
value={jobTitle.id}
/>
{' '}
{jobTitle.title}
</label>
</div>
))}
</fieldset>
This renders the radio buttons correctly, but when you click to select a radio button, the radio button never sets as selected. You can't select an option - the form is broken.
What's strange is if I update: value={jobTitle.id} to value="anything" then the radio buttons can be selected.
I'm not seeing anything in the redux form docs about radio buttons dynamically generated. What am I doing wrong?
Thanks

Convert value to String:
<Field
name="job_title_id"
component="input"
type="radio"
value={jobTitle.id.toString()}
/>

Set the checked property to a state or prop, then update that in the click handler.
<Field
onClick={
() => {
this.setState((prevState) => {
return {isChecked: !prevState.isChecked};
});
}
}
name="job_title_id"
component="input"
type="radio"
checked={this.state.isChecked}
value={jobTitle.id}
/>

Related

URL search parameters gets replaced - Remix Run

I'm working on a search UI where I have quite a few filters which I want as URL parameters when someone selects/checks the options. I've used the technique as advised on the Remix.run docs to come up with multiple forms within the filters. Each time a group of Filters gets submitted, the selected old parameters get disappeared. Heres my code,
<Panel header="Status" key="status">
<Form
name="search"
action='/search'
method="get"
onChange={(e) => submit(e.currentTarget, { replace: false })}
>
<ul>
<li>
<Checkbox
name="status"
value="buy_now"
defaultChecked={status.includes('buy_now')}
>
Buy Now
</Checkbox>
</li>
<li>
<Checkbox
name="status"
value="on_auction"
defaultChecked={status.includes('on_auction')}
>
On Auction
</Checkbox>
</li>
</ul>
</Form>
</Panel>
<Panel header="Price" key="price">
<Form name="search" action='/search' method="get">
<Select
name="blockchain"
value={
blockchain
? options.filter((a) => a.value === blockchain)
: undefined
}
options={options}
placeholder="Blockchain"
type="white"
/>
<div className="d-flex align-center price">
<TextInput
value={min ? min : undefined}
name="min"
placeholder="Min"
/>
<span>to</span>
<TextInput
value={max ? max : undefined}
name="max"
placeholder="Max"
/>
</div>
<button
onClick={(e) => {
e.stopPropagation()
submit(e.currentTarget, { replace: false })
}}
className="btn primary-btn btn-lg w-100"
>
Apply
</button>
</Form>
</Panel>
How Can I get around this to have all the parameters without having to manage them on my own using React state?
Edit:- I want the first filter to be submitted automatically and the latter to be submitted on a button click.
Bit of a UI of what I'm trying to achieve,
Answer: After investing enough time to look through for shortcuts, finally understood that it's not one of the magic that remix.run does. use something like formik and update the state imparatively.
When you submit a form, the only values included are the one under the submitted form. The values from any other form are not included (fortunately!).
So I'd use a single Form with all the inputs under it (checkboxes as well as text inputs).
Then instead of a onChange on the Form, you can add something like an onChange handler on the checkboxes and submit the form inside imperatively (using a ref click on the submit button or something, I think using a ref on the form you need to submit all values in the submit function so a button ref click may be simpler).
Keep in mind that if you want to "restore" the field values after submitting, you need to return them from the loader function like this:
// Loader function
const url = new URL(request.url);
return {
results: [...],
values: Object.fromEntries(url.searchParams.entries())
};
Then in the component, use values from useLoaderData:
<input type="text" name="max" defaultValue={values.max || ""}/>
Added benefit: if you come back to this page (by clicking browser back for example), your search parameters and search results are still there!
I actually put up a stackblitz for you but I lost all my changes :(
It seems like you could just keep all fields in a single form and submit that form when the submit button is pressed.
Then onChange, check if the target's name is 'status', and submit the form anyway.
export default function App() {
const submit = (form) => {
form.submit();
};
return (
<form
name="search"
action="/search"
method="get"
onChange={(e) => {
if (e.target.name === "status") {
submit(e.currentTarget);
}
}}
>
<fieldset>
<legend>status</legend>
<label>
<input type="checkbox" name="status" value="buy_now" />
buy_now
</label>
<label>
<input type="checkbox" name="status" value="on_auction" />
on_auction
</label>
</fieldset>
<fieldset>
<legend>price</legend>
<label>
<div>blockchain</div>
<select name="blockchain">
<option value="option_1">Blockchain Option 1</option>
<option value="option_2">Blockchain Option 2</option>
</select>
</label>
<label>
min <input type="number" name="min" />
</label>
<label>
max <input type="number" name="max" />
</label>
</fieldset>
<button type="submit">Apply</button>
</form>
);
}
demo
Note: not sure what your motivation is to want to separate this into separate forms, but I think the magic you're referring to is that server state, URLSearchParams, FormData and UI are all aligned because they are using the same underlying data using only common web APIs.

How To Check checked value of a checkbox using Reactstrap

I've got a React web app using bootstrap 4 and Reactstrap. I want to have several checkboxes in a toolbar and I can't figure out how to get anything out of the onChange event besides "on".
Here is my code that continues to write "on" to the console every time I click the checkbox. The checkbox does toggle on and off.
<li className="show-sessions">
<FormGroup check>
<Label check>
<Input
type="checkbox"
onChange={(e) => console.log(e.target.value)}
/>{" "}
<strong>Show Favorites</strong>
</Label>
</FormGroup>
</li>
Is there another way to make a checkbox in Reactstrap? The doc's are very limited.
you can check checked state rather than value; it is a boolean
<Input
type="checkbox"
onChange={(e) => console.log(e.target.checked)}
/>

Warning in Chrome for updating "value" attribute in React without onChange

I am creating a form. There is a radio input that chooses the value of the next input. The code works are written, but I get a warning in the Chrome console. I've tried adding onChange() several different ways but all I get are errors. How do I fix this warning.
const [lyeConcentration, setLyeConcentration] = useState("33.33%");
const [lyeUnits, setLyeUnits] = useState("percentage");
<div onChange={e => setLyeConcentration(e.target.value)}>
<input type="radio" id="lyePercentage" name="lyeUnits" value="33.33%" defaultChecked />
Percentage
<input type="radio" id="lyeRatio" name="lyeUnits" value="2:1" />
Ratio
</div>
<div>
<label htmlFor="lyeConcentration">Lye Concentration</label>
<input id="lyeConcentration" value={lyeConcentration} type="text" className="lyeConcentration" autoComplete="off" />
</div>
try the code below, i added onChange to both radio input and the text input.
I think its actually complaning about the text input.
const [lyeConcentration, setLyeConcentration] = useState("33.33%");
const [lyeUnits, setLyeUnits] = useState("percentage");
return (
<>
<div>
<input type="radio" id="lyePercentage" name="lyeUnits" value="33.33%" onChange={e => setLyeConcentration(e.target.value)} defaultChecked />
Percentage
<input type="radio" id="lyeRatio" name="lyeUnits" onChange={e => setLyeConcentration(e.target.value)} value="2:1" />
Ratio
</div>
<div>
<label htmlFor="lyeConcentration">Lye Concentration</label>
<input id="lyeConcentration" value={lyeConcentration} type="text" className="lyeConcentration" autoComplete="off" onChange={e => setLyeConcentration(e.target.value)}/>
</div>
</>
)

Radio button when clicked to show what is clicked

I'm using reactjs chartjs 2 to create some charts. I have a radio button as you can see of two values of Line and Bar. When one is clicked I want it to show the one that is clicked and when the other one is clicked show that one. But it is not working out, anyone might have a clue?
<div>
<label>Choose your chart sample:</label>
<label>Line Chart
<input
value="Line"
name="Line"
type="radio"
checked={"Line" === this.state.chartOption}
onChange={e => {
this.setState({chartOption: e.target.value})
}}
/>
</label>
<label>Bar Chart
<input
value="Bar"
name="Bar"
type="radio"
checked={"Bar" === this.state.chartOption}
onChange={e => {
this.setState({chartOption: e.target.value})
}}
/>
</label>
</div>
<this.state.chartOption data={data} />
```

React I can't change my input field's value if it has a value and onChange

I have a CRUD application, in my component's state I save the name of the user. Now the problem is: I have an input field for name in my form and when the user clicks on update user from the list, the selected user's name will appear on the input field and then I'm unable to change the name because the input field won't let me. I delete a letter and it reappears automatically, how can I fix this?
In my component's render method:
<div className="col-sm-9">
<div className="form-check">
<input name="user_name" ref="user_name" className="form-check-input" type="checkbox" value="1" id="user_name"
value={this.state.user_name} onChange={this.onChange} />
</div>
</div>
Outside my render method:
onChange(e) {
this.setState({[e.target.name]: e.target.value})
}
Have you bind your onChange method(i suppose that is the issue, that your state is not getting updated). If not, then :
try changing to this :
onChange = (e) => {
this.setState({[e.target.name]: e.target.value})
}
Or to this :
<div className="col-sm-9">
<div className="form-check">
<input name="user_name" ref="user_name" className="form-check-input" type="checkbox" value="1" id="user_name"
value={this.state.user_name} onChange={this.onChange.bind(this)} />
</div>
</div>

Resources