Fixed form error handler

This commit is contained in:
Giuseppe Digilio
2018-07-10 15:25:36 +02:00
parent 1f02a4cb5b
commit 9b249f00df
7 changed files with 59 additions and 33 deletions

View File

@@ -85,7 +85,7 @@ export const FORM_GROUP_TEST_GROUP = new FormGroup({
dc_contributor_author: new FormControl(),
});
describe('DsDynamicGroupComponent test suite', () => {
fdescribe('DsDynamicGroupComponent test suite', () => {
const config = {
form: {
validatorMap: {
@@ -188,8 +188,8 @@ describe('DsDynamicGroupComponent test suite', () => {
});
it('should init component properly', inject([FormBuilderService], (service: FormBuilderService) => {
const config = {rows: groupComp.model.formConfiguration} as SubmissionFormsModel;
const formModel = service.modelFromConfiguration(config, groupComp.model.scopeUUID, {}, groupComp.model.submissionScope, groupComp.model.readOnly);
const formConfig = {rows: groupComp.model.formConfiguration} as SubmissionFormsModel;
const formModel = service.modelFromConfiguration(formConfig, groupComp.model.scopeUUID, {}, groupComp.model.submissionScope, groupComp.model.readOnly);
const chips = new Chips([], 'value', 'dc.contributor.author');
expect(groupComp.formCollapsed).toEqual(Observable.of(false));
@@ -258,8 +258,8 @@ describe('DsDynamicGroupComponent test suite', () => {
});
it('should init component properly', inject([FormBuilderService], (service: FormBuilderService) => {
const config = {rows: groupComp.model.formConfiguration} as SubmissionFormsModel;
const formModel = service.modelFromConfiguration(config, groupComp.model.scopeUUID, {}, groupComp.model.submissionScope, groupComp.model.readOnly);
const formConfig = {rows: groupComp.model.formConfiguration} as SubmissionFormsModel;
const formModel = service.modelFromConfiguration(formConfig, groupComp.model.scopeUUID, {}, groupComp.model.submissionScope, groupComp.model.readOnly);
const chips = new Chips(modelValue, 'value', 'dc.contributor.author');
expect(groupComp.formCollapsed).toEqual(Observable.of(true));

View File

@@ -43,6 +43,19 @@ export class DynamicGroupModel extends DsDynamicInputModel {
}
get value() {
return this._value
}
set value(value) {
this._value = (isEmpty(value)) ? null : value;
}
isEmpty() {
const value = this.getGroupValue();
return (value.length === 1 && isNull(value[0][this.mandatoryField]));
}
getGroupValue(): any[] {
if (isEmpty(this._value)) {
// If items is empty, last element has been removed
// so emit an empty value that allows to dispatch
@@ -57,12 +70,4 @@ export class DynamicGroupModel extends DsDynamicInputModel {
}
return this._value
}
set value(value) {
this._value = value;
}
isEmpty() {
return (this.value.length === 1 && isNull(this.value[0][this.mandatoryField]));
}
}

View File

@@ -18,7 +18,10 @@ import { isObject, isString, mergeWith } from 'lodash';
import { hasValue, isEmpty, isNotEmpty, isNotNull, isNotUndefined, isNull } from '../../empty.util';
import { DynamicQualdropModel } from './ds-dynamic-form-ui/models/ds-dynamic-qualdrop.model';
import { SubmissionFormsModel } from '../../../core/shared/config/config-submission-forms.model';
import { DYNAMIC_FORM_CONTROL_TYPE_RELATION_GROUP } from './ds-dynamic-form-ui/models/dynamic-group/dynamic-group.model';
import {
DYNAMIC_FORM_CONTROL_TYPE_RELATION_GROUP,
DynamicGroupModel
} from './ds-dynamic-form-ui/models/dynamic-group/dynamic-group.model';
import { DYNAMIC_FORM_CONTROL_TYPE_TAG } from './ds-dynamic-form-ui/models/tag/dynamic-tag.model';
import { RowParser } from './parsers/row-parser';
@@ -150,7 +153,7 @@ export class FormBuilderService extends DynamicFormService {
}
if (this.isRelationGroup(controlModel)) {
const values = (controlModel as any).value;
const values = (controlModel as DynamicGroupModel).getGroupValue();
values.forEach((groupValue, groupIndex) => {
const newGroupValue = Object.create({});
Object.keys(groupValue)

View File

@@ -106,11 +106,12 @@ export class FormAddError implements Action {
payload: {
formId: string,
fieldId: string,
fieldIndex: number,
errorMessage: string,
};
constructor(formId: string, fieldId: string, errorMessage: string) {
this.payload = {formId, fieldId, errorMessage};
constructor(formId: string, fieldId: string, fieldIndex: number, errorMessage: string) {
this.payload = {formId, fieldId, fieldIndex, errorMessage};
}
}
@@ -118,11 +119,12 @@ export class FormRemoveErrorAction implements Action {
type = FormActionTypes.FORM_REMOVE_ERROR;
payload: {
formId: string,
fieldId: string
fieldId: string,
fieldIndex: number,
};
constructor(formId: string, fieldId: string) {
this.payload = {formId, fieldId};
constructor(formId: string, fieldId: string, fieldIndex: number,) {
this.payload = {formId, fieldId, fieldIndex};
}
}

View File

@@ -162,14 +162,15 @@ export class FormComponent implements OnDestroy, OnInit {
const {formGroup, formModel} = this;
errors
.filter((error: FormError) => findIndex(this.formErrors, {fieldId: error.fieldId}) === -1)
.filter((error: FormError) => findIndex(this.formErrors, {fieldId: error.fieldId, fieldIndex: error.fieldIndex}) === -1)
.forEach((error: FormError) => {
const {fieldId} = error;
const {fieldIndex} = error;
let field: AbstractControl;
if (!!this.parentFormModel) {
field = this.formBuilderService.getFormControlById(fieldId, formGroup.parent as FormGroup, formModel);
field = this.formBuilderService.getFormControlById(fieldId, formGroup.parent as FormGroup, formModel, fieldIndex);
} else {
field = this.formBuilderService.getFormControlById(fieldId, formGroup, formModel);
field = this.formBuilderService.getFormControlById(fieldId, formGroup, formModel, fieldIndex);
}
if (field) {
@@ -181,14 +182,15 @@ export class FormComponent implements OnDestroy, OnInit {
});
this.formErrors
.filter((error: FormError) => findIndex(errors, {fieldId: error.fieldId}) === -1)
.filter((error: FormError) => findIndex(errors, {fieldId: error.fieldId, fieldIndex: error.fieldIndex}) === -1)
.forEach((error: FormError) => {
const {fieldId} = error;
const {fieldIndex} = error;
let field: AbstractControl;
if (!!this.parentFormModel) {
field = this.formBuilderService.getFormControlById(fieldId, formGroup.parent as FormGroup, formModel);
field = this.formBuilderService.getFormControlById(fieldId, formGroup.parent as FormGroup, formModel, fieldIndex);
} else {
field = this.formBuilderService.getFormControlById(fieldId, formGroup, formModel);
field = this.formBuilderService.getFormControlById(fieldId, formGroup, formModel, fieldIndex);
}
if (field) {
@@ -251,8 +253,9 @@ export class FormComponent implements OnDestroy, OnInit {
}
const control: FormControl = event.control;
const fieldIndex: number = (event.context && event.context.index) ? event.context.index : 0;
if (control.valid) {
this.store.dispatch(new FormRemoveErrorAction(this.formId, event.model.id));
this.store.dispatch(new FormRemoveErrorAction(this.formId, event.model.id, fieldIndex));
}
}

View File

@@ -1,9 +1,11 @@
import { FormEntry, formReducer } from './form.reducer';
import { formReducer } from './form.reducer';
import {
FormAddError,
FormChangeAction, FormClearErrorsAction,
FormChangeAction,
FormClearErrorsAction,
FormInitAction,
FormRemoveAction, FormRemoveErrorAction,
FormRemoveAction,
FormRemoveErrorAction,
FormStatusChangeAction
} from './form.actions';
@@ -165,15 +167,17 @@ describe('formReducer', () => {
const expectedErrors = [
{
fieldId: 'title',
fieldIndex: 0,
message: 'Not valid'
}
];
const formId = 'testForm';
const fieldId = 'title';
const fieldIndex = 0;
const message = 'Not valid';
const action = new FormAddError(formId, fieldId, message);
const action = new FormAddError(formId, fieldId, fieldIndex, message);
const newState = formReducer(initState, action);
expect(newState.testForm.errors).toEqual(expectedErrors);
@@ -192,10 +196,12 @@ describe('formReducer', () => {
errors: [
{
fieldId: 'author',
fieldIndex: 0,
message: 'error.validation.required'
},
{
fieldId: 'title',
fieldIndex: 0,
message: 'error.validation.required'
}
]
@@ -205,13 +211,16 @@ describe('formReducer', () => {
const expectedErrors = [
{
fieldId: 'title',
fieldIndex: 0,
message: 'error.validation.required'
}
];
const formId = 'testForm';
const fieldId = 'author';
const fieldIndex = 0;
const action = new FormRemoveErrorAction(formId, 'author');
const action = new FormRemoveErrorAction(formId, fieldId, fieldIndex);
const newState = formReducer(initState, action);
expect(newState.testForm.errors).toEqual(expectedErrors);
@@ -252,6 +261,7 @@ describe('formReducer', () => {
errors: [
{
fieldId: 'author',
fieldIndex: 0,
message: 'error.validation.required'
}
]

View File

@@ -14,6 +14,7 @@ import { isEqual, uniqWith } from 'lodash';
export interface FormError {
message: string;
fieldId: string;
fieldIndex: number;
}
export interface FormEntry {
@@ -70,6 +71,7 @@ function addFormErrors(state: FormState, action: FormAddError) {
if (hasValue(state[formId])) {
const error: FormError = {
fieldId: action.payload.fieldId,
fieldIndex: action.payload.fieldIndex,
message: action.payload.errorMessage
};
@@ -88,8 +90,9 @@ function addFormErrors(state: FormState, action: FormAddError) {
function removeFormError(state: FormState, action: FormRemoveErrorAction) {
const formId = action.payload.formId;
const fieldId = action.payload.fieldId;
const fieldIndex = action.payload.fieldIndex;
if (hasValue(state[formId])) {
const errors = state[formId].errors.filter((error) => error.fieldId !== fieldId);
const errors = state[formId].errors.filter((error) => error.fieldId !== fieldId || error.fieldIndex !== fieldIndex);
const newState = Object.assign({}, state);
newState[formId] = Object.assign({}, state[formId], {errors});
return newState;