feature/fix-required-radio-buttons (#525)
* ignore validations for radio booleans from the custom form w/ burnettk * use carbon for radio buttons * added comment about error message without label --------- Co-authored-by: jasquat <jasquat@users.noreply.github.com>
This commit is contained in:
parent
34a0323c4d
commit
acc918b664
|
@ -152,8 +152,18 @@ export default function CustomForm({
|
||||||
formDataToCheck: any,
|
formDataToCheck: any,
|
||||||
propertyKey: string,
|
propertyKey: string,
|
||||||
errors: any,
|
errors: any,
|
||||||
jsonSchema: any
|
jsonSchema: any,
|
||||||
|
uiSchemaPassedIn?: any
|
||||||
) => {
|
) => {
|
||||||
|
// this validation only applies to checkboxes,
|
||||||
|
// other forms of booleans are validated differently
|
||||||
|
if (
|
||||||
|
uiSchemaPassedIn &&
|
||||||
|
'ui:widget' in uiSchemaPassedIn &&
|
||||||
|
uiSchemaPassedIn['ui:widget'] !== 'checkbox'
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (
|
if (
|
||||||
jsonSchema.required &&
|
jsonSchema.required &&
|
||||||
jsonSchema.required.includes(propertyKey) &&
|
jsonSchema.required.includes(propertyKey) &&
|
||||||
|
@ -169,7 +179,8 @@ export default function CustomForm({
|
||||||
const checkFieldsWithCustomValidations = (
|
const checkFieldsWithCustomValidations = (
|
||||||
jsonSchema: any,
|
jsonSchema: any,
|
||||||
formDataToCheck: any,
|
formDataToCheck: any,
|
||||||
errors: any
|
errors: any,
|
||||||
|
uiSchemaPassedIn?: any
|
||||||
// eslint-disable-next-line sonarjs/cognitive-complexity
|
// eslint-disable-next-line sonarjs/cognitive-complexity
|
||||||
) => {
|
) => {
|
||||||
// if the jsonSchema has an items attribute then assume the element itself
|
// if the jsonSchema has an items attribute then assume the element itself
|
||||||
|
@ -177,9 +188,21 @@ export default function CustomForm({
|
||||||
const jsonSchemaToUse =
|
const jsonSchemaToUse =
|
||||||
'items' in jsonSchema ? jsonSchema.items : jsonSchema;
|
'items' in jsonSchema ? jsonSchema.items : jsonSchema;
|
||||||
|
|
||||||
|
let uiSchemaToUse = uiSchemaPassedIn;
|
||||||
|
if (!uiSchemaToUse) {
|
||||||
|
uiSchemaToUse = uiSchema;
|
||||||
|
}
|
||||||
|
if ('items' in uiSchemaToUse) {
|
||||||
|
uiSchemaToUse = uiSchemaToUse.items;
|
||||||
|
}
|
||||||
|
|
||||||
if ('properties' in jsonSchemaToUse) {
|
if ('properties' in jsonSchemaToUse) {
|
||||||
Object.keys(jsonSchemaToUse.properties).forEach((propertyKey: string) => {
|
Object.keys(jsonSchemaToUse.properties).forEach((propertyKey: string) => {
|
||||||
const propertyMetadata = jsonSchemaToUse.properties[propertyKey];
|
const propertyMetadata = jsonSchemaToUse.properties[propertyKey];
|
||||||
|
let currentUiSchema: any = null;
|
||||||
|
if (propertyKey in uiSchemaToUse) {
|
||||||
|
currentUiSchema = uiSchemaToUse[propertyKey];
|
||||||
|
}
|
||||||
if ('minimumDate' in propertyMetadata) {
|
if ('minimumDate' in propertyMetadata) {
|
||||||
checkMinimumDate(
|
checkMinimumDate(
|
||||||
formDataToCheck,
|
formDataToCheck,
|
||||||
|
@ -195,7 +218,8 @@ export default function CustomForm({
|
||||||
formDataToCheck,
|
formDataToCheck,
|
||||||
propertyKey,
|
propertyKey,
|
||||||
errors,
|
errors,
|
||||||
jsonSchemaToUse
|
jsonSchemaToUse,
|
||||||
|
currentUiSchema
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,7 +237,8 @@ export default function CustomForm({
|
||||||
checkFieldsWithCustomValidations(
|
checkFieldsWithCustomValidations(
|
||||||
propertyMetadata,
|
propertyMetadata,
|
||||||
item,
|
item,
|
||||||
errorsToSend
|
errorsToSend,
|
||||||
|
currentUiSchema
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,7 +57,7 @@ function CheckboxWidget(props: WidgetProps) {
|
||||||
title={commonAttributes.tooltipText}
|
title={commonAttributes.tooltipText}
|
||||||
autoFocus={autofocus}
|
autoFocus={autofocus}
|
||||||
invalid={commonAttributes.invalid}
|
invalid={commonAttributes.invalid}
|
||||||
invalidText={commonAttributes.errorMessageForField}
|
invalidText={commonAttributes.errorMessageForFieldWithoutLabel}
|
||||||
helperText={commonAttributes.helperText}
|
helperText={commonAttributes.helperText}
|
||||||
labelText={
|
labelText={
|
||||||
required
|
required
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
import React from "react";
|
import React from 'react';
|
||||||
import FormControlLabel from "@mui/material/FormControlLabel";
|
import { RadioButtonGroup, RadioButton } from '@carbon/react';
|
||||||
import FormLabel from "@mui/material/FormLabel";
|
import { WidgetProps } from '@rjsf/utils';
|
||||||
import Radio from "@mui/material/Radio";
|
import { getCommonAttributes } from '../../helpers';
|
||||||
import RadioGroup from "@mui/material/RadioGroup";
|
|
||||||
import { WidgetProps } from "@rjsf/utils";
|
|
||||||
|
|
||||||
const RadioWidget = ({
|
function RadioWidget({
|
||||||
id,
|
id,
|
||||||
schema,
|
schema,
|
||||||
options,
|
options,
|
||||||
|
@ -17,11 +15,19 @@ const RadioWidget = ({
|
||||||
onChange,
|
onChange,
|
||||||
onBlur,
|
onBlur,
|
||||||
onFocus,
|
onFocus,
|
||||||
}: WidgetProps) => {
|
uiSchema,
|
||||||
|
rawErrors,
|
||||||
|
}: WidgetProps) {
|
||||||
const { enumOptions, enumDisabled } = options;
|
const { enumOptions, enumDisabled } = options;
|
||||||
|
|
||||||
const _onChange = (_: any, value: any) =>
|
const _onChange = (newValue: any, _radioButtonId: any) => {
|
||||||
onChange(schema.type == "boolean" ? value !== "false" : value);
|
if (schema.type === 'boolean') {
|
||||||
|
const v: any = newValue === 'true' || newValue === true;
|
||||||
|
onChange(v);
|
||||||
|
} else {
|
||||||
|
onChange(newValue);
|
||||||
|
}
|
||||||
|
};
|
||||||
const _onBlur = ({ target: { value } }: React.FocusEvent<HTMLInputElement>) =>
|
const _onBlur = ({ target: { value } }: React.FocusEvent<HTMLInputElement>) =>
|
||||||
onBlur(id, value);
|
onBlur(id, value);
|
||||||
const _onFocus = ({
|
const _onFocus = ({
|
||||||
|
@ -30,43 +36,39 @@ const RadioWidget = ({
|
||||||
|
|
||||||
const row = options ? options.inline : false;
|
const row = options ? options.inline : false;
|
||||||
|
|
||||||
return (
|
const commonAttributes = getCommonAttributes(
|
||||||
<>
|
label,
|
||||||
<RadioGroup
|
schema,
|
||||||
id={id}
|
uiSchema,
|
||||||
name={id}
|
rawErrors
|
||||||
value={`${value}`}
|
|
||||||
row={row as boolean}
|
|
||||||
onChange={_onChange}
|
|
||||||
onBlur={_onBlur}
|
|
||||||
onFocus={_onFocus}
|
|
||||||
>
|
|
||||||
{Array.isArray(enumOptions) &&
|
|
||||||
enumOptions.map((option) => {
|
|
||||||
const itemDisabled =
|
|
||||||
Array.isArray(enumDisabled) &&
|
|
||||||
enumDisabled.indexOf(option.value) !== -1;
|
|
||||||
const radio = (
|
|
||||||
<FormControlLabel
|
|
||||||
control={
|
|
||||||
<Radio
|
|
||||||
name={id}
|
|
||||||
id={`${id}-${option.value}`}
|
|
||||||
color="primary"
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
label={`${option.label}`}
|
|
||||||
value={`${option.value}`}
|
|
||||||
key={option.value}
|
|
||||||
disabled={disabled || itemDisabled || readonly}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
|
|
||||||
return radio;
|
|
||||||
})}
|
|
||||||
</RadioGroup>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
};
|
|
||||||
|
// pass values in as strings so we can support both boolean and string radio buttons
|
||||||
|
return (
|
||||||
|
<RadioButtonGroup
|
||||||
|
id={id}
|
||||||
|
name={id}
|
||||||
|
legendText={commonAttributes.helperText}
|
||||||
|
valueSelected={`${value}`}
|
||||||
|
invalid={commonAttributes.invalid}
|
||||||
|
invalidText={commonAttributes.errorMessageForFieldWithoutLabel}
|
||||||
|
disabled={disabled || readonly}
|
||||||
|
onChange={_onChange}
|
||||||
|
onBlur={_onBlur}
|
||||||
|
onFocus={_onFocus}
|
||||||
|
>
|
||||||
|
{Array.isArray(enumOptions) &&
|
||||||
|
enumOptions.map((option) => {
|
||||||
|
return (
|
||||||
|
<RadioButton
|
||||||
|
id={`${id}-${option.value}`}
|
||||||
|
labelText={option.label}
|
||||||
|
value={`${option.value}`}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</RadioButtonGroup>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export default RadioWidget;
|
export default RadioWidget;
|
||||||
|
|
|
@ -25,12 +25,17 @@ export const getCommonAttributes = (
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// some rjsf validations add in labels by default so avoid showing it twice
|
||||||
|
let errorMessageForFieldWithoutLabel = null;
|
||||||
|
|
||||||
let invalid = false;
|
let invalid = false;
|
||||||
let errorMessageForField = null;
|
let errorMessageForField = null;
|
||||||
if (rawErrors && rawErrors.length > 0) {
|
if (rawErrors && rawErrors.length > 0) {
|
||||||
invalid = true;
|
invalid = true;
|
||||||
|
[errorMessageForFieldWithoutLabel] = rawErrors;
|
||||||
if ('validationErrorMessage' in schema) {
|
if ('validationErrorMessage' in schema) {
|
||||||
errorMessageForField = (schema as any).validationErrorMessage;
|
errorMessageForField = (schema as any).validationErrorMessage;
|
||||||
|
errorMessageForFieldWithoutLabel = errorMessageForField;
|
||||||
} else {
|
} else {
|
||||||
errorMessageForField = `${labelToUse.replace(/\*$/, '')} ${rawErrors[0]}`;
|
errorMessageForField = `${labelToUse.replace(/\*$/, '')} ${rawErrors[0]}`;
|
||||||
}
|
}
|
||||||
|
@ -41,6 +46,7 @@ export const getCommonAttributes = (
|
||||||
label: labelToUse,
|
label: labelToUse,
|
||||||
invalid,
|
invalid,
|
||||||
errorMessageForField,
|
errorMessageForField,
|
||||||
|
errorMessageForFieldWithoutLabel,
|
||||||
labelWithRequiredIndicator,
|
labelWithRequiredIndicator,
|
||||||
tooltipText,
|
tooltipText,
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue