React-Hook-Form Input Element is Empty in Inspect Element but Not in Browser - reactjs

I am using react-form-hook in a project. I have css styles based on input field value attributes. react-form-hook is setting the values of all the inputs but doesn't show in inspect element niegther my css styles work. I just want to know how react-form-hook set the values on input elements when there is no actual value. Here is the code
import React, { useState } from 'react';
const CustomInput = (props: any) => {
const { label, name, className, type, onChange, register, setValue, value, disabled } = props;
return (
<div className="custom--input--container">
<input
type={type}
name={name}
ref={register}
className={`custom--input ${className}`}
onChange={e => {
onChange();
setValue(name, e.target.value, { shouldValidate: true });
}}
/>
<span className="custom--input--label">{label}</span>
</div>
);
};
export default CustomInput;
Component used here
<CustomInput
label="First Name*"
type="text"
name={SettingsFormFields.FIRST_NAME}
className={classNames({
error: errors[SettingsFormFields.FIRST_NAME],
})}
setValue={setValue}
register={register}
onChange={enableButton}
/>
value is being displaed
No value in inspect element

Related

What am I misunderstanding in my boolean radio group in Formik?

Following the Radio Group Example in the Formik docs and using Bootstrap 5 I've tried to create a boolean radio component that gets passed in a name and label. However, on render with the initialValues:
<Formik
initialValues={{
foo: false,
bar: false,
}}>
the no is selected because the initial value is set to false but whenever yes is chosen the radio will not fill in, component:
import React from 'react'
import PropTypes from 'prop-types'
import { Field } from 'formik'
const RadioBool = ({ name, label }) => {
const yesId = `${name}-yes`
const noId = `${name}-no`
return (
<>
<p id={`${name}-group-label`}>{label}:</p>
<div className="form-group mb-4" role="group" aria-labelledby={`${name}-group-label`}>
<div className="form-check">
<label htmlFor={yesId}>Yes</label>
<Field id={yesId} className="form-check-input" type="radio" name={name} value={true} />
</div>
<div className="form-check">
<label htmlFor={noId}>No</label>
<Field id={noId} className="form-check-input" type="radio" name={name} value={false} />
</div>
</div>
</>
)
}
RadioBool.propTypes = {
name: PropTypes.string.isRequired,
label: PropTypes.string.isRequired,
}
export default RadioBool
but if checked is added to Yes, example:
<Field id={yesId} className="form-check-input" type="radio" name={name} value={true} checked />
the radio group works and I'm not sure why.
tests:
<RadioBool name="foo" label="Look at foo?" />
<RadioBool name="bar" label="Look at bar?" />
Research
How to add Radio Button in Formik Validations Reactjs?
How to create Radio buttons with Formik?
How to make use of Radio Group with useFormik Hook
how do you use onChange property on react formik radio field
formik radio button validation issues
Why does my boolean radio component not work in Formik unless checked is used on one <Field />?
The problem is described here Radio values must be strings, can't be numbers or booleans and as I see it's not solved 'from the box' yet.
In my TypeScript project I've created custom component. May it would be helpfull for you:
import React, { FC } from 'react';
type Props = {
name: string
value: boolean
checked: boolean
setValues: (values: React.SetStateAction<any>, shouldValidate?: boolean) => void;
}
const RadioButtonBooleanField: FC<Props> = ({name, value, checked, setValues}) => {
return (
<input type='radio' className="form-check-input" name={name} value={String(value)} checked={checked}
onChange={(e: any) => {
setValues((prevValues: any) => ({
...prevValues,
[e.target.name]: e.target.value === "true"
}))
}
}
/>
);
};
It can be used like this inside Formik component:
{({ errors, touched, values, setValues }) => (
<RadioButtonBooleanField name="IsExtendedView" value={false} checked={!values.IsExtendedView} setValues={setValues}/>
)}

React phone input 2 with react hook form

I am using PhoneInput along with react hook form, I want to enable save button only if phone number is valid
Code:
<form onSubmit={handleSubmit(onSubmitRequest)}>
.....................other code..............
<Controller
as={
<PhoneInput
id="pNum"
placeholder="Enter phone number"
className={classes.phoneInput}
inputRef={register({required: true})}
isValid={(inputNumber, onlyCountries) => {
return onlyCountries.some((country) => {
return startsWith(inputNumber, country.dialCode) || startsWith(country.dialCode, inputNumber);
});
}}
/>
}
name="phoneNumber"
control={control}
/>
........................other code...................
<Button
fullWidth
type="submit"
variant="contained"
color={'primary'}
className={classes.submitBtn}
data-testid="customerFormButton"
disabled={!formState.isValid}
>
Save
</Button>
</form>
Here I used PhoneInput as controller along with isValid for it. How can I disable Save button for invalid phone number input?
How are you? I believe that your problem is because you are not configuring the rules for the controller.
You need to change your controller to something like this:
<Controller
as={
<PhoneInput
id="pNum"
placeholder="Enter phone number"
className={classes.phoneInput}
inputRef={register}
isValid={(inputNumber, onlyCountries) => {
return onlyCountries.some((country) => {
return startsWith(inputNumber, country.dialCode) || startsWith(country.dialCode, inputNumber);
});
}}
/>
}
name="phoneNumber"
control={control}
rules= {{required: true}}
/>
ref cannot be currently used on this element. react-phone-input-2.
Until its supported, you can provide a hidden input field which updates its value when the phone updates its value and put the ref on that
Example:
import React, { FC, useCallback } from 'react';
import { useFormContext } from 'react-hook-form';
import PhoneInput from 'react-phone-input-2';
import 'react-phone-input-2/lib/style.css';
interface Props {
handleChange: (name: string, val: string) => void;
defaultValue: string;
name: string;
}
const MyComponent: FC<Props> = ({ defaultValue, name, handleChange }) => {
const { register, setValue, watch } = useFormContext(); // Note: needs <FormProvider> in parent for this to be acessible
const nameHidden = `${name}Hidden`;
const handleChangePhone = useCallback(
(val: string) => {
setValue(nameHidden, val, { shouldValidate: true });
handleChange(name, val);
},
[handleChange]
);
return (
<>
<PhoneInput value={defaultValue as string} country="gb" onChange={handleChangePhone} />
<input
type="hidden"
name={nameHidden}
defaultValue={defaultValue}
ref={register({
// validate stuff here...
})}
/>
</>
);
};
export default MyComponent;

How to add react-phone-number-input to -react-final-form?

I'm currently creating a form using react-final-form and trying to use react-phone-number-input with it through integration as an adapter, as displayed through this example.
I attempted to use the example to learn how it is done, but I'm not sure how to access the component and create the adapter for it properly.
import React from 'react';
import { Form, Field } from 'react-final-form';
import PhoneInput from 'react-phone-number-input';
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms))
const onSubmit = async values => {
await sleep(300)
window.alert(JSON.stringify(values, 0, 2))
}
const PhoneAdapter = ({ input, meta, ...rest }) => (
<PhoneInput
{...input}
{...rest}
value={input.value}
onChange={(event, value) => input.onChange(value)}
/>
)
class ContactForm extends React.Component {
render() {
return (
<>
<Form
onSubmit={onSubmit}
initialValues={{ }}
render={({ handleSubmit, form, submitting, pristine, values }) => (
<form onSubmit={handleSubmit}>
<fieldset>
<Field component={PhoneAdapter} />
</fieldset>
<fieldset>
<button type="submit" disabled={submitting || pristine}>
Submit
</button>
</fieldset>
<pre>{JSON.stringify(values, 0, 2)}</pre>
</form>
)}
/>
</>
);
}
}
export default ContactForm;
Update: July 2019
Apparently, all you need to do is to spread the input property of Field. Works flawlessly. Learn about spreading if you're not familiar with it.
const PhoneAdapter = ({ input }) => (
<PhoneInput {...input} />
)
<Field name="phone" placeholder="Enter phone number" component={PhoneAdapter} />
I ended up experimenting with the FieldRenderProps props until it worked out. I wasn't so sure whether it would work or not, as react-phone-number-input is two elements in a component. I thought it would implement the input on only one of the elements.
By using input, I gain access to the input's props. Hence, I called upon it's value, as the default looks like so:
<PhoneInput
placeholder="Enter phone number"
value={ this.state.value } // This is what I called.
onChange={ value => this.setState({ value }) }/>
I then did the same for the onChange function prop.
const PhoneAdapter = ({ input }) => (
<PhoneInput value={input.value.value} onChange={value => input.onChange(value)} />
)
Finally, I used the component adapter like so:
<Field name="phone" placeholder="Enter phone number" component={PhoneAdapter} />

How to get formvalues in handlechange?

In my form I have an onChange event on one of the formfields:
<div>
<label>Last Name</label>
<div>
<Field
name="lastName"
component="input"
type="text"
placeholder="Last Name"
onChange={() => this.handleChange()}
/>
</div>
</div>
When handleChange gets fired I want to get the formvalues :
handleChange(){
//do calculation
console.log('handlechange',this.props.values)
}
At the moment I am getting this.props.values = undefined? How can I get the formvalues?
You'll need to create a custom input.
You'll need to intercept and update redux's input.onChange function.
Optional -- If you want other form values to influence this value, then utilize reduxForm's formSelector with react-redux's connect's mapStateToProps to access formProps within the component in this.props (the working example below already includes this functionality)
components/CustomInput.js
import React from "react";
const CustomInput = ({
// we'll intercept redux's "onChange" func, while leaving the other
// input props as is in "inputProps"
input: { onChange, ...inputProps },
// the "handleChange" func below is the parent func that will handle input changes
handleChange,
// "rest" contains any additional properties (className, placeholder, type ...etc)
...rest
}) => (
// we spread out the "inputProps" and the "rest" of the props, then we add
// an "onChange" event handler that returns the "event" and the
// input's "onChange" func to our "handleChange" parent func
<input {...inputProps} {...rest} onChange={e => handleChange(e, onChange)} />
);
export default CustomInput;
containers/Form.js
class ControlledFormValue extends PureComponent {
// this parent func will handle updates through the "event.target.value";
// the value can be changed/altered and then passed to the input's
// "onChange" func to update the field
handleChange = ({ target: { value } }, onChange) => {
// this will alter the value by adding a "-" after each input update
onChange(`${value}-`);
setTimeout(() => console.log(this.props.values), 500);
};
render() {
return (
<form onSubmit={this.props.handleSubmit}>
<div>
<label>First Name</label>
<div>
<Field
className="uk-input"
name="firstName"
component={CustomInput}
type="text"
placeholder="First Name"
handleChange={this.handleChange}
/>
</div>
</div>
...etc
</form>
);
}
}
Working example: https://codesandbox.io/s/lx1r4yjwy7

How to use react-select with redux-form?

I am trying to integrate react-select using redux form...
Here is my code
import Select from 'react-select'
import StyledSelectField, { StyledMessages } from './style'
const SelectField = props => {
const { input, label, placeholder, options, meta, ...StyledProps } = props
const { onChange, onBlur, onFocus } = props.input
return (
<StyledSelectField {...StyledProps} meta={meta} hasValue={!!input.value}>
<label htmlFor={input.name}>{label}</label>
{placeholder && <div className="placeholder">{placeholder}</div>}
<Select
name={input.name}
value={input.value.value}
onChange={onChange}
onBlur={onBlur}
onFocus={onFocus}
options={options}
{...props}
/>
<StyledMessages>
{meta.touched &&
((meta.error && <span className="error">{meta.error}</span>) ||
(meta.warning && <span className="warning">{meta.warning}</span>))}
</StyledMessages>
</StyledSelectField>
)
}
class TestingCycleForm extends PureComponent {
render() {
const { preMonitoring, handleChange, handleSubmit } = this.props
return (<div>
<Field
label="18%"
name="patientPercentage"
className="form-control"
component={SelectField}
options={Config.get('/PATIENT_PERCENTAGE')}
/>
</div>)
}
}
All things are working but my input field gets cleared on focus out what I am doing wrong here?
Thanks in advance... Any help would be appreciated
You say “focus out” - does that mean it clears on blur? If so, does setting onBlurResetsInput and onCloseResetsInput to false help?
Update: here's the link to the props table from the github readme. You've got to set both onBlurResetsInput and onCloseResetsInput to false at the same time, onBlurResetsInput set to false, by itself, will do nothing.
And also you need to remove the onBlur prop from the select which causes field clear on Blur
<Select
name={input.name}
value={input.value.value}
onChange={onChange}
onBlurResetsInput={false}
onCloseResetsInput={false}
onFocus={onFocus}
options={options}
{...props}
/>

Resources