fixed error messaging a little bit for forms w/ burnettk cullerton
This commit is contained in:
parent
215824d4b9
commit
7eac40be5a
|
@ -1,57 +1,80 @@
|
|||
import React from 'react';
|
||||
// @ts-ignore
|
||||
import { TextInput } from '@carbon/react';
|
||||
import { getInputProps, WidgetProps } from '@rjsf/utils';
|
||||
import {
|
||||
getInputProps,
|
||||
FormContextType,
|
||||
RJSFSchema,
|
||||
StrictRJSFSchema,
|
||||
WidgetProps,
|
||||
} from '@rjsf/utils';
|
||||
|
||||
function BaseInputTemplate({
|
||||
id,
|
||||
placeholder,
|
||||
required,
|
||||
readonly,
|
||||
disabled,
|
||||
type,
|
||||
label,
|
||||
value,
|
||||
onChange,
|
||||
onBlur,
|
||||
onFocus,
|
||||
autofocus,
|
||||
options,
|
||||
schema,
|
||||
uiSchema,
|
||||
rawErrors = [],
|
||||
registry,
|
||||
...textFieldProps
|
||||
}: WidgetProps) {
|
||||
const inputProps = getInputProps(schema, type, options);
|
||||
// Now we need to pull out the step, min, max into an inner `inputProps` for material-ui
|
||||
const { step, min, max, ...rest } = inputProps;
|
||||
const otherProps = {
|
||||
inputProps: {
|
||||
step,
|
||||
min,
|
||||
max,
|
||||
...(schema.examples ? { list: `examples_${id}` } : undefined),
|
||||
},
|
||||
import { useCallback } from 'react';
|
||||
|
||||
/** The `BaseInputTemplate` is the template to use to render the basic `<input>` component for the `core` theme.
|
||||
* It is used as the template for rendering many of the <input> based widgets that differ by `type` and callbacks only.
|
||||
* It can be customized/overridden for other themes or individual implementations as needed.
|
||||
*
|
||||
* @param props - The `WidgetProps` for this template
|
||||
*/
|
||||
export default function BaseInputTemplate<
|
||||
T = any,
|
||||
S extends StrictRJSFSchema = RJSFSchema,
|
||||
F extends FormContextType = any
|
||||
>(props: WidgetProps<T, S, F>) {
|
||||
const {
|
||||
id,
|
||||
value,
|
||||
readonly,
|
||||
disabled,
|
||||
autofocus,
|
||||
label,
|
||||
onBlur,
|
||||
onFocus,
|
||||
onChange,
|
||||
required,
|
||||
options,
|
||||
schema,
|
||||
uiSchema,
|
||||
formContext,
|
||||
registry,
|
||||
rawErrors,
|
||||
type,
|
||||
...rest
|
||||
} = props;
|
||||
|
||||
// Note: since React 15.2.0 we can't forward unknown element attributes, so we
|
||||
// exclude the "options" and "schema" ones here.
|
||||
if (!id) {
|
||||
console.log('No id for', props);
|
||||
throw new Error(`no id for props ${JSON.stringify(props)}`);
|
||||
}
|
||||
const inputProps = {
|
||||
...rest,
|
||||
...getInputProps<T, S, F>(schema, type, options),
|
||||
};
|
||||
const localOnChange = ({
|
||||
// eslint-disable-next-line no-shadow
|
||||
target: { value },
|
||||
}: React.ChangeEvent<HTMLInputElement>) => {
|
||||
onChange(value === '' ? options.emptyValue : value);
|
||||
};
|
||||
const localOnBlur = ({
|
||||
// eslint-disable-next-line no-shadow
|
||||
target: { value },
|
||||
}: React.FocusEvent<HTMLInputElement>) => onBlur(id, value);
|
||||
const localOnFocus = ({
|
||||
// eslint-disable-next-line no-shadow
|
||||
target: { value },
|
||||
}: React.FocusEvent<HTMLInputElement>) => onFocus(id, value);
|
||||
|
||||
const { schemaUtils } = registry;
|
||||
const displayLabel = schemaUtils.getDisplayLabel(schema, uiSchema);
|
||||
let inputValue;
|
||||
if (inputProps.type === 'number' || inputProps.type === 'integer') {
|
||||
inputValue = value || value === 0 ? value : '';
|
||||
} else {
|
||||
inputValue = value == null ? '' : value;
|
||||
}
|
||||
|
||||
const _onChange = useCallback(
|
||||
({ target: { value } }: React.ChangeEvent<HTMLInputElement>) =>
|
||||
onChange(value === '' ? options.emptyValue : value),
|
||||
[onChange, options]
|
||||
);
|
||||
const _onBlur = useCallback(
|
||||
({ target: { value } }: React.FocusEvent<HTMLInputElement>) =>
|
||||
onBlur(id, value),
|
||||
[onBlur, id]
|
||||
);
|
||||
const _onFocus = useCallback(
|
||||
({ target: { value } }: React.FocusEvent<HTMLInputElement>) =>
|
||||
onFocus(id, value),
|
||||
[onFocus, id]
|
||||
);
|
||||
|
||||
let labelToUse = label;
|
||||
if (uiSchema && uiSchema['ui:title']) {
|
||||
|
@ -59,39 +82,33 @@ function BaseInputTemplate({
|
|||
} else if (schema && schema.title) {
|
||||
labelToUse = schema.title;
|
||||
}
|
||||
if (required) {
|
||||
labelToUse = `${labelToUse}*`;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<TextInput
|
||||
id={id}
|
||||
name={id}
|
||||
placeholder={placeholder}
|
||||
labelText={displayLabel ? labelToUse : false}
|
||||
labelText={labelToUse}
|
||||
autoFocus={autofocus}
|
||||
disabled={disabled || readonly}
|
||||
value={value || value === 0 ? value : ''}
|
||||
error={rawErrors.length > 0}
|
||||
onChange={localOnChange}
|
||||
onBlur={localOnBlur}
|
||||
onFocus={localOnFocus}
|
||||
onChange={_onChange}
|
||||
onBlur={_onBlur}
|
||||
onFocus={_onFocus}
|
||||
// eslint-disable-next-line react/jsx-props-no-spreading
|
||||
{...otherProps}
|
||||
{...inputProps}
|
||||
/>
|
||||
{schema.examples && (
|
||||
<datalist id={`examples_${id}`}>
|
||||
{(schema.examples as string[])
|
||||
.concat(schema.default ? ([schema.default] as string[]) : [])
|
||||
.map((example: any) => {
|
||||
// eslint-disable-next-line jsx-a11y/control-has-associated-label
|
||||
return <option key={example} value={example} />;
|
||||
})}
|
||||
{Array.isArray(schema.examples) && (
|
||||
<datalist key={`datalist_${id}`} id={`examples_${id}`}>
|
||||
{[
|
||||
...new Set(
|
||||
schema.examples.concat(schema.default ? [schema.default] : [])
|
||||
),
|
||||
].map((example: any) => (
|
||||
<option key={example} value={example} />
|
||||
))}
|
||||
</datalist>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default BaseInputTemplate;
|
||||
|
|
|
@ -1,34 +1,16 @@
|
|||
import React from 'react';
|
||||
import ErrorIcon from '@mui/icons-material/Error';
|
||||
import Box from '@mui/material/Box';
|
||||
import List from '@mui/material/List';
|
||||
import ListItem from '@mui/material/ListItem';
|
||||
import ListItemIcon from '@mui/material/ListItemIcon';
|
||||
import ListItemText from '@mui/material/ListItemText';
|
||||
import Paper from '@mui/material/Paper';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import { ErrorListProps } from '@rjsf/utils';
|
||||
// @ts-ignore
|
||||
import { Tag } from '@carbon/react';
|
||||
|
||||
function ErrorList({ errors }: ErrorListProps) {
|
||||
return (
|
||||
<Paper elevation={2}>
|
||||
<Box mb={2} p={2}>
|
||||
<Typography variant="h6">Errors</Typography>
|
||||
<List dense>
|
||||
{errors.map((error, i: number) => {
|
||||
return (
|
||||
<ListItem key={i}>
|
||||
<ListItemIcon>
|
||||
<ErrorIcon color="error" />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary={error.stack} />
|
||||
</ListItem>
|
||||
);
|
||||
})}
|
||||
</List>
|
||||
</Box>
|
||||
</Paper>
|
||||
);
|
||||
if (errors) {
|
||||
return (
|
||||
<Tag type="red" size="md" title="Fill Required Fields">
|
||||
Please fill out required fields
|
||||
</Tag>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export default ErrorList;
|
||||
|
|
|
@ -1,29 +1,9 @@
|
|||
import React from 'react';
|
||||
import { FieldErrorProps } from '@rjsf/utils';
|
||||
import ListItem from '@mui/material/ListItem';
|
||||
import FormHelperText from '@mui/material/FormHelperText';
|
||||
import List from '@mui/material/List';
|
||||
|
||||
/** The `FieldErrorTemplate` component renders the errors local to the particular field
|
||||
*
|
||||
* @param props - The `FieldErrorProps` for the errors being rendered
|
||||
*/
|
||||
export default function FieldErrorTemplate(props: FieldErrorProps) {
|
||||
const { errors = [], idSchema } = props;
|
||||
if (errors.length === 0) {
|
||||
return null;
|
||||
}
|
||||
const id = `${idSchema.$id}__error`;
|
||||
|
||||
return (
|
||||
<List dense disablePadding>
|
||||
{errors.map((error, i: number) => {
|
||||
return (
|
||||
<ListItem key={i} disableGutters>
|
||||
<FormHelperText id={id}>{error}</FormHelperText>
|
||||
</ListItem>
|
||||
);
|
||||
})}
|
||||
</List>
|
||||
);
|
||||
export default function FieldErrorTemplate(_props: FieldErrorProps) {
|
||||
return null;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue