I am building a form with Yup, React Hook Form and, MUI V5. I am using a DateTimePicker from MUI V5 but it is not displaying Yup's error messages as expected.
Ideally, the errors should display as follow:
Invalid format message: Invalid date format. (mm/dd/yyyy hh:mm am or
pm)
Required field's message: The field cannot be left blank.
Additionally, when there is a validation error or when the field
loses its focus it does not turn red.
So, if the field is empty and I press the submit button, the invalid format message is displayed.
here is the schemas code:
const schema = yup.object().shape({
name: yup
.string()
.required("Please enter your name. The field cannot be left blank."),
date: yup
.date()
.transform(parseDateString)
.typeError("Invalid date format. (mm/dd/yyyy hh:mm am or pm)")
.nullable()
.required("Please enter a valid date. The field cannot be left blank.")
});
I have tried moving nullable() to every different position and the result still the same.
I have commented nullable() and typeError and I get the default error from date (date must be a date type, but the final value was: Invalid Date.)
Here is a working example
The Invalid Date error comes from the date-fns parser function that is in the parseDateString function called in the Yup transform method.
Yup transform method is used to transform incoming date from the input field, in this case it's MUI's DateTimePicker.
That being sad it has nothing to do with this error and the problem is in the DatePicker component. Make note of the TextField and {...params} destructuring. Since the error prop was before we destructure params it was overwritten.
Here is a working example.
const CalPicker = ({ helperText, name, label, control, required, error }) => {
const [value, setValue] = React.useState();
return (
<Stack sx={{ mt: 2 }}>
<LocalizationProvider dateAdapter={DateAdapter}>
<Controller
name={name}
control={control}
render={({ field }) => (
<DateTimePicker
{...field}
renderInput={(params) => (
<TextField
required={required}
{...params}
helperText={helperText}
error={error}
/>
)}
label={label}
value={value}
onChange={(newValue) => {
field.onChange(newValue);
setValue(newValue);
}}
/>
)}
/>
</LocalizationProvider>
</Stack>
);
};
add under LocalizationProvider:
{error ? <div className="error">{error}</div> : null}
Related
I have an edit form I need verified with several datetime inputs.
Here is an example of one of the inputs. Can old() be used this way?
<input
type="text"
name="call_timeRecd"
id="call_timeRecd"
class="form-control
form-control-sm"
value="{{ $data->call_timeRecd ? date('Y-m-d H:i', (new DateTime( old($data->call_timeRecd, $data->call_timeRecd) ))->getTimestamp()) : '' }}" />
I'm trying to have invalid inputs return to the form with an error and the invalid input displayed in the input box. However, it is showing the original input rather than the incorrect version when it returns with the error.
$data is a MySql record and call_timeRecd is a timestamp field.
I'm using DateRangePicker from #mui/lab and now, there is need to add custom toolbar with action buttons above or under calendar (for example, buttons apply or cancel). I struggled to find solution but couldn't find something useful. It should be on both desktop and mobile versions of datepicker.
For all those who suffer from the lack of simple and necessary solutions.
Hope this will help 🫡
Here the docs, but there is huge lack of information and examples
<LocalizationProvider dateAdapter={AdapterDateFns} localeText={{ start: 'from', end: 'to' }}>
<DateRangePicker
components={{ //edit component
PaperContent: data => { //exactly PaperContent
const childCopy = [...data.children]; //duplicate to avoid errors
const Component = () => <Box>BUILD YOUR COMPONENT</Box>;
childCopy.push(<Component />);
return childCopy; //return array of childrens
}
}}
value={value}
onChange={newValue => {
setValue(newValue);
}}
renderInput={(startProps, endProps) => (
<>
<MNVTTextField {...startProps} />
<Box>-</Box>
<MNVTTextField {...endProps} />
</>
)}
/>
</LocalizationProvider>;
I'm trying to use a custom Input component on a Typeahead with the multiple option set. I see in the docs it says to "handle the refs" correctly, but I see no examples of how this is done. I'm not sure what to pass into referenceElementRef. Everything I've tried so far just doesn't render the options as I type. I see them in the DOM, but the opacity of the .rbt-menu is set to 0, so they're basically hidden.
Here's my code so far:
const divRef = React.useRef(null);
return (
<Col>
<div ref={divRef}>
<span className="uppercase">
<FormattedMessage id="d.customer" defaultMessage="Customer" tagName="h4" />
</span>
<AsyncTypeahead
multiple
id="customer-filter-input"
inputProps={{
'aria-label': 'Customer search',
style: { fontSize: '14px' },
}}
key={'customer-input'}
minLength={4}
isLoading={props.isLoadingcustomersSuggestions}
delay={300}
onSearch={(term: string) => handleFilterInputs(term, 'customers')}
size={'lg'}
options={dataSource}
labelKey={'defaultMessage'}
placeholder={intl.formatMessage({
id: 'companyName',
defaultMessage: 'Company name',
})}
onChange={(filterItem: any) => handleAutocompleteUpdate(filterItem, 'customer')}
renderInput={({ inputRef, referenceElementRef, ...inputProps }: any) => (
<Input
{...inputProps}
style={{ position: 'relative' }}
ref={(input: any) => {
inputRef(input);
referenceElementRef(divRef); // What do I put here?
}}
/>
)}
/>
</div>
</Col>
);
And this is what renders in the DOM after I type in the Typeahead and get results:
Any ideas or working examples of Typeahead using multiple and renderInput together?
EDIT:
Here's a codesandbox of what I'm seeing. I also see that the problem is also happening when multiple is NOT set. It seems to be an issue with using renderInput. Is it required that I also use renderMenu?
https://codesandbox.io/s/react-bootstrap-typeahead-async-pagination-example-forked-3kz3z
If you upgrade the typeahead version in your sandbox to the latest version (v5.1.1) and pass the input element to referenceElementRef, it works (note that you need to type some characters into the input for the menu to appear):
// v5.0 or later
renderInput={({ inputRef, referenceElementRef, ...inputProps }) => (
<Input
{...inputProps}
ref={(input) => {
inputRef(input);
referenceElementRef(input);
}}
/>
)}
The menu is rendered in relation to the referenceElementRef node by react-popper. In most common cases, the reference node will be the input itself. The reason there's both an inputRef and a referenceElementRef is for more complex cases (like multi-selection) where the menu needs to be rendered in relation to a container element around the input.
If using v4 of the component, the approach is similar, but the ref to use is simply called ref:
// v4
renderInput={({ inputRef, ref, ...inputProps }) => (
<Input
{...inputProps}
ref={(input) => {
inputRef(input);
ref(input);
}}
/>
)}
I want to use Material-UI Next textfield error props link, the props type is boolean. The previous version of Material-UI props name is errorText and the props type is node link.
Textfield Material-UI previous version using errorText props :
<TextField
name='name'
floatingLabelText='Name'
hintText='Type your name'
value={this.state.fields.name}
onChange={this.onChange}
errorText={this.state.error}
/>
With errorText in Material-UI previous version, the code works good for displaying an error state.
Textfield Material-UI Next using error props:
<TextField
name='name'
label='Name'
placeholder='Type your name'
value={this.state.fields.name}
onChange={this.onChange}
error={true} //only accept true or false value
/>
On Material-UI Next errorText props changed to error with boolean type and only accept true or false value. If i set the error props to true, the textfield displaying error state at any time. I just want to displaying error state under certain conditions.
How can i use error state this.state.error on Material-UI Next textfield?
Using a react component state, one can store the TextField value and use that as an indicator for an error. Material-UI exposes the error and helperText props to display an error interactively.
Take a look at the following example:
<TextField
value={this.state.text}
onChange={event => this.setState({ text: event.target.value })}
error={text === ""}
helperText={text === "" ? 'Empty field!' : ' '}
/>
I add an example that does not shows an error when the value is empty and validates a regular expression (MAC Address).
<TextField id="macAddress" label="MAC Address" name="macAddress"
value={this.state.macAddress}
onChange={this.handleChange}
error={this.state.macAddress !== "" && !this.state.macAddress.match("^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$")}
helperText={this.state.macAddress !== "" && !this.state.macAddress.match("^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$") ? 'MAC Address must be a 6-bytes string.' : ' '}
/>
I am stuck here and would very much appreciate help. I have a form in a razor view with a input field for current city which looks like this:
#Html.LabelFor(x => x.UserModel.CurrentCity)
#Html.TextBoxFor(x => x.UserModel.CurrentCity, new { #data_bind = "value: UserModel.CurrentCity ", #class = "city", #data_val = "true", #data_val_required="City is required" })
#Html.ValidationMessageFor(x => x.UserModel.CurrentCity)
I want autocomplete for this field and am using jquery token input plugin for this like:
$(".city").tokenInput('#Url.Action("AutocompleteCity", "Settings")',{ minChars: 2, tokenLimit: 1, hintText: "Type in a city" });
$(".city").tokenInput("add", {name: viewModel.UserModel.CurrentCity()});
Everything works fine except the clientside unobtrusive validation. The form gets posted even if CurrentCity is empty.
I also tried to change the MVC helpers to plain html:
<input data-val="true" data-val-required="City is required" type="text" class="city" data-bind = "value: UserModel.CurrentCity, attr: { name: 'UserModel.CurrentCity', id: 'UserModel.CurrentCity'}" />
<span class="field-validation-valid" data-valmsg-for="UserModel.CurrentCity" data-valmsg-replace="true"></span>
This approach prevents the form from being submitted but the validation-error class is not injected into the span and the error message does not show up.
Any suggestions?
The original input element you created is hidden. You will likely need to enable validation of hidden elements: jquery.validate v. 1.9 ignores some hidden inputs or https://stackoverflow.com/a/13295938/173225.