Redux Form Semantic UI React Dropdown meta:touched not working - reactjs

Redux Form Semantic UI React Dropdown meta:touched not working
My Redux form has two Semantic UI React Dropdown components. One dropdown the user selects a month (January thru December) and the other the user selects a year (2020 thru 2030). I have a requirement to validate that the month and year provider by the user is not in the past. For example, it is now May 2020 and if the user selects January 2020 an error needs to be shown to the user.
I’ve created a validator that properly works and creates an error for the above condition. The problem is that the Dropdown component’s “touched” meta is always false so the error is never displayed to the user.
Code for my DropdownInput component is shown below.
If a remove “touched” from the error label, the error displays immediately before the user has a chance to input their date… not a good user experience.
Any suggestions as to how to get the Dropdown component to update to “true” when the user makes a selection would be appreciated. I’ve also used the Semantic UI React Select component in place of the Dropdown component and have the same result.
Thanks in advance for your suggestions.
import React from 'react';
import { Form, Label, Dropdown } from 'semantic-ui-react';
const SelectInput = ({
input,
multiple,
options,
placeholder,
size,
style,
label,
meta: { touched, error },
}) => {
console.log(`DropdownInput: touched=${touched} error=${error}`);
return (
<Form.Field error={touched && !!error}>
{label && <label>{label}</label>}
<Dropdown
selection
value={input.value || null}
onChange={(e, data) => input.onChange(data.value)}
multiple={multiple}
options={options}
placeholder={placeholder}
size={size}
style={style}
/>
{touched && error && (
<Label basic color='red'>
{error}
</Label>
)}
</Form.Field>
);
};
export default SelectInput;

Related

React final form with datepicker validation

Is there any way to display error message if the validation on the Field level fails when using react datepicker?
I am using datepicker with react final form:
const DatePickerAdapter = ({ input: { onChange, value }, ...rest }) => (
<DatePicker
selected={value}
onChange={(date) => {
console.log(date);
onChange(date);
}}
{...rest}
/>
);
And then I put into Field component from RFF:
<Field
name="date"
validate={required}
dateFormat="yyyy/MM/dd"
component={DatePickerAdapter}
/>
The issue is that it wont display any error if for example I leave the field empty or any part of validation is not passing. Is there a way to display this error message somehow in final form component?
Here is my codesandbox- other fields with validation can show error message but Field with datepicker is not:
https://codesandbox.io/s/react-final-form-third-party-components-example-datepicker-forked-wzrqgr?file=/index.js:2392-2579
my recommendation would be to use Formik and Yup. With Formik package use useFormik that will ask for initial values that would be empty string, validationSchema that would be from yup and lastly ask for onSubmit that is linked to button.
See a quick example in this url:
https://stackblitz.com/edit/react-ff8inu?file=src/App.js
This code will not work since the program is wrote inside Stackblitz react and not react native but idea stay the same

ReactJS + Ant Design: hook up two AntD components

I am a newbie and I have an issue that I need to connect two components(slider and radio buttons) from Ant design in React and make them collaborate together. So if I choose one of the options of the radio button, I want the slider to adjust the choice and conversely. For example, if I choose on the radio button year 2022 I want the to slider move to the right, and for example, if I choose 2022 on the slider I want to have checked radio button value 2022, and so on... I tried to put them into some conditions, but really don't know what to do with them. And also to have radio buttons in same width as slider.
import React from "react";
import { Radio, Slider } from "antd";
const App = () => {
const [currentValueRadio, setcurrentValueRadio] = React.useState(1);
const [currentValue, setCurrentValue] = React.useState();
return (
<>
<Radio.Group
onChange={(e) => {
console.log("radio checked", e.target.value);
setcurrentValueRadio(e.target.value);
}}
value={currentValueRadio}
>
<Radio value={1}>2021</Radio>
<Radio value={2}>2022</Radio>
</Radio.Group>
<Slider
defaultValue={2021}
min={2021}
max={2022}
style={{ width: 240 }}
onChange={(value) => {
console.log(currentValue);
setCurrentValue(value);
}}
/>
</>
);
};
https://codesandbox.io/embed/radio-group-antd-4-19-4-forked-134cps?fontsize=14&hidenavigation=1&theme=dark
You need to add the state being controlled as a 'value' prop to both components, to have them syncronised.
<Slider
value={currentValueRadio} // <- add a value prop
defaultValue={2021}
...
Adding the value prop in your example will have both components react to the same state value.
However, since the Radio components set the value to 1 or 2, and the range on the Slider is from 2021 to 2022, you may not see the result you're looking for. Perhaps change the Radio values to 2021 and 2022 respectively.

react-final-form with multiple select

I'm trying to build a form with a multiple value Select component by Material-UI using react-final-form. Somehow with single Select, I can get the value but with multiple, it doesn't. Somehow it seems like react-final-form is holding its own value internally.
Here's a the guiding link from Material-UI for building multiple Select:
https://codesandbox.io/s/sr6pf
I tried to replicate the very first example (without using react hook) in my form and I still miss something ?
https://codesandbox.io/embed/react-final-form-material-ui-example-jfmoe
What should I add to my Component to make this work ?
Thanks,
For some reasons I've managed to figure out the solution for my own question. The proper answer is to create a custom MultiSelect component instead of reusing the one from final-form-material-ui.
Notes: I've tried to use <Select /> from final-form-material-ui but adding multiple prop to the component will not be passed to , this is weird.
So, my custom component would look like this, almost similar to the one from their github with multiple prop added.
import React from 'react';
import FormControl from '#material-ui/core/FormControl';
import FormHelperText from '#material-ui/core/FormHelperText';
import InputLabel from '#material-ui/core/InputLabel';
import Select from '#material-ui/core/Select';
function SelectMulti({
input: { name, value, onChange, ...restInput },
meta,
label,
formControlProps,
...rest
}) {
const showError =
((meta.submitError && !meta.dirtySinceLastSubmit) || meta.error) &&
meta.touched;
return (
<FormControl {...formControlProps} error={showError}>
<InputLabel htmlFor={name} shrink>
{label}
</InputLabel>
<Select
{...rest}
multiple
name={name}
value={value}
onChange={onChange}
inputProps={restInput}
/>
{showError && (
<FormHelperText>{meta.error || meta.submitError}</FormHelperText>
)}
</FormControl>
);
}
SelectMulti.propTypes = {};
export default SelectMulti;
Hope this help someone in the future
I was able to solve this with by setting the fomat as such
<Field
name="concepts"
component={Select}
displayEmpty={trie}
multiple={true}
value={[]}
format={value => value || []}
/>
As per https://github.com/erikras/redux-form-material-ui/issues/212#issuecomment-358376925

Rendering Formik Field outside Formik form

We have our own input components (like Checkbox, Textbox, or even CurrencyInput component)
We are now using Formik. So we replaced all <input... with <Field... in our components, eg.
const Checkbox = (props) => {
...
return (
<div className={myClass1}>
<Field type='checkbox' name={props.name} className={myClass2} ... />
<label ...>{props.label}</label>
</div>
)
};
Now the problem is, we can't have a standalone Checkbox outside a form anymore (eg. for an on-screen-only option). It will throw:
this.props.formik.registerField is not a function
We feel this is a dealbreaker. But before we ditch Formik and write our own form validation logics, I wonder if anyone else are having this dependency issue.
Is there really no way of rendering Formik Field outside Formik?
The Field component is what connects a form field to the Formik state. It uses context under the hood; Formik is the context provider and Field is the context consumer. Field is tied to Formik and has no use outside of it. For your use case where you want to render form fields that are sometimes connected to Formik and sometimes not, I would export two different components:
The base Checkbox component that has nothing to do with Formik. It should just use a normal input
A Field wrapper around that Checkbox component
While the Field component can take a type, causing it to render the corresponding input, it can also take a render prop to render whatever you want, and it is passed all of the state Formik manages for that field.
For example, your Checkbox and CheckboxField components could looks something like this:
const Checkbox = (props) => {
...
return (
<div className={myClass1}>
<input type='checkbox' checked={props.checked} onChange={props.onChange} />
<label ...>{props.label}</label>
</div>
)
};
const CheckboxField = (props) => {
return (
<Field name={props.name}>
{(field) => <Checkbox label={props.label} {...field} />}
</Field>
)
}
Now you use have two components that render exactly the same, but one is meant to be used within a Formik form (CheckboxField) and the other can be used anywhere (Checkbox).

redux-form dynamic wizard

I'm trying to create a wizard (form) with a dynamic number of steps (with redux-form).
At every step, the user can either go to the last step of the wizard or add an extra step.
An example would be a wizard to order a customizable item. Each step of the wizard contains all the fields to configure the item. The user can then either add another item and configure it or go to the checkout (last step of the wizard).
I'm following the Wizard example but I'm unsure how to add steps dynamically. I tried mixing it up with a FieldArray without success.
Any help?
I did something similar for my work. For your case, if a user selects a certain answer on the same page, you can just do conditional rendering for showing the next page/dynamic values.
My case also had conditional rendering. I had to use formValueSelector API to access form values on different pages. Here is the modified wizard code from the redux-form example Wizard. If you choose male on second page, you get favorite color dropdown question on third page. If you choose female, you get an employed checkbox question.
I made a conditional variable of isMale and return different Field depending on if male answer is true or not. I'm sure there are more elegant ways to do this, but this is one way that worked for me.
https://codesandbox.io/s/34jp9rqp71
I just modified/added these parts of the code.
WizardFormThirdPage.js
import { Field, reduxForm, formValueSelector } from "redux-form";
import { connect } from "react-redux";
let WizardFormThirdPage = props => {
const { sex, handleSubmit, pristine, previousPage, submitting } = props;
var isMale = sex == "male" ? true : false;
return (
<form onSubmit={handleSubmit}>
{isMale && (
<div>
<label>Favorite Color</label>
<Field name="favoriteColor" component={renderColorSelector} />
</div>
)}
{!isMale && (
<div>
<label htmlFor="employed">Employed</label>
<div>
<Field
name="employed"
id="employed"
component="input"
type="checkbox"
/>
</div>
</div>
)}
. . .
</form>
);
};
const mapStateToProps = state => ({
sex: formValueSelector("wizard")(state, "sex")
});
WizardFormThirdPage = connect(mapStateToProps)(WizardFormThirdPage);

Resources