mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2026-09-09 18:03:21 +00:00
AAE-46517 Add onRowCountChange form event for Repeatable Sections (#12062)
* AAE-46517 Add onRowCountChange event for Repeatable Sections * code review fixes for unit test
This commit is contained in:
@@ -16,6 +16,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { DateFnsUtils } from '../../../../common';
|
import { DateFnsUtils } from '../../../../common';
|
||||||
|
import { FormRulesEvent } from '../../../events/form-rules.event';
|
||||||
|
import { firstValueFrom, map, Subject, take, timeout } from 'rxjs';
|
||||||
import { FormFieldTypes } from './form-field-types';
|
import { FormFieldTypes } from './form-field-types';
|
||||||
import { RequiredFieldValidator } from './form-field-validator';
|
import { RequiredFieldValidator } from './form-field-validator';
|
||||||
import { FormFieldModel } from './form-field.model';
|
import { FormFieldModel } from './form-field.model';
|
||||||
@@ -1541,6 +1543,17 @@ describe('FormFieldModel', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('add row', () => {
|
describe('add row', () => {
|
||||||
|
const assignFormRulesEventSubject = (): Subject<FormRulesEvent> => {
|
||||||
|
const formRulesEvent = new Subject<FormRulesEvent>();
|
||||||
|
(field.form as any).formService = {
|
||||||
|
formRulesEvent,
|
||||||
|
validateForm: new Subject(),
|
||||||
|
validateFormField: new Subject(),
|
||||||
|
formFieldValueChanged: new Subject()
|
||||||
|
};
|
||||||
|
return formRulesEvent;
|
||||||
|
};
|
||||||
|
|
||||||
it('should add row if allowed by limit param', () => {
|
it('should add row if allowed by limit param', () => {
|
||||||
expect(field.rows.length).toBe(2);
|
expect(field.rows.length).toBe(2);
|
||||||
|
|
||||||
@@ -1568,18 +1581,56 @@ describe('FormFieldModel', () => {
|
|||||||
expect(field.rows.length).toBe(5);
|
expect(field.rows.length).toBe(5);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should call onRepeatableSectionChanged', () => {
|
it('should call onRepeatableSectionRowCountChanged', () => {
|
||||||
spyOn(field.form, 'onRepeatableSectionChanged').and.callThrough();
|
spyOn(field.form, 'onRepeatableSectionRowCountChanged').and.callThrough();
|
||||||
|
|
||||||
expect(field.form.onRepeatableSectionChanged).not.toHaveBeenCalled();
|
expect(field.form.onRepeatableSectionRowCountChanged).not.toHaveBeenCalled();
|
||||||
|
|
||||||
field.addRow(field.fields, form);
|
field.addRow(field.fields, form);
|
||||||
|
|
||||||
expect(field.form.onRepeatableSectionChanged).toHaveBeenCalled();
|
expect(field.form.onRepeatableSectionRowCountChanged).toHaveBeenCalledWith(field);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should emit onRowCountChanged via formService.formRulesEvent', async () => {
|
||||||
|
const formRulesEvent = assignFormRulesEventSubject();
|
||||||
|
const emissionPromise = firstValueFrom(formRulesEvent);
|
||||||
|
|
||||||
|
field.addRow(field.fields, form);
|
||||||
|
|
||||||
|
const emittedEvent = await emissionPromise;
|
||||||
|
expect(emittedEvent.type).toBe('onRowCountChanged');
|
||||||
|
expect(emittedEvent.field).toBe(field);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should NOT emit onRowCountChanged when add row is not allowed', async () => {
|
||||||
|
const formRulesEvent = assignFormRulesEventSubject();
|
||||||
|
|
||||||
|
field.addRow(field.fields, form);
|
||||||
|
field.addRow(field.fields, form);
|
||||||
|
field.addRow(field.fields, form);
|
||||||
|
expect(field.rows.length).toBe(5);
|
||||||
|
|
||||||
|
const emissionPromise = firstValueFrom(formRulesEvent.pipe(timeout(50)));
|
||||||
|
|
||||||
|
field.addRow(field.fields, form);
|
||||||
|
|
||||||
|
await expectAsync(emissionPromise).toBeRejected();
|
||||||
|
expect(field.rows.length).toBe(5);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('remove row', () => {
|
describe('remove row', () => {
|
||||||
|
const assignFormRulesEventSubject = (): Subject<FormRulesEvent> => {
|
||||||
|
const formRulesEvent = new Subject<FormRulesEvent>();
|
||||||
|
(field.form as any).formService = {
|
||||||
|
formRulesEvent,
|
||||||
|
validateForm: new Subject(),
|
||||||
|
validateFormField: new Subject(),
|
||||||
|
formFieldValueChanged: new Subject()
|
||||||
|
};
|
||||||
|
return formRulesEvent;
|
||||||
|
};
|
||||||
|
|
||||||
it('should remove row if target index exists', () => {
|
it('should remove row if target index exists', () => {
|
||||||
expect(field.rows.length).toBe(2);
|
expect(field.rows.length).toBe(2);
|
||||||
|
|
||||||
@@ -1646,14 +1697,77 @@ describe('FormFieldModel', () => {
|
|||||||
expect(field.form.onFormFieldChanged).not.toHaveBeenCalled();
|
expect(field.form.onFormFieldChanged).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should call onRepeatableSectionChanged', () => {
|
it('should call onRepeatableSectionRowCountChanged', () => {
|
||||||
spyOn(field.form, 'onRepeatableSectionChanged').and.callThrough();
|
spyOn(field.form, 'onRepeatableSectionRowCountChanged').and.callThrough();
|
||||||
|
|
||||||
expect(field.form.onRepeatableSectionChanged).not.toHaveBeenCalled();
|
expect(field.form.onRepeatableSectionRowCountChanged).not.toHaveBeenCalled();
|
||||||
|
|
||||||
field.removeRow(1);
|
field.removeRow(1);
|
||||||
|
|
||||||
expect(field.form.onRepeatableSectionChanged).toHaveBeenCalled();
|
expect(field.form.onRepeatableSectionRowCountChanged).toHaveBeenCalledWith(field);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should emit onRowCountChanged via formService.formRulesEvent', async () => {
|
||||||
|
const formRulesEvent = assignFormRulesEventSubject();
|
||||||
|
const emissionPromise = firstValueFrom(formRulesEvent);
|
||||||
|
|
||||||
|
field.removeRow(1);
|
||||||
|
|
||||||
|
const emittedEvent = await emissionPromise;
|
||||||
|
expect(emittedEvent.type).toBe('onRowCountChanged');
|
||||||
|
expect(emittedEvent.field).toBe(field);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should update form values before emitting onRowCountChanged', async () => {
|
||||||
|
const formRulesEvent = assignFormRulesEventSubject();
|
||||||
|
form.values[field.id] = [
|
||||||
|
{
|
||||||
|
Text0wwp7n: 'mock-1',
|
||||||
|
Integer0rzkwq: 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Text0wwp7n: 'mock-2',
|
||||||
|
Integer0rzkwq: 2
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const valuesLengthAtEmissionPromise = firstValueFrom(
|
||||||
|
formRulesEvent.pipe(
|
||||||
|
take(1),
|
||||||
|
map(() => form.values[field.id].length)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
field.removeRow(1);
|
||||||
|
|
||||||
|
const valuesLengthAtEmission = await valuesLengthAtEmissionPromise;
|
||||||
|
expect(valuesLengthAtEmission).toBe(1);
|
||||||
|
expect(form.values[field.id]).toEqual([
|
||||||
|
{
|
||||||
|
Text0wwp7n: 'mock-1',
|
||||||
|
Integer0rzkwq: 1
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should emit onRowCountChanged even when form values do not contain section id', async () => {
|
||||||
|
const formRulesEvent = assignFormRulesEventSubject();
|
||||||
|
form.values = {};
|
||||||
|
const emissionPromise = firstValueFrom(formRulesEvent);
|
||||||
|
|
||||||
|
field.removeRow(1);
|
||||||
|
|
||||||
|
const emittedEvent = await emissionPromise;
|
||||||
|
expect(emittedEvent.type).toBe('onRowCountChanged');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should NOT emit onRowCountChanged when remove row target index does not exist', async () => {
|
||||||
|
const formRulesEvent = assignFormRulesEventSubject();
|
||||||
|
const emissionPromise = firstValueFrom(formRulesEvent.pipe(timeout(50)));
|
||||||
|
|
||||||
|
field.removeRow(2);
|
||||||
|
|
||||||
|
await expectAsync(emissionPromise).toBeRejected();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -470,7 +470,7 @@ export class FormFieldModel extends FormWidgetModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.rows.push(this.createRow(fields, form, this.rows.length));
|
this.rows.push(this.createRow(fields, form, this.rows.length));
|
||||||
this.form.onRepeatableSectionChanged();
|
this.form.onRepeatableSectionRowCountChanged(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private shouldAddRow(): boolean {
|
private shouldAddRow(): boolean {
|
||||||
@@ -484,14 +484,17 @@ export class FormFieldModel extends FormWidgetModel {
|
|||||||
|
|
||||||
this.rows.splice(index, 1);
|
this.rows.splice(index, 1);
|
||||||
this.updateChildrenFieldsRowIndex();
|
this.updateChildrenFieldsRowIndex();
|
||||||
this.form.onRepeatableSectionChanged();
|
|
||||||
|
|
||||||
if (!this.form.values[this.id]) {
|
const hasSectionValues = !!this.form.values[this.id];
|
||||||
return;
|
if (hasSectionValues) {
|
||||||
|
this.form.values[this.id].splice(index, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.form.values[this.id].splice(index, 1);
|
this.form.onRepeatableSectionRowCountChanged(this);
|
||||||
this.form.onFormFieldChanged(this);
|
|
||||||
|
if (hasSectionValues) {
|
||||||
|
this.form.onFormFieldChanged(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private shouldRemoveRow(index: number): boolean {
|
private shouldRemoveRow(index: number): boolean {
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { FormFieldEvent } from '../../../events/form-field.event';
|
import { FormFieldEvent } from '../../../events/form-field.event';
|
||||||
|
import { FormRulesEvent } from '../../../events/form-rules.event';
|
||||||
import { ValidateFormFieldEvent } from '../../../events/validate-form-field.event';
|
import { ValidateFormFieldEvent } from '../../../events/validate-form-field.event';
|
||||||
import { ValidateFormEvent } from '../../../events/validate-form.event';
|
import { ValidateFormEvent } from '../../../events/validate-form.event';
|
||||||
import { ContainerModel } from './container.model';
|
import { ContainerModel } from './container.model';
|
||||||
@@ -154,6 +155,11 @@ export class FormModel implements ProcessFormModel {
|
|||||||
this.fieldsCache = this.getFormFields([], true);
|
this.fieldsCache = this.getFormFields([], true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onRepeatableSectionRowCountChanged(sectionField: FormFieldModel): void {
|
||||||
|
this.onRepeatableSectionChanged();
|
||||||
|
this.formService?.formRulesEvent?.next(new FormRulesEvent('onRowCountChanged', new FormFieldEvent(this, sectionField)));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validates entire form and all form fields.
|
* Validates entire form and all form fields.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
import { Subject } from 'rxjs';
|
import { Subject } from 'rxjs';
|
||||||
import { FormFieldEvent } from '../events/form-field.event';
|
import { FormFieldEvent } from '../events/form-field.event';
|
||||||
|
import { FormRulesEvent } from '../events/form-rules.event';
|
||||||
import { ValidateFormFieldEvent } from '../events/validate-form-field.event';
|
import { ValidateFormFieldEvent } from '../events/validate-form-field.event';
|
||||||
import { ValidateFormEvent } from '../events/validate-form.event';
|
import { ValidateFormEvent } from '../events/validate-form.event';
|
||||||
|
|
||||||
@@ -24,4 +25,5 @@ export interface FormValidationService {
|
|||||||
formFieldValueChanged: Subject<FormFieldEvent>;
|
formFieldValueChanged: Subject<FormFieldEvent>;
|
||||||
validateForm: Subject<ValidateFormEvent>;
|
validateForm: Subject<ValidateFormEvent>;
|
||||||
validateFormField: Subject<ValidateFormFieldEvent>;
|
validateFormField: Subject<ValidateFormFieldEvent>;
|
||||||
|
formRulesEvent?: Subject<FormRulesEvent>;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user