Merge pull request #24622 from richcooper95/feat/expose-extra-form-props

feat: expose uiSchema and formContext in FormProps
This commit is contained in:
Ben Lambert
2024-07-23 08:52:37 +02:00
committed by GitHub
5 changed files with 79 additions and 5 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-scaffolder-react': patch
---
Add ability to customise form fields in the UI by exposing `uiSchema` and `formContext` in `FormProps`
+1 -1
View File
@@ -128,7 +128,7 @@ export interface FieldExtensionUiSchema<TFieldReturnValue, TUiOptions>
// @public
export type FormProps = Pick<
FormProps_2,
'transformErrors' | 'noHtml5Validate'
'transformErrors' | 'noHtml5Validate' | 'uiSchema' | 'formContext'
>;
// @public
@@ -32,7 +32,7 @@ export type TemplateGroupFilter = {
*/
export type FormProps = Pick<
SchemaFormProps,
'transformErrors' | 'noHtml5Validate'
'transformErrors' | 'noHtml5Validate' | 'uiSchema' | 'formContext'
>;
/**
@@ -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