How to use Formik inside Input component - reactjs

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.

Related

React Hook Form Controller and React-Bootstrap Form.Check radio

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?

Ant.design does not detect custom input component in Form.Item React

So, the main problem is, that antd form does not detect my custom input based on antd standard input:
There is a piece of form code (AddProduct):
<Form.Item
className="m-t-10"
name="price"
rules={[
{
required: true,
message: `${t('FORM.ERR.SHOP.PRICE')}`,
},
]}
>
<CurrencyInput size="small" placeholder={t('FORM.SHOP.PRICE_VAT')} name="price" />
</Form.Item>
There is my custom input (CurrencyInput):
return (
<Input size={props.size} placeholder={props.placeholder} name={props.name} type="number" prefix={settings[6].value} />
)
The problem is when I try to submit the form it does not detect currency input, throws err that this field is required. Any ideas are it possible to implement custom input, basically, it's more HOC than custom input
You need to pass to your custom component all props, because Form.Item pass to there onChange and value props
function CustomInput({size, placehodler, name, ...restProps}) {
return (
<Input size={size} placeholder={placeholder} name={name}
type="number" prefix={settings[6].value} {...restProps} />
)
}

Dynamically rendering Custom Radio Button Component

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" />

How to update the state in react outside a render method using a function

I am using a redux-form to submit data that user enters into a form-input to an api. The inputs of the redux-form are for editing the values of existing data in the form.So,what I want is to populate the input values of the form with the previous(existing) value which comes from the api.So,I used props to get the existing values and assign those values to the component state.And when the input changes, then I am changing the state for that input using setState. Now,the issue that I am facing is, since I am using redux-form, I am using Field component which comes from redux-form.So,this is how my render() method looks like:
render() {
const { handleSubmit } = this.props;
return (
<form onSubmit={handleSubmit(this.onSubmit.bind(this))}>
<Field
label="Title for Post"
name="title"
component={this.renderField}
/>
<Field
label="Post Content"
name="body"
component={this.renderField}
/>
);
}
And the renderField() method which is used above looks as shown below:
renderField(field) {
return(
<div className="title-design">
<label className="label-design"> {field.label} </label>
<input
type="text"
className="title-input"
{...field.input}
value={this.state.title}
onChange={this.onInputChange}
/>
<div className="text-help has-danger">
{field.meta.touched ? field.meta.error : ''}
</div>
</div>
)
}
And the onInputChange() method looks like:
onInputChange(event) {
this.setState({title: event.target.value})
}
So,since my input is in the renderField() method,so when I try to type something in the input,I do not see the state updated(because my renderField() method is used as a prop and it is not in the render method,so state is not being updated), and that is the reason why my input is not working properly.I mean I am not able to insert or delete values in the input.
But,if I use the input as shown below inside my render method,it works properly as expected.
<input
type="text"
className="title-input"
value={this.state.title}
onChange={this.onInputChange}
/>
But,I don't know how to pass the values with only input as shown above to a redux-form.So, how to proceed with this? Can anyone please help me figure out?Thanks in advance.

How to get default value in radio button component?

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.

Resources