I am trying to dynamically render a custom button component in a form in react js.
Here is my radio custom button component.
export class CustomRadio extends Component {
render() {
return (
<div>
<FormGroup>
<ControlLabel>{this.props.label}</ControlLabel>
<br />
<input type="radio" name={this.props.name} />
</FormGroup>
</div>
);
}
}
The below is how I call that component in a form
<CustomRadio label="status" />
Anyways I was not able to get the expected output. Can anyone help me out to solve this matter?
First thing, you must import your component as,
import {CustomRadio} from './CustomRadio'; //because you are exporting as named export
Another thing, as you are using this.props.name you must pass it as,
<CustomRadio label="Status" name="name"/>
By looking at FormGroup, I think you are using reactstrap, in reactstrap you can use this to get radio button,
<FormGroup>
<Label>
<input type="radio" name={this.props.name} />
{this.props.label}
</Label>
</FormGroup>
Demo
Note:
If ControlLabel is another custom component, then you can do this,
<FormGroup>
<ControlLabel>
<input type="radio" name={this.props.name} />
{this.props.label}
</ControlLabel>
</FormGroup>
And your ControlLabel component should be,
const ControlLabel = (props) => {
return (
<Label>{props.children}</Label>
)
}
As you have mentioned the name as a prop in CustomRadio component you must need to pass name also from here as follows:
<CustomRadio label="status" name="Xyz" />
Related
I'm using React Hook Form and React-Bootstrap and I'm trying to set up a radio button group.
Radio 1 should be selected by default and then the user can switch between them.
Because I'm using Form.Check from React-Bootstrap I'm wrapping it in a React Hook Form Controller (Wrapper component for controlled inputs).
It should look like this:
This works fine for all the normal text inputs:
<Controller
control={control}
name="name"
defaultValue=""
render={({ field: { onChange, value, ref } }) => (
<Form.Control
type="text"
onChange={onChange}
placeholder="Name"
value={value}
isInvalid={!!errors.name}
ref={ref}
/>
)}
/>
But for radio boxes this doesn't seem to work. It's rendered without a default checked box, I can select both of them, and the submitted data is always the same.
Here's the code for the radio boxes:
Controller
control={control}
name="myradiovalue"
defaultValue="radio1"
render={({ field: { onChange } }) => (
<>
<Form.Check
onChange={onChange}
type="radio"
label="Radio 1"
id="formAdapterRadio1"
value="radio1"
/>
<Form.Check
onChange={onChange}
type="radio"
label="Radio 2"
id="formAdapterRadio2"
value="radio2"
/>
</>
)}
/>
How should this look? Separate Controllers maybe?
I wanted to build multi-step form with state preservation and thankfully I've found number of tutorials for that. However, once I've started doing some modifications and adjustments I got a bit confused why it's not working.
I wanted to add select into form/basic.js but for some reason I'm getting error:
input is a void element tag and must neither have children nor use
dangerouslySetInnerHTML.
in input (created by Field)
Additionally I'm using React Router to retain data. That's the code of a form:
import React, { Component } from "react";
import { Link } from "react-router-dom";
import { Field } from "formik";
class BasicPage extends Component {
render() {
return (
<div>
<div>
<Field type="email" name="email" placeholder="Email" />
</div>
<div>
<Field type="text" name="firstName" placeholder="First Name" />
</div>
<div>
<Field type="text" name="lastName" placeholder="Last Name" />
</div>
<div>
<Field name="country" as="select">
<option value="france">France</option>
<option value="greece">Greece</option>
<option value="denmark">Denmark</option>
</Field>
</div>
<Link to="/form/location" className="next">Next</Link>
</div>
);
}
}
export default BasicPage;
Whole codesandbox is here - https://codesandbox.io/s/tmp-forked-dv66l . Error can be seen in "Wizard" page.
Formik introduced the <Field as> in version 2, and your using version 0.11.11.
Try bumping the version to 2.2.5, and your example should work.
https://codesandbox.io/s/tmp-forked-vsz2b?file=/src/index.js
I have created an input component to try avoid repetition of the bootstrap divs/classes. It looks like this:
import React from "react";
import "./Input.css";
const Input = ({ name, label, error, ...rest }) => {
return (
<div className="form-group">
<label htmlFor={name}>{label}</label>
<input
{...rest}
id={name}
name={name}
className="form-control form-control-lg"
></input>
{error && <span className="input-error">{error}</span>}
</div>
);
};
export default Input;
Then on the form, I just call it like this:
<Input name="lastName label="Last Name" type="text" />
But because I want to use Formik I have to add the onBlur, onChange and error. But it is very repetitive to have to add those to each input. I have tried to add them into my Input component but I obviously get errors about useFormik not existing and I am a bit stuck. This is the input after adding formik
<Input
name="lastName"
label="Last Name *"
type="text"
value={formik.values.lastName}
onBlur={formik.handleBlur}
onChange={formik.handleChange}
error={formik.touched.lastName && formik.errors.lastName}
/>
I basically want to be able to add onBlur, onChange and error to the input component.
You have to wrap your inputs with Formik as it injects context to React tree, then you will be able to use useField in your custom input component.
FormControl is a component from react-bootstrap and has by default the class form-control. I want to remove this class when this input is inside the FormGroup with class "mygroup".
<FormGroup className="mygroup">
<FormControl>
</FormGroup>
You can set the prop "bsClass" to override the default styles applied by react-bootstrap.
Set it to empty string or to any custom class that you want.
<FormGroup className="mygroup">
<FormControl
bsClass=""
type="text"
placeholder="Enter text"
/>
</FormGroup>
More details here - https://5c507d49471426000887a6a7--react-bootstrap.netlify.com/components/forms/
I have created a radio component but when clicked it does'nt show checked
here is the code
import React from 'react';
import classnames from 'classnames';
const RadioButton = (field) => {
const inputClasses = classnames('form-group has-feedback ',{
'has-error': field.meta.touched && field.meta.error,
});
console.log(field.input.value)
return(
<div className={inputClasses}>
<label className="radio-inline custom-radio nowrap">
<input
type="radio"
name={field.id}
onClick={e => field.input.onChange(field.val)}
/>
<span>{field.label}</span>
</label>
</div>
);
};
export default RadioButton;
here is the field:
<Field
component={RadioButton}
label ="Yes"
name="person.gender"
id="person.gender"
val={true}
/>
<Field
component={RadioButton}
label ="No"
name="person.gender"
id="person.gender"
val={false}
/>
So, how to get default value that is the initial value?
i want to get default value
<Field
component={RadioButton}
label ="No"
name="court.lit"
id="court.lit"
val={field.val}
defaultChecked={false}
/>
If you want to share the value from parent Field component you have to pass its value to the child. Then pass to RadioButton component.
<input
type="radio"
name={field.id}
value={field.val}
onClick={e => field.input.onChange(field.val)}
/>
but when clicked it does'nt show checked
You missed the value field
When using the redux-form library (which I assume is the case given your use of field.meta and field.input), you generally want to follow this pattern:
<input
{...field.input}
// your fields here
/>
This way, the onChange, value, and other fields are set for you.