fix: merge uiSchema and formContext in Stepper component
This commit ensures that the uiSchema and formContext are merged in the Stepper component form, with the non-props values taking precedence over the props values. The uiSchemas are deep-merged using `lodash.merge` to ensure that nested values are correctly merged. Signed-off-by: Rich Barton-Cooper <rich@syntasso.io>
This commit is contained in:
@@ -549,6 +549,66 @@ describe('Stepper', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should allow overrides to the uiSchema and formContext correctly', async () => {
|
||||
const manifest: TemplateParameterSchema = {
|
||||
title: 'Custom Fields',
|
||||
steps: [
|
||||
{
|
||||
title: 'Test',
|
||||
schema: {
|
||||
properties: {
|
||||
name: {
|
||||
type: 'string',
|
||||
'ui:placeholder': 'Enter your name',
|
||||
},
|
||||
age: {
|
||||
type: 'number',
|
||||
'ui:placeholder': 'Enter your age',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const uiSchema = {
|
||||
name: {
|
||||
'ui:readonly': true,
|
||||
'ui:placeholder': 'Should be overwritten',
|
||||
},
|
||||
};
|
||||
|
||||
const formContext = {
|
||||
readOnlyAsDisabled: true,
|
||||
};
|
||||
|
||||
const { getByRole } = await renderInTestApp(
|
||||
<SecretsContextProvider>
|
||||
<Stepper
|
||||
manifest={manifest}
|
||||
onCreate={jest.fn()}
|
||||
extensions={[]}
|
||||
formProps={{ uiSchema, formContext }}
|
||||
initialState={{ name: 'Some Name', age: 40 }}
|
||||
/>
|
||||
</SecretsContextProvider>,
|
||||
);
|
||||
|
||||
expect(getByRole('textbox', { name: 'name' })).toHaveValue('Some Name');
|
||||
expect(getByRole('textbox', { name: 'name' })).toBeDisabled();
|
||||
expect(getByRole('textbox', { name: 'name' })).toHaveAttribute(
|
||||
'placeholder',
|
||||
'Enter your name',
|
||||
);
|
||||
|
||||
expect(getByRole('spinbutton', { name: 'age' })).toHaveValue(40);
|
||||
expect(getByRole('spinbutton', { name: 'age' })).toBeEnabled();
|
||||
expect(getByRole('spinbutton', { name: 'age' })).toHaveAttribute(
|
||||
'placeholder',
|
||||
'Enter your age',
|
||||
);
|
||||
});
|
||||
|
||||
describe('Scaffolder Layouts', () => {
|
||||
it('should render the step in the scaffolder layout', async () => {
|
||||
const ScaffolderLayout: LayoutTemplate = ({ properties }) => (
|
||||
|
||||
@@ -51,6 +51,7 @@ import { ErrorListTemplate } from './ErrorListTemplate';
|
||||
import { makeStyles } from '@material-ui/core/styles';
|
||||
import { PasswordWidget } from '../PasswordWidget/PasswordWidget';
|
||||
import ajvErrors from 'ajv-errors';
|
||||
import { merge } from 'lodash';
|
||||
|
||||
const validator = customizeValidator();
|
||||
ajvErrors(validator.ajv);
|
||||
@@ -193,6 +194,14 @@ export const Stepper = (stepperProps: StepperProps) => {
|
||||
setFormState(current => ({ ...current, ...formData }));
|
||||
};
|
||||
|
||||
const {
|
||||
formContext: propFormContext,
|
||||
uiSchema: propUiSchema,
|
||||
...restFormProps
|
||||
} = props.formProps ?? {};
|
||||
|
||||
const mergedUiSchema = merge({}, propUiSchema, currentStep?.uiSchema);
|
||||
|
||||
return (
|
||||
<>
|
||||
{isValidating && <LinearProgress variant="indeterminate" />}
|
||||
@@ -229,9 +238,9 @@ export const Stepper = (stepperProps: StepperProps) => {
|
||||
validator={validator}
|
||||
extraErrors={errors as unknown as ErrorSchema}
|
||||
formData={formState}
|
||||
formContext={{ formData: formState }}
|
||||
formContext={{ ...propFormContext, formData: formState }}
|
||||
schema={currentStep.schema}
|
||||
uiSchema={currentStep.uiSchema}
|
||||
uiSchema={mergedUiSchema}
|
||||
onSubmit={handleNext}
|
||||
fields={fields}
|
||||
showErrorList="top"
|
||||
@@ -241,7 +250,7 @@ export const Stepper = (stepperProps: StepperProps) => {
|
||||
experimental_defaultFormStateBehavior={{
|
||||
allOf: 'populateDefaults',
|
||||
}}
|
||||
{...(props.formProps ?? {})}
|
||||
{...restFormProps}
|
||||
>
|
||||
<div className={styles.footer}>
|
||||
<Button
|
||||
|
||||
Reference in New Issue
Block a user