import { FormControl, UntypedFormArray, UntypedFormBuilder, UntypedFormGroup, Validators } from "@angular/forms"; import { DescriptionStatus } from "@app/core/common/enum/description-status"; import { IsActive } from "@app/core/common/enum/is-active.enum"; import { DescriptionTemplate, DescriptionTemplateField, DescriptionTemplateFieldSet, DescriptionTemplateSection } from "@app/core/model/description-template/description-template"; import { Description, DescriptionExternalIdentifier, DescriptionExternalIdentifierPersist, DescriptionField, DescriptionFieldPersist, DescriptionPersist, DescriptionPropertyDefinition, DescriptionPropertyDefinitionFieldSet, DescriptionPropertyDefinitionFieldSetItem, DescriptionPropertyDefinitionFieldSetItemPersist, DescriptionPropertyDefinitionFieldSetPersist, DescriptionPropertyDefinitionPersist, DescriptionReference, DescriptionReferencePersist } from "@app/core/model/description/description"; import { ReferencePersist } from "@app/core/model/reference/reference"; import { BaseEditorModel } from "@common/base/base-form-editor-model"; import { BackendErrorValidator } from '@common/forms/validation/custom-validator'; import { ValidationErrorModel } from '@common/forms/validation/error-model/validation-error-model'; import { Validation, ValidationContext } from '@common/forms/validation/validation-context'; import { Guid } from "@common/types/guid"; export class DescriptionEditorModel extends BaseEditorModel implements DescriptionPersist { label: string; dmpId: Guid; dmpDescriptionTemplateId: Guid; descriptionTemplateId: Guid; status: DescriptionStatus; description: string; properties: DescriptionPropertyDefinitionEditorModel = new DescriptionPropertyDefinitionEditorModel(this.validationErrorModel); tags: string[] = []; references: DescriptionReferenceEditorModel[]; permissions: string[]; public validationErrorModel: ValidationErrorModel = new ValidationErrorModel(); protected formBuilder: UntypedFormBuilder = new UntypedFormBuilder(); constructor() { super(); } public fromModel(item: Description, descriptionTemplate?: DescriptionTemplate): DescriptionEditorModel { if (item) { super.fromModel(item); this.label = item.label; this.dmpId = item.dmp?.id; this.dmpDescriptionTemplateId = item.dmpDescriptionTemplate?.id; this.descriptionTemplateId = item.descriptionTemplate?.id; this.status = item.status ?? DescriptionStatus.Draft; this.description = item.description; this.tags = item.descriptionTags?.map(x => x.tag?.label); this.properties = new DescriptionPropertyDefinitionEditorModel(this.validationErrorModel).fromModel(item.properties, descriptionTemplate, item.descriptionReferences); //if (item.references) { item.references.map(x => this.references.push(new DescriptionReferenceEditorModel().fromModel(x))); } } return this; } buildForm(context: ValidationContext = null, disabled: boolean = false): UntypedFormGroup { if (context == null) { context = this.createValidationContext(); } return this.formBuilder.group({ id: [{ value: this.id, disabled: disabled }, context.getValidation('id').validators], label: [{ value: this.label, disabled: disabled }, context.getValidation('label').validators], dmpId: [{ value: this.dmpId, disabled: disabled }, context.getValidation('dmpId').validators], dmpDescriptionTemplateId: [{ value: this.dmpDescriptionTemplateId, disabled: disabled }, context.getValidation('dmpDescriptionTemplateId').validators], descriptionTemplateId: [{ value: this.descriptionTemplateId, disabled: disabled }, context.getValidation('descriptionTemplateId').validators], status: [{ value: this.status, disabled: disabled }, context.getValidation('status').validators], description: [{ value: this.description, disabled: disabled }, context.getValidation('description').validators], tags: [{ value: this.tags, disabled: disabled }, context.getValidation('tags').validators], properties: this.buildProperties(), hash: [{ value: this.hash, disabled: disabled }, context.getValidation('hash').validators] }); } buildProperties() { return this.properties.buildForm({ rootPath: `properties.` }); } createValidationContext(): ValidationContext { const baseContext: ValidationContext = new ValidationContext(); const baseValidationArray: Validation[] = new Array(); baseValidationArray.push({ key: 'id', validators: [BackendErrorValidator(this.validationErrorModel, 'id')] }); baseValidationArray.push({ key: 'label', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'label')] }); baseValidationArray.push({ key: 'dmpId', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'dmpId')] }); baseValidationArray.push({ key: 'dmpDescriptionTemplateId', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'dmpDescriptionTemplateId')] }); baseValidationArray.push({ key: 'descriptionTemplateId', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'descriptionTemplateId')] }); baseValidationArray.push({ key: 'status', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'status')] }); baseValidationArray.push({ key: 'description', validators: [BackendErrorValidator(this.validationErrorModel, 'description')] }); baseValidationArray.push({ key: 'tags', validators: [BackendErrorValidator(this.validationErrorModel, 'tags')] }); baseValidationArray.push({ key: 'hash', validators: [] }); baseContext.validation = baseValidationArray; return baseContext; } static reApplyPropertiesValidators(params: { formGroup: UntypedFormGroup, validationErrorModel: ValidationErrorModel, }): void { const { formGroup, validationErrorModel } = params; const control = formGroup?.get('properties'); DescriptionPropertyDefinitionEditorModel.reapplyValidators({ formGroup: control.get('fieldSets') as UntypedFormGroup, rootPath: `properties.`, validationErrorModel: validationErrorModel }); } } export class DescriptionPropertyDefinitionEditorModel implements DescriptionPropertyDefinitionPersist { fieldSets: Map = new Map; protected formBuilder: UntypedFormBuilder = new UntypedFormBuilder(); constructor( public validationErrorModel: ValidationErrorModel = new ValidationErrorModel() ) { } public fromModel(item: DescriptionPropertyDefinition, descriptionTemplate: DescriptionTemplate, descriptionReferences: DescriptionReference[]): DescriptionPropertyDefinitionEditorModel { this.fieldSets = this.calculateProperties(item, descriptionTemplate, descriptionReferences); return this; } buildForm(params?: { context?: ValidationContext, disabled?: boolean, rootPath?: string }): UntypedFormGroup { let { context = null, disabled = false, rootPath } = params ?? {} if (context == null) { context = DescriptionPropertyDefinitionEditorModel.createValidationContext({ validationErrorModel: this.validationErrorModel, rootPath }); } const formGroup = this.formBuilder.group({}); const fieldSetsFormGroup = this.formBuilder.group({}); if (this.fieldSets.size > 0) { this.fieldSets.forEach((value, key) => fieldSetsFormGroup.addControl(key.toString(), value.buildForm({ rootPath: `${rootPath}fieldSets[${key}].` })), context.getValidation('fieldSets')); formGroup.addControl('fieldSets', fieldSetsFormGroup); } return formGroup; } static createValidationContext(params: { rootPath?: string, validationErrorModel: ValidationErrorModel }): ValidationContext { const { rootPath = '', validationErrorModel } = params; const baseContext: ValidationContext = new ValidationContext(); const baseValidationArray: Validation[] = new Array(); baseValidationArray.push({ key: 'fieldSets', validators: [BackendErrorValidator(validationErrorModel, `${rootPath}fieldSets`)] }); baseContext.validation = baseValidationArray; return baseContext; } static reapplyValidators(params: { formGroup: UntypedFormGroup, validationErrorModel: ValidationErrorModel, rootPath: string }): void { const { formGroup, rootPath, validationErrorModel } = params; const keys = Object.keys(formGroup.value as Object); keys.forEach((key) => { const formArray = formGroup?.get(key); DescriptionPropertyDefinitionFieldSetEditorModel.reapplyValidators({ formArray: formArray.get('items') as UntypedFormArray, rootPath: `${rootPath}fieldSets[${key}].`, validationErrorModel: validationErrorModel }) }); } private calculateProperties(item: DescriptionPropertyDefinition, descriptionTemplate: DescriptionTemplate, descriptionReferences: DescriptionReference[]): Map { let result: Map = new Map(); if (descriptionTemplate) ( descriptionTemplate.definition.pages.forEach(definitionPage => { definitionPage.sections.forEach(definitionSection => { const sectionResult = this.calculateSectionProperties(definitionSection, item, descriptionReferences); if (sectionResult != null) { result = new Map([...result, ...sectionResult]); } }) }) ) return result; } private calculateSectionProperties(definitionSection: DescriptionTemplateSection, item: DescriptionPropertyDefinition, descriptionReferences: DescriptionReference[]): Map { if (definitionSection == null) return null; let result: Map = new Map(); definitionSection?.fieldSets?.forEach(definitionFieldSet => { const fieldSetResult = this.calculateFieldSetProperties(definitionFieldSet, item, descriptionReferences); if (fieldSetResult != null) { result.set(definitionFieldSet.id, fieldSetResult); } }); if (definitionSection.sections != null && definitionSection.sections?.length > 0) { definitionSection.sections.forEach(nestedDefinitionSection => { const nestedSectionResult = this.calculateSectionProperties(nestedDefinitionSection, item, descriptionReferences); if (nestedSectionResult != null) { result = new Map([...result, ...nestedSectionResult]); } }); } return result; } public calculateFieldSetProperties(definitionFieldSet: DescriptionTemplateFieldSet, item: DescriptionPropertyDefinition, descriptionReferences: DescriptionReference[]): DescriptionPropertyDefinitionFieldSetEditorModel { if (definitionFieldSet == null) return null; // current saved values const fieldSetValue: DescriptionPropertyDefinitionFieldSet = item?.fieldSets[definitionFieldSet.id] ?? {}; // new item case, where we need to add controls for all the containing fields. if (fieldSetValue.items == null || fieldSetValue.items?.length == 0) { const fields = new Map(); definitionFieldSet.fields.forEach(definitionField => { fields.set(definitionField.id, { textValue: undefined, textListValue: undefined, dateValue: undefined, externalIdentifier: undefined, references: undefined }); }) fieldSetValue.items = [{ fields: fields, ordinal: 0 } as DescriptionPropertyDefinitionFieldSetItem] } return new DescriptionPropertyDefinitionFieldSetEditorModel(this.validationErrorModel).fromModel(fieldSetValue, descriptionReferences, definitionFieldSet); } } export class DescriptionPropertyDefinitionFieldSetEditorModel implements DescriptionPropertyDefinitionFieldSetPersist { items?: DescriptionPropertyDefinitionFieldSetItemEditorModel[] = []; protected formBuilder: UntypedFormBuilder = new UntypedFormBuilder(); constructor( public validationErrorModel: ValidationErrorModel = new ValidationErrorModel() ) { } public fromModel(item: DescriptionPropertyDefinitionFieldSet, descriptionReferences: DescriptionReference[], definitionFieldSet: DescriptionTemplateFieldSet): DescriptionPropertyDefinitionFieldSetEditorModel { if (item) { if (item.items) { item.items.map(x => this.items.push(new DescriptionPropertyDefinitionFieldSetItemEditorModel(this.validationErrorModel).fromModel(x, descriptionReferences, definitionFieldSet))); } } return this; } buildForm(params?: { context?: ValidationContext, disabled?: boolean, rootPath?: string }): UntypedFormGroup { let { context = null, disabled = false, rootPath } = params ?? {} if (context == null) { context = DescriptionPropertyDefinitionFieldSetEditorModel.createValidationContext({ validationErrorModel: this.validationErrorModel, rootPath }); } return this.formBuilder.group({ items: this.formBuilder.array( (this.items ?? []).map( (item, index) => item.buildForm({ rootPath: `${rootPath}items[${index}].` }) ), context.getValidation('items').validators ) }); } static createValidationContext(params: { rootPath?: string, validationErrorModel: ValidationErrorModel }): ValidationContext { const { rootPath = '', validationErrorModel } = params; const baseContext: ValidationContext = new ValidationContext(); const baseValidationArray: Validation[] = new Array(); baseValidationArray.push({ key: 'items', validators: [BackendErrorValidator(validationErrorModel, `${rootPath}items`)] }); baseContext.validation = baseValidationArray; return baseContext; } static reapplyValidators(params: { formArray: UntypedFormArray, validationErrorModel: ValidationErrorModel, rootPath: string }): void { const { validationErrorModel, rootPath, formArray } = params; formArray?.controls?.forEach( (control, index) => DescriptionPropertyDefinitionFieldSetItemEditorModel.reapplyValidators({ formGroup: control as UntypedFormGroup, rootPath: `${rootPath}items[${index}].`, validationErrorModel: validationErrorModel }) ); } } export class DescriptionPropertyDefinitionFieldSetItemEditorModel implements DescriptionPropertyDefinitionFieldSetItemPersist { fields: Map = new Map; comment?: string; ordinal?: number; protected formBuilder: UntypedFormBuilder = new UntypedFormBuilder(); constructor( public validationErrorModel: ValidationErrorModel = new ValidationErrorModel() ) { } public fromModel(item: DescriptionPropertyDefinitionFieldSetItem, descriptionReferences: DescriptionReference[], definitionFieldSet: DescriptionTemplateFieldSet): DescriptionPropertyDefinitionFieldSetItemEditorModel { if (item) { this.comment = item.comment; this.ordinal = item.ordinal; if (item.fields) { //TODO: don't like it. Find a common way to parse it either its Map or json. if (item.fields instanceof Map) new Map(item.fields)?.forEach((value, key) => this.fields.set(key, new DescriptionFieldEditorModel(this.validationErrorModel).fromModel(value, definitionFieldSet?.fields?.find(x => x.id == key), descriptionReferences))); else Object.keys(item.fields)?.forEach((key) => this.fields.set(key, new DescriptionFieldEditorModel(this.validationErrorModel).fromModel(item.fields[key], definitionFieldSet?.fields?.find(x => x.id == key), descriptionReferences))); } } return this; } buildForm(params?: { context?: ValidationContext, disabled?: boolean, rootPath?: string }): UntypedFormGroup { let { context = null, disabled = false, rootPath } = params ?? {} if (context == null) { context = DescriptionPropertyDefinitionFieldSetItemEditorModel.createValidationContext({ validationErrorModel: this.validationErrorModel, rootPath }); } const formGroup = this.formBuilder.group({}); formGroup.addControl('comment', new FormControl({ value: this.comment, disabled: disabled }, context.getValidation('comment').validators)); formGroup.addControl('ordinal', new FormControl({ value: this.ordinal, disabled: disabled }, context.getValidation('ordinal').validators)); const fieldsFormGroup = this.formBuilder.group({}); this.fields.forEach((value, key) => fieldsFormGroup.addControl(key.toString(), value.buildForm({ rootPath: `${rootPath}fields[${key}].` })), context.getValidation('fields') ) formGroup.addControl('fields', fieldsFormGroup); return formGroup; } static createValidationContext(params: { rootPath?: string, validationErrorModel: ValidationErrorModel }): ValidationContext { const { rootPath = '', validationErrorModel } = params; const baseContext: ValidationContext = new ValidationContext(); const baseValidationArray: Validation[] = new Array(); baseValidationArray.push({ key: 'fields', validators: [BackendErrorValidator(validationErrorModel, `${rootPath}fields`)] }); baseValidationArray.push({ key: 'comment', validators: [BackendErrorValidator(validationErrorModel, `${rootPath}comment`)] }); baseValidationArray.push({ key: 'ordinal', validators: [BackendErrorValidator(validationErrorModel, `${rootPath}ordinal`)] }); baseContext.validation = baseValidationArray; return baseContext; } static reapplyValidators(params: { formGroup: UntypedFormGroup, validationErrorModel: ValidationErrorModel, rootPath: string }): void { const { formGroup, rootPath, validationErrorModel } = params; const context = DescriptionPropertyDefinitionFieldSetItemEditorModel.createValidationContext({ rootPath, validationErrorModel }); const fields = formGroup?.get('fields') as UntypedFormGroup; const keys = Object.keys(fields.value as Object); keys.forEach((key) => { const control = fields?.get(key); DescriptionFieldEditorModel.reapplyValidators({ formGroup: control as UntypedFormGroup, rootPath: `${rootPath}fields[${key}].`, validationErrorModel: validationErrorModel }) }); ['comment', 'ordinal'].forEach(keyField => { const control = formGroup?.get(keyField); control?.clearValidators(); control?.addValidators(context.getValidation(keyField).validators); }); } } export class DescriptionFieldEditorModel implements DescriptionFieldPersist { textValue: string; textListValue: string[]; dateValue: Date; references: ReferencePersist[] = []; reference: ReferencePersist; externalIdentifier?: DescriptionExternalIdentifierEditorModel = new DescriptionExternalIdentifierEditorModel(this.validationErrorModel); protected formBuilder: UntypedFormBuilder = new UntypedFormBuilder(); constructor( public validationErrorModel: ValidationErrorModel = new ValidationErrorModel() ) { } public fromModel(item: DescriptionField, descriptionTemplateField: DescriptionTemplateField, descriptionReferences: DescriptionReference[]): DescriptionFieldEditorModel { if (item) { this.textValue = item.textValue; this.textListValue = item.textListValue; this.dateValue = item.dateValue; this.reference = descriptionReferences?.filter(x => descriptionTemplateField.data.multipleSelect == false && x.data?.fieldId == descriptionTemplateField?.id && x.isActive == IsActive.Active).map(x => { return { id: x.reference.id, label: x.reference.label, reference: x.reference.reference, source: x.reference.source, typeId: x.reference.type.id, description: x.reference.source, definition: x.reference.definition, abbreviation: x.reference.abbreviation, sourceType: x.reference.sourceType } })[0]; this.references = descriptionReferences?.filter(x => x.data?.fieldId == descriptionTemplateField?.id && x.isActive == IsActive.Active).map(x => { return { id: x.reference.id, label: x.reference.label, reference: x.reference.reference, source: x.reference.source, typeId: x.reference.type.id, description: x.reference.source, definition: x.reference.definition, abbreviation: x.reference.abbreviation, sourceType: x.reference.sourceType } }); this.externalIdentifier = new DescriptionExternalIdentifierEditorModel(this.validationErrorModel).fromModel(item.externalIdentifier); } return this; } buildForm(params?: { context?: ValidationContext, disabled?: boolean, rootPath?: string }): UntypedFormGroup { let { context = null, disabled = false, rootPath } = params ?? {} if (context == null) { context = DescriptionFieldEditorModel.createValidationContext({ validationErrorModel: this.validationErrorModel, rootPath }); } return this.formBuilder.group({ textValue: [{ value: this.textValue, disabled: disabled }, context.getValidation('textValue').validators], textListValue: [{ value: this.textListValue, disabled: disabled }, context.getValidation('textListValue').validators], dateValue: [{ value: this.dateValue, disabled: disabled }, context.getValidation('dateValue').validators], references: [{ value: this.references, disabled: disabled }, context.getValidation('references').validators], reference: [{ value: this.reference, disabled: disabled }, context.getValidation('reference').validators], externalIdentifier: this.externalIdentifier.buildForm({ rootPath: `${rootPath}externalIdentifier.` }), }); } static createValidationContext(params: { rootPath?: string, validationErrorModel: ValidationErrorModel }): ValidationContext { const { rootPath = '', validationErrorModel } = params; const baseContext: ValidationContext = new ValidationContext(); const baseValidationArray: Validation[] = new Array(); baseValidationArray.push({ key: 'textValue', validators: [BackendErrorValidator(validationErrorModel, `${rootPath}textValue`)] }); baseValidationArray.push({ key: 'textListValue', validators: [BackendErrorValidator(validationErrorModel, `${rootPath}textListValue`)] }); baseValidationArray.push({ key: 'dateValue', validators: [BackendErrorValidator(validationErrorModel, `${rootPath}dateValue`)] }); baseValidationArray.push({ key: 'references', validators: [BackendErrorValidator(validationErrorModel, `${rootPath}references`)] }); baseValidationArray.push({ key: 'reference', validators: [BackendErrorValidator(validationErrorModel, `${rootPath}references`)] }); baseValidationArray.push({ key: 'externalIdentifier', validators: [BackendErrorValidator(validationErrorModel, `${rootPath}externalIdentifier`)] }); baseContext.validation = baseValidationArray; return baseContext; } static reapplyValidators(params: { formGroup: UntypedFormGroup, validationErrorModel: ValidationErrorModel, rootPath: string }): void { const { formGroup, rootPath, validationErrorModel } = params; const context = DescriptionFieldEditorModel.createValidationContext({ rootPath, validationErrorModel }); ['textValue', 'textListValue', 'dateValue'].forEach(keyField => { const control = formGroup?.get(keyField); control?.clearValidators(); control?.addValidators(context.getValidation(keyField).validators); }) DescriptionExternalIdentifierEditorModel.reapplyValidators({ formGroup: formGroup?.get('externalIdentifier') as UntypedFormGroup, rootPath: `${rootPath}externalIdentifier.`, validationErrorModel: validationErrorModel }); } } export class DescriptionExternalIdentifierEditorModel implements DescriptionExternalIdentifierPersist { identifier: string; type: string; protected formBuilder: UntypedFormBuilder = new UntypedFormBuilder(); constructor( public validationErrorModel: ValidationErrorModel = new ValidationErrorModel() ) { } public fromModel(item: DescriptionExternalIdentifier): DescriptionExternalIdentifierEditorModel { if (item) { this.identifier = item.identifier; this.type = item.type; } return this; } buildForm(params?: { context?: ValidationContext, disabled?: boolean, rootPath?: string }): UntypedFormGroup { let { context = null, disabled = false, rootPath } = params ?? {} if (context == null) { context = DescriptionExternalIdentifierEditorModel.createValidationContext({ validationErrorModel: this.validationErrorModel, rootPath }); } return this.formBuilder.group({ identifier: [{ value: this.identifier, disabled: disabled }, context.getValidation('identifier').validators], type: [{ value: this.type, disabled: disabled }, context.getValidation('type').validators], }); } static createValidationContext(params: { rootPath?: string, validationErrorModel: ValidationErrorModel }): ValidationContext { const { rootPath = '', validationErrorModel } = params; const baseContext: ValidationContext = new ValidationContext(); const baseValidationArray: Validation[] = new Array(); baseValidationArray.push({ key: 'identifier', validators: [BackendErrorValidator(validationErrorModel, `${rootPath}identifier`)] }); baseValidationArray.push({ key: 'type', validators: [BackendErrorValidator(validationErrorModel, `${rootPath}type`)] }); baseContext.validation = baseValidationArray; return baseContext; } static reapplyValidators(params: { formGroup: UntypedFormGroup, validationErrorModel: ValidationErrorModel, rootPath: string }): void { const { formGroup, rootPath, validationErrorModel } = params; const context = DescriptionExternalIdentifierEditorModel.createValidationContext({ rootPath, validationErrorModel }); ['identifier', 'type'].forEach(keyField => { const control = formGroup?.get(keyField); control?.clearValidators(); control?.addValidators(context.getValidation(keyField).validators); }); } } export class DescriptionReferenceEditorModel implements DescriptionReferencePersist { id: Guid; reference?: ReferencePersist; hash: string; protected formBuilder: UntypedFormBuilder = new UntypedFormBuilder(); constructor( public validationErrorModel: ValidationErrorModel = new ValidationErrorModel() ) { } fromModel(item: DescriptionReference): DescriptionReferenceEditorModel { this.id = item.id; //TODO: refactor reference type //this.reference = item.reference; this.hash = item.hash; return this; } buildForm(params?: { context?: ValidationContext, disabled?: boolean, rootPath?: string }): UntypedFormGroup { let { context = null, disabled = false, rootPath } = params ?? {} if (context == null) { context = DescriptionReferenceEditorModel.createValidationContext({ validationErrorModel: this.validationErrorModel, rootPath }); } return this.formBuilder.group({ id: [{ value: this.id, disabled: disabled }, context.getValidation('id').validators], reference: [{ value: this.reference, disabled: disabled }, context.getValidation('reference').validators], hash: [{ value: this.hash, disabled: disabled }, context.getValidation('hash').validators] }); } static createValidationContext(params: { rootPath?: string, validationErrorModel: ValidationErrorModel }): ValidationContext { const { rootPath = '', validationErrorModel } = params; const baseContext: ValidationContext = new ValidationContext(); const baseValidationArray: Validation[] = new Array(); baseValidationArray.push({ key: 'id', validators: [BackendErrorValidator(validationErrorModel, `${rootPath}id`)] }); baseValidationArray.push({ key: 'reference', validators: [BackendErrorValidator(validationErrorModel, `${rootPath}reference`)] }); baseValidationArray.push({ key: 'hash', validators: [] }); baseContext.validation = baseValidationArray; return baseContext; } static reapplyValidators(params: { formGroup: UntypedFormGroup, validationErrorModel: ValidationErrorModel, rootPath: string }): void { const { formGroup, rootPath, validationErrorModel } = params; const context = DescriptionExternalIdentifierEditorModel.createValidationContext({ rootPath, validationErrorModel }); ['id', 'reference'].forEach(keyField => { const control = formGroup?.get(keyField); control?.clearValidators(); control?.addValidators(context.getValidation(keyField).validators); }); } }