mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-05-19 17:14:57 +00:00
[ADF-4441] Save button should be disabled when form fields are invalid (#4817)
* [ADF-4441] Save button should be disabled when form inputs are invalid, Refactored disable custom outcome buttons unit tests * [ADF-4441] add missing space * [ADF-4441] Refactor failing unit tests * [ADF-4441] Added documentation for disableSaveButton property
This commit is contained in:
parent
3e1092d7bf
commit
4ea656e537
@ -78,6 +78,7 @@ The template defined inside `empty-form` will be shown when no form definition i
|
|||||||
| appName | `string` | | App id to fetch corresponding form and values. |
|
| appName | `string` | | App id to fetch corresponding form and values. |
|
||||||
| data | [`TaskVariableCloud`](../../../lib/process-services-cloud/src/lib/form/models/task-variable-cloud.model.ts)`[]` | | Custom form values map to be used with the rendered form. |
|
| data | [`TaskVariableCloud`](../../../lib/process-services-cloud/src/lib/form/models/task-variable-cloud.model.ts)`[]` | | Custom form values map to be used with the rendered form. |
|
||||||
| disableCompleteButton | `boolean` | false | If true then the `Complete` outcome button is shown but it will be disabled. |
|
| disableCompleteButton | `boolean` | false | If true then the `Complete` outcome button is shown but it will be disabled. |
|
||||||
|
| disableSaveButton | `boolean` | false | If true then the `Save` outcome button is shown but it will be disabled. |
|
||||||
| disableStartProcessButton | `boolean` | false | If true then the `Start Process` outcome button is shown but it will be disabled. |
|
| disableStartProcessButton | `boolean` | false | If true then the `Start Process` outcome button is shown but it will be disabled. |
|
||||||
| fieldValidators | [`FormFieldValidator`](../../../lib/core/form/components/widgets/core/form-field-validator.ts)`[]` | \[] | Contains a list of form field validator instances. |
|
| fieldValidators | [`FormFieldValidator`](../../../lib/core/form/components/widgets/core/form-field-validator.ts)`[]` | \[] | Contains a list of form field validator instances. |
|
||||||
| form | [`FormCloud`](../../../lib/process-services-cloud/src/lib/form/models/form-cloud.model.ts) | | Underlying [form model](../../../lib/core/form/components/widgets/core/form.model.ts) instance. |
|
| form | [`FormCloud`](../../../lib/process-services-cloud/src/lib/form/models/form-cloud.model.ts) | | Underlying [form model](../../../lib/core/form/components/widgets/core/form.model.ts) instance. |
|
||||||
|
@ -56,6 +56,7 @@ Any content in the body of `<adf-form>` will be shown when no form definition is
|
|||||||
| ---- | ---- | ------------- | ----------- |
|
| ---- | ---- | ------------- | ----------- |
|
||||||
| data | [`FormValues`](../../../lib/core/form/components/widgets/core/form-values.ts) | | Custom form values map to be used with the rendered form. |
|
| data | [`FormValues`](../../../lib/core/form/components/widgets/core/form-values.ts) | | Custom form values map to be used with the rendered form. |
|
||||||
| disableCompleteButton | `boolean` | false | If true then the `Complete` outcome button is shown but it will be disabled. |
|
| disableCompleteButton | `boolean` | false | If true then the `Complete` outcome button is shown but it will be disabled. |
|
||||||
|
| disableSaveButton | `boolean` | false | If true then the `Save` outcome button is shown but it will be disabled. |
|
||||||
| disableStartProcessButton | `boolean` | false | If true then the `Start Process` outcome button is shown but it will be disabled. |
|
| disableStartProcessButton | `boolean` | false | If true then the `Start Process` outcome button is shown but it will be disabled. |
|
||||||
| fieldValidators | [`FormFieldValidator`](../../../lib/core/form/components/widgets/core/form-field-validator.ts)`[]` | \[] | Contains a list of form field validator instances. |
|
| fieldValidators | [`FormFieldValidator`](../../../lib/core/form/components/widgets/core/form-field-validator.ts)`[]` | \[] | Contains a list of form field validator instances. |
|
||||||
| form | [`FormModel`](../../../lib/core/form/components/widgets/core/form.model.ts) | | Underlying [form model](../../../lib/core/form/components/widgets/core/form.model.ts) instance. |
|
| form | [`FormModel`](../../../lib/core/form/components/widgets/core/form.model.ts) | | Underlying [form model](../../../lib/core/form/components/widgets/core/form.model.ts) instance. |
|
||||||
|
@ -48,6 +48,10 @@ export abstract class FormBaseComponent {
|
|||||||
@Input()
|
@Input()
|
||||||
disableCompleteButton: boolean = false;
|
disableCompleteButton: boolean = false;
|
||||||
|
|
||||||
|
/** If true then the `Save` outcome button is shown but it will be disabled. */
|
||||||
|
@Input()
|
||||||
|
disableSaveButton: boolean = false;
|
||||||
|
|
||||||
/** If true then the `Start Process` outcome button is shown but it will be disabled. */
|
/** If true then the `Start Process` outcome button is shown but it will be disabled. */
|
||||||
@Input()
|
@Input()
|
||||||
disableStartProcessButton: boolean = false;
|
disableStartProcessButton: boolean = false;
|
||||||
@ -116,9 +120,8 @@ export abstract class FormBaseComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (outcome) {
|
if (outcome) {
|
||||||
// Make 'Save' button always available
|
|
||||||
if (outcome.name === FormOutcomeModel.SAVE_ACTION) {
|
if (outcome.name === FormOutcomeModel.SAVE_ACTION) {
|
||||||
return true;
|
return this.disableSaveButton ? false : this.form.isValid;
|
||||||
}
|
}
|
||||||
if (outcome.name === FormOutcomeModel.COMPLETE_ACTION) {
|
if (outcome.name === FormOutcomeModel.COMPLETE_ACTION) {
|
||||||
return this.disableCompleteButton ? false : this.form.isValid;
|
return this.disableCompleteButton ? false : this.form.isValid;
|
||||||
|
@ -689,25 +689,48 @@ describe('FormCloudComponent', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should disable complete outcome button when disableCompleteButton is true', () => {
|
it('should disable complete outcome button when disableCompleteButton is true', () => {
|
||||||
const formModel = new FormCloud();
|
const formModel = new FormCloud(cloudFormMock);
|
||||||
formComponent.form = formModel;
|
formComponent.form = formModel;
|
||||||
formComponent.disableCompleteButton = true;
|
formComponent.disableCompleteButton = true;
|
||||||
|
|
||||||
expect(formModel.isValid).toBeTruthy();
|
expect(formModel.isValid).toBeTruthy();
|
||||||
|
expect(formComponent.form.hasOutcomes()).toBe(true);
|
||||||
const completeOutcome = formComponent.form.outcomes.find((outcome) => outcome.name === FormOutcomeModel.COMPLETE_ACTION);
|
const completeOutcome = formComponent.form.outcomes.find((outcome) => outcome.name === FormOutcomeModel.COMPLETE_ACTION);
|
||||||
|
|
||||||
expect(formComponent.isOutcomeButtonEnabled(completeOutcome)).toBeFalsy();
|
expect(formComponent.isOutcomeButtonEnabled(completeOutcome)).toBeFalsy();
|
||||||
|
|
||||||
|
formComponent.disableCompleteButton = false;
|
||||||
|
expect(formComponent.isOutcomeButtonEnabled(completeOutcome)).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should disable save outcome button when disableSaveButton is true', () => {
|
||||||
|
const formModel = new FormCloud(cloudFormMock);
|
||||||
|
formComponent.form = formModel;
|
||||||
|
formComponent.disableSaveButton = true;
|
||||||
|
|
||||||
|
expect(formModel.isValid).toBeTruthy();
|
||||||
|
expect(formComponent.form.hasOutcomes()).toBe(true);
|
||||||
|
const saveOutcome = formComponent.form.outcomes.find((outcome) => outcome.name === FormOutcomeModel.SAVE_ACTION);
|
||||||
|
|
||||||
|
expect(formComponent.isOutcomeButtonEnabled(saveOutcome)).toBeFalsy();
|
||||||
|
|
||||||
|
formComponent.disableSaveButton = false;
|
||||||
|
expect(formComponent.isOutcomeButtonEnabled(saveOutcome)).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should disable start process outcome button when disableStartProcessButton is true', () => {
|
it('should disable start process outcome button when disableStartProcessButton is true', () => {
|
||||||
const formModel = new FormCloud();
|
const formModel = new FormCloud(cloudFormMock);
|
||||||
formComponent.form = formModel;
|
formComponent.form = formModel;
|
||||||
formComponent.disableStartProcessButton = true;
|
formComponent.disableStartProcessButton = true;
|
||||||
|
|
||||||
expect(formModel.isValid).toBeTruthy();
|
expect(formModel.isValid).toBeTruthy();
|
||||||
|
expect(formComponent.form.hasOutcomes()).toBe(true);
|
||||||
const startProcessOutcome = formComponent.form.outcomes.find((outcome) => outcome.name === FormOutcomeModel.START_PROCESS_ACTION);
|
const startProcessOutcome = formComponent.form.outcomes.find((outcome) => outcome.name === FormOutcomeModel.START_PROCESS_ACTION);
|
||||||
|
|
||||||
expect(formComponent.isOutcomeButtonEnabled(startProcessOutcome)).toBeFalsy();
|
expect(formComponent.isOutcomeButtonEnabled(startProcessOutcome)).toBeFalsy();
|
||||||
|
|
||||||
|
formComponent.disableStartProcessButton = false;
|
||||||
|
expect(formComponent.isOutcomeButtonEnabled(startProcessOutcome)).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should raise [executeOutcome] event for formService', (done) => {
|
it('should raise [executeOutcome] event for formService', (done) => {
|
||||||
|
@ -586,7 +586,7 @@ describe('FormComponent', () => {
|
|||||||
expect(formService.completeTaskForm).not.toHaveBeenCalled();
|
expect(formService.completeTaskForm).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should complete form form and raise corresponding event', () => {
|
it('should complete form and raise corresponding event', () => {
|
||||||
spyOn(formService, 'completeTaskForm').and.callFake(() => {
|
spyOn(formService, 'completeTaskForm').and.callFake(() => {
|
||||||
return new Observable((observer) => {
|
return new Observable((observer) => {
|
||||||
observer.next();
|
observer.next();
|
||||||
@ -709,7 +709,7 @@ describe('FormComponent', () => {
|
|||||||
expect(formComponent.data).toBe(metadata);
|
expect(formComponent.data).toBe(metadata);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should disable outcome buttons for readonly form', () => {
|
it('should disable custom outcome buttons for readonly form', () => {
|
||||||
const formModel = new FormModel();
|
const formModel = new FormModel();
|
||||||
formModel.readOnly = true;
|
formModel.readOnly = true;
|
||||||
formComponent.form = formModel;
|
formComponent.form = formModel;
|
||||||
@ -727,31 +727,6 @@ describe('FormComponent', () => {
|
|||||||
expect(formComponent.isOutcomeButtonEnabled(null)).toBeFalsy();
|
expect(formComponent.isOutcomeButtonEnabled(null)).toBeFalsy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should always enable save outcome for writeable form', () => {
|
|
||||||
const formModel = new FormModel();
|
|
||||||
|
|
||||||
const field = new FormFieldModel(formModel, {
|
|
||||||
type: 'text',
|
|
||||||
value: null,
|
|
||||||
required: true
|
|
||||||
});
|
|
||||||
|
|
||||||
const containerModel = new ContainerModel(field);
|
|
||||||
formModel.fields.push(containerModel);
|
|
||||||
formComponent.form = formModel;
|
|
||||||
formModel.onFormFieldChanged(field);
|
|
||||||
|
|
||||||
expect(formModel.isValid).toBeFalsy();
|
|
||||||
|
|
||||||
const outcome = new FormOutcomeModel(new FormModel(), {
|
|
||||||
id: FormComponent.SAVE_OUTCOME_ID,
|
|
||||||
name: FormOutcomeModel.SAVE_ACTION
|
|
||||||
});
|
|
||||||
|
|
||||||
formComponent.readOnly = true;
|
|
||||||
expect(formComponent.isOutcomeButtonEnabled(outcome)).toBeTruthy();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should disable outcome buttons for invalid form', () => {
|
it('should disable outcome buttons for invalid form', () => {
|
||||||
const formModel = new FormModel();
|
const formModel = new FormModel();
|
||||||
const field = new FormFieldModel(formModel, {
|
const field = new FormFieldModel(formModel, {
|
||||||
@ -780,19 +755,139 @@ describe('FormComponent', () => {
|
|||||||
formComponent.form = formModel;
|
formComponent.form = formModel;
|
||||||
formComponent.disableCompleteButton = true;
|
formComponent.disableCompleteButton = true;
|
||||||
|
|
||||||
|
const field = new FormFieldModel(formModel, {
|
||||||
|
type: 'text',
|
||||||
|
value: 'text',
|
||||||
|
required: true
|
||||||
|
});
|
||||||
|
|
||||||
|
const containerModel = new ContainerModel(field);
|
||||||
|
formModel.fields.push(containerModel);
|
||||||
|
formComponent.form = formModel;
|
||||||
|
formModel.onFormFieldChanged(field);
|
||||||
|
|
||||||
|
expect(formModel.isValid).toBeTruthy();
|
||||||
|
|
||||||
|
const completeOutcome = new FormOutcomeModel(new FormModel(), {
|
||||||
|
id: FormComponent.COMPLETE_OUTCOME_ID,
|
||||||
|
name: FormOutcomeModel.COMPLETE_ACTION
|
||||||
|
});
|
||||||
|
|
||||||
expect(formModel.isValid).toBeTruthy();
|
expect(formModel.isValid).toBeTruthy();
|
||||||
const completeOutcome = formComponent.form.outcomes.find((outcome) => outcome.name === FormOutcomeModel.COMPLETE_ACTION);
|
|
||||||
|
|
||||||
expect(formComponent.isOutcomeButtonEnabled(completeOutcome)).toBeFalsy();
|
expect(formComponent.isOutcomeButtonEnabled(completeOutcome)).toBeFalsy();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should disable save outcome button when form is valid and readOnly', () => {
|
||||||
|
const formModel = new FormModel();
|
||||||
|
|
||||||
|
const field = new FormFieldModel(formModel, {
|
||||||
|
type: 'text',
|
||||||
|
value: 'text',
|
||||||
|
required: true
|
||||||
|
});
|
||||||
|
|
||||||
|
const containerModel = new ContainerModel(field);
|
||||||
|
formModel.fields.push(containerModel);
|
||||||
|
formComponent.form = formModel;
|
||||||
|
formModel.onFormFieldChanged(field);
|
||||||
|
|
||||||
|
expect(formModel.isValid).toBeTruthy();
|
||||||
|
|
||||||
|
const saveOutcome = new FormOutcomeModel(new FormModel(), {
|
||||||
|
id: FormComponent.SAVE_OUTCOME_ID,
|
||||||
|
name: FormOutcomeModel.SAVE_ACTION
|
||||||
|
});
|
||||||
|
|
||||||
|
formComponent.form.readOnly = true;
|
||||||
|
expect(formComponent.isOutcomeButtonEnabled(saveOutcome)).toBeFalsy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should enable save outcome button when form is valid and not readOnly', () => {
|
||||||
|
const formModel = new FormModel();
|
||||||
|
|
||||||
|
const field = new FormFieldModel(formModel, {
|
||||||
|
type: 'text',
|
||||||
|
value: 'text',
|
||||||
|
required: true
|
||||||
|
});
|
||||||
|
|
||||||
|
const containerModel = new ContainerModel(field);
|
||||||
|
formModel.fields.push(containerModel);
|
||||||
|
formComponent.form = formModel;
|
||||||
|
formModel.onFormFieldChanged(field);
|
||||||
|
|
||||||
|
expect(formModel.isValid).toBeTruthy();
|
||||||
|
|
||||||
|
const saveOutcome = new FormOutcomeModel(new FormModel(), {
|
||||||
|
id: FormComponent.SAVE_OUTCOME_ID,
|
||||||
|
name: FormOutcomeModel.SAVE_ACTION
|
||||||
|
});
|
||||||
|
|
||||||
|
formComponent.form.readOnly = false;
|
||||||
|
expect(formComponent.isOutcomeButtonEnabled(saveOutcome)).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should disable save outcome button when disableSaveButton is true', () => {
|
||||||
|
const formModel = new FormModel();
|
||||||
|
formComponent.form = formModel;
|
||||||
|
formComponent.disableSaveButton = true;
|
||||||
|
|
||||||
|
const saveOutcome = new FormOutcomeModel(new FormModel(), {
|
||||||
|
id: FormComponent.SAVE_OUTCOME_ID,
|
||||||
|
name: FormOutcomeModel.SAVE_ACTION
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(formComponent.isOutcomeButtonEnabled(saveOutcome)).toBeFalsy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should disable save outcome button when the form is invalid', () => {
|
||||||
|
const formModel = new FormModel();
|
||||||
|
formComponent.form = formModel;
|
||||||
|
|
||||||
|
const field = new FormFieldModel(formModel, {
|
||||||
|
type: 'text',
|
||||||
|
value: null,
|
||||||
|
required: true
|
||||||
|
});
|
||||||
|
|
||||||
|
const containerModel = new ContainerModel(field);
|
||||||
|
formModel.fields.push(containerModel);
|
||||||
|
formComponent.form = formModel;
|
||||||
|
formModel.onFormFieldChanged(field);
|
||||||
|
|
||||||
|
expect(formModel.isValid).toBeFalsy();
|
||||||
|
|
||||||
|
const saveOutcome = new FormOutcomeModel(new FormModel(), {
|
||||||
|
id: FormComponent.SAVE_OUTCOME_ID,
|
||||||
|
name: FormOutcomeModel.SAVE_ACTION
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(formComponent.isOutcomeButtonEnabled(saveOutcome)).toBeFalsy();
|
||||||
|
});
|
||||||
|
|
||||||
it('should disable start process outcome button when disableStartProcessButton is true', () => {
|
it('should disable start process outcome button when disableStartProcessButton is true', () => {
|
||||||
const formModel = new FormModel();
|
const formModel = new FormModel();
|
||||||
formComponent.form = formModel;
|
formComponent.form = formModel;
|
||||||
formComponent.disableStartProcessButton = true;
|
formComponent.disableStartProcessButton = true;
|
||||||
|
|
||||||
|
const field = new FormFieldModel(formModel, {
|
||||||
|
type: 'text',
|
||||||
|
value: 'text',
|
||||||
|
required: true
|
||||||
|
});
|
||||||
|
|
||||||
|
const containerModel = new ContainerModel(field);
|
||||||
|
formModel.fields.push(containerModel);
|
||||||
|
formComponent.form = formModel;
|
||||||
|
formModel.onFormFieldChanged(field);
|
||||||
|
|
||||||
expect(formModel.isValid).toBeTruthy();
|
expect(formModel.isValid).toBeTruthy();
|
||||||
const startProcessOutcome = formComponent.form.outcomes.find((outcome) => outcome.name === FormOutcomeModel.START_PROCESS_ACTION);
|
|
||||||
|
const startProcessOutcome = new FormOutcomeModel(new FormModel(), {
|
||||||
|
id: FormComponent.START_PROCESS_OUTCOME_ID,
|
||||||
|
name: FormOutcomeModel.START_PROCESS_ACTION
|
||||||
|
});
|
||||||
|
|
||||||
expect(formComponent.isOutcomeButtonEnabled(startProcessOutcome)).toBeFalsy();
|
expect(formComponent.isOutcomeButtonEnabled(startProcessOutcome)).toBeFalsy();
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user