From 412c778d8c8463255cfd307986763061102927a2 Mon Sep 17 00:00:00 2001 From: amentis Date: Tue, 16 Jan 2024 11:55:46 +0200 Subject: [PATCH] add backend validation in language, references, tenant,supportive material editor forms. --- .../commons/validation/BaseValidator.java | 3 + .../eudat/model/persist/ReferencePersist.java | 3 - .../TenantDepositConfigPersist.java | 2 +- .../TenantFileTransformersConfigPersist.java | 2 +- .../tenantconfig/TenantSourcePersist.java | 2 +- .../editor/language-editor.component.html | 16 ++-- .../editor/reference-editor.component.html | 47 ++++++------ .../editor/reference-editor.component.ts | 11 ++- .../editor/reference-editor.model.ts | 55 +++++++++++++- .../editor/tenant-editor.component.html | 57 +++++++------- .../tenant/editor/tenant-editor.component.ts | 24 +++++- .../tenant/editor/tenant-editor.model.ts | 74 ++++++++++++++++++- .../supportive-material-editor.component.html | 10 ++- 13 files changed, 229 insertions(+), 77 deletions(-) diff --git a/dmp-backend/core/src/main/java/eu/eudat/commons/validation/BaseValidator.java b/dmp-backend/core/src/main/java/eu/eudat/commons/validation/BaseValidator.java index 5992c55e3..3a2e5ac9c 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/commons/validation/BaseValidator.java +++ b/dmp-backend/core/src/main/java/eu/eudat/commons/validation/BaseValidator.java @@ -40,6 +40,9 @@ public abstract class BaseValidator extends AbstractValidator { protected Boolean isEmpty(String value) { return this.conventionService.isNullOrEmpty(value); } + protected Boolean isListNullOrEmpty(List value) { + return this.conventionService.isListNullOrEmpty(value); + } protected Boolean isNull(Object value) { return value == null; } diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/persist/ReferencePersist.java b/dmp-backend/core/src/main/java/eu/eudat/model/persist/ReferencePersist.java index 978cdc09b..95feb91e6 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/model/persist/ReferencePersist.java +++ b/dmp-backend/core/src/main/java/eu/eudat/model/persist/ReferencePersist.java @@ -186,9 +186,6 @@ public class ReferencePersist { .iff(() -> !this.isEmpty(item.getReference())) .must(() -> this.lessEqualLength(item.getReference(), ReferenceEntity._referenceLength)) .failOn(ReferencePersist._reference).failWith(messageSource.getMessage("Validation_MaxLength", new Object[]{ReferencePersist._reference}, LocaleContextHolder.getLocale())), - this.spec() - .must(() -> !this.isEmpty(item.getAbbreviation())) - .failOn(ReferencePersist._abbreviation).failWith(messageSource.getMessage("Validation_Required", new Object[]{ReferencePersist._abbreviation}, LocaleContextHolder.getLocale())), this.spec() .iff(() -> !this.isEmpty(item.getAbbreviation())) .must(() -> this.lessEqualLength(item.getAbbreviation(), ReferenceEntity._abbreviationLength)) diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/persist/tenantconfig/TenantDepositConfigPersist.java b/dmp-backend/core/src/main/java/eu/eudat/model/persist/tenantconfig/TenantDepositConfigPersist.java index 431d422e0..e2bbd6ea0 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/model/persist/tenantconfig/TenantDepositConfigPersist.java +++ b/dmp-backend/core/src/main/java/eu/eudat/model/persist/tenantconfig/TenantDepositConfigPersist.java @@ -47,7 +47,7 @@ public class TenantDepositConfigPersist { @Override protected List specifications(TenantDepositConfigPersist item) { return Collections.singletonList( - this.refSpec() + this.navSpec() .iff(() -> !this.isNull(item.getSources())) .on(TenantDepositConfigPersist._sources) .over(item.getSources()) diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/persist/tenantconfig/TenantFileTransformersConfigPersist.java b/dmp-backend/core/src/main/java/eu/eudat/model/persist/tenantconfig/TenantFileTransformersConfigPersist.java index e72b6ffa8..b8ede05c5 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/model/persist/tenantconfig/TenantFileTransformersConfigPersist.java +++ b/dmp-backend/core/src/main/java/eu/eudat/model/persist/tenantconfig/TenantFileTransformersConfigPersist.java @@ -47,7 +47,7 @@ public class TenantFileTransformersConfigPersist { @Override protected List specifications(TenantFileTransformersConfigPersist item) { return Collections.singletonList( - this.refSpec() + this.navSpec() .iff(() -> !this.isNull(item.getSources())) .on(TenantFileTransformersConfigPersist._sources) .over(item.getSources()) diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/persist/tenantconfig/TenantSourcePersist.java b/dmp-backend/core/src/main/java/eu/eudat/model/persist/tenantconfig/TenantSourcePersist.java index 0185b7b10..46add9237 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/model/persist/tenantconfig/TenantSourcePersist.java +++ b/dmp-backend/core/src/main/java/eu/eudat/model/persist/tenantconfig/TenantSourcePersist.java @@ -112,7 +112,7 @@ public class TenantSourcePersist { .must(() -> !this.isEmpty(item.getUrl())) .failOn(TenantSourcePersist._url).failWith(messageSource.getMessage("Validation_Required", new Object[]{TenantSourcePersist._url}, LocaleContextHolder.getLocale())), this.spec() - .must(() -> !this.isNull(item.getCodes())) + .must(() -> !this.isListNullOrEmpty(item.getCodes())) .failOn(TenantSourcePersist._codes).failWith(messageSource.getMessage("Validation_Required", new Object[]{TenantSourcePersist._codes}, LocaleContextHolder.getLocale())), this.spec() .must(() -> !this.isEmpty(item.getIssuerUrl())) diff --git a/dmp-frontend/src/app/ui/admin/language/editor/language-editor.component.html b/dmp-frontend/src/app/ui/admin/language/editor/language-editor.component.html index d63d0769c..3bc5faa99 100644 --- a/dmp-frontend/src/app/ui/admin/language/editor/language-editor.component.html +++ b/dmp-frontend/src/app/ui/admin/language/editor/language-editor.component.html @@ -33,8 +33,8 @@ {{'LANGUAGE-EDITOR.FIELDS.CODE' | translate}} - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} + {{formGroup.get('code').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}
@@ -45,24 +45,24 @@ {{languageCode}} - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} + {{formGroup.get('code').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}
{{'LANGUAGE-EDITOR.FIELDS.ORDINAL' | translate}} - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} + {{formGroup.get('ordinal').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}
{{'LANGUAGE-EDITOR.FIELDS.PAYLOAD' | translate}} - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} + {{formGroup.get('payload').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}} {{'LANGUAGE-EDITOR.FIELDS.OVERRIDE' | translate}} diff --git a/dmp-frontend/src/app/ui/admin/reference/editor/reference-editor.component.html b/dmp-frontend/src/app/ui/admin/reference/editor/reference-editor.component.html index 80e0cadbd..f527e3962 100644 --- a/dmp-frontend/src/app/ui/admin/reference/editor/reference-editor.component.html +++ b/dmp-frontend/src/app/ui/admin/reference/editor/reference-editor.component.html @@ -33,8 +33,8 @@ {{'REFERENCE-EDITOR.FIELDS.LABEL' | translate}} - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} + {{formGroup.get('label').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}
@@ -44,9 +44,9 @@ {{enumUtils.toReferenceTypeString(type)}} - - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} + + {{formGroup.get('type').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}
@@ -55,9 +55,8 @@
- - {{'GENERAL.VALIDATION.REQUIRED'| translate}} - + {{formGroup.get('description').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED'| translate}}
@@ -65,8 +64,8 @@ {{'REFERENCE-EDITOR.FIELDS.SOURCE' | translate}} - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} + {{formGroup.get('source').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}
@@ -76,25 +75,25 @@ {{enumUtils.toReferenceSourceTypeString(sourceType)}} - - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} + + {{formGroup.get('sourceType').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}
{{'REFERENCE-EDITOR.FIELDS.REFERENCE' | translate}} - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} + {{formGroup.get('reference').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}
{{'REFERENCE-EDITOR.FIELDS.ABBREVIATION' | translate}} - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} + {{formGroup.get('abbreviation').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}
@@ -121,8 +120,8 @@ {{'REFERENCE-EDITOR.FIELDS.CODE' | translate}} - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} + {{field.get('code').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}
@@ -132,17 +131,17 @@ {{enumUtils.toReferenceFieldDataTypeString(dataType)}} - - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} + + {{field.get('dataType').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}
{{'REFERENCE-EDITOR.FIELDS.VALUE' | translate}} - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} + {{field.get('value').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}
diff --git a/dmp-frontend/src/app/ui/admin/reference/editor/reference-editor.component.ts b/dmp-frontend/src/app/ui/admin/reference/editor/reference-editor.component.ts index f18bb26e6..a5741084e 100644 --- a/dmp-frontend/src/app/ui/admin/reference/editor/reference-editor.component.ts +++ b/dmp-frontend/src/app/ui/admin/reference/editor/reference-editor.component.ts @@ -190,12 +190,19 @@ export class ReferenceEditorComponent extends BaseEditor FieldEditorModel.reapplyValidators({ + formGroup: control as UntypedFormGroup, + rootPath: `${rootPath}fields[${index}].`, + validationErrorModel: validationErrorModel + }) + ); + } } export class FieldEditorModel implements FieldPersist { @@ -191,5 +225,24 @@ export class FieldEditorModel implements FieldPersist { baseContext.validation = baseValidationArray; return baseContext; } + + static reapplyValidators(params: { + formGroup: UntypedFormGroup, + validationErrorModel: ValidationErrorModel, + rootPath: string + }): void { + + const { formGroup, rootPath, validationErrorModel } = params; + const context = FieldEditorModel.createValidationContext({ + rootPath, + validationErrorModel + }); + + ['code', 'dataType', 'value'].forEach(keyField => { + const control = formGroup?.get(keyField); + control?.clearValidators(); + control?.addValidators(context.getValidation(keyField).validators); + }) + } } diff --git a/dmp-frontend/src/app/ui/admin/tenant/editor/tenant-editor.component.html b/dmp-frontend/src/app/ui/admin/tenant/editor/tenant-editor.component.html index 48e3f4bcd..377ee3ef5 100644 --- a/dmp-frontend/src/app/ui/admin/tenant/editor/tenant-editor.component.html +++ b/dmp-frontend/src/app/ui/admin/tenant/editor/tenant-editor.component.html @@ -32,16 +32,16 @@ {{'TENANT-EDITOR.FIELDS.NAME' | translate}} - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} + {{formGroup.get('name').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}
{{'TENANT-EDITOR.FIELDS.CODE' | translate}} - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} + {{formGroup.get('code').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}
@@ -50,9 +50,8 @@
- - {{'GENERAL.VALIDATION.REQUIRED'| translate}} - + {{formGroup.get('description').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED'| translate}}
@@ -79,40 +78,40 @@ {{'TENANT-EDITOR.FIELDS.URL' | translate}} - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} + {{source.get('url').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}
{{'TENANT-EDITOR.FIELDS.ISSUER-URL' | translate}} - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} + {{source.get('issuerUrl').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}
{{'TENANT-EDITOR.FIELDS.CLIENT-ID' | translate}} - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} + {{source.get('clientId').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}
{{'TENANT-EDITOR.FIELDS.CLIENT-SECRET' | translate}} - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} + {{source.get('clientSecret').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}
{{'TENANT-EDITOR.FIELDS.SCOPE' | translate}} - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} + {{source.get('scope').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}
@@ -134,6 +133,8 @@ [matChipInputAddOnBlur]="true" (matChipInputTokenEnd)="addDepositCode($event)"/> + {{source.get('codes').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}
@@ -162,40 +163,40 @@ {{'TENANT-EDITOR.FIELDS.URL' | translate}} - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} + {{source.get('url').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}
{{'TENANT-EDITOR.FIELDS.ISSUER-URL' | translate}} - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} + {{source.get('issuerUrl').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}
{{'TENANT-EDITOR.FIELDS.CLIENT-ID' | translate}} - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} + {{source.get('clientId').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}
{{'TENANT-EDITOR.FIELDS.CLIENT-SECRET' | translate}} - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} + {{source.get('clientSecret').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}
{{'TENANT-EDITOR.FIELDS.SCOPE' | translate}} - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} + {{source.get('scope').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}
@@ -217,6 +218,8 @@ [matChipInputAddOnBlur]="true" (matChipInputTokenEnd)="addFileCode($event)"/> + {{source.get('codes').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}
diff --git a/dmp-frontend/src/app/ui/admin/tenant/editor/tenant-editor.component.ts b/dmp-frontend/src/app/ui/admin/tenant/editor/tenant-editor.component.ts index a2e83aadf..b3269e787 100644 --- a/dmp-frontend/src/app/ui/admin/tenant/editor/tenant-editor.component.ts +++ b/dmp-frontend/src/app/ui/admin/tenant/editor/tenant-editor.component.ts @@ -192,12 +192,20 @@ export class TenantEditorComponent extends BaseEditor // deposit source // addDepositSource(): void { - const source: TenantSourceEditorModel = new TenantSourceEditorModel(); - (this.formGroup.get('config').get('deposit').get('sources') as FormArray).push(source.buildForm()); + (this.formGroup.get('config').get('deposit').get('sources') as FormArray).push(this.editorModel.createChildDeposit((this.formGroup.get('config').get('deposit').get('sources') as FormArray).length)); } removeDepositSource(sourceIndex: number): void { (this.formGroup.get('config').get('deposit').get('sources') as FormArray).removeAt(sourceIndex); + + //Reapply validators + TenantEditorModel.reApplyDepositSourcesValidators( + { + formGroup: this.formGroup, + validationErrorModel: this.editorModel.validationErrorModel + } + ) + this.formGroup.get('config').get('deposit').get('sources').markAsDirty(); } // deposit source codes @@ -232,12 +240,20 @@ export class TenantEditorComponent extends BaseEditor // fileTransformers source // addFileSource(): void { - const source: TenantSourceEditorModel = new TenantSourceEditorModel(); - (this.formGroup.get('config').get('fileTransformers').get('sources') as FormArray).push(source.buildForm()); + (this.formGroup.get('config').get('fileTransformers').get('sources') as FormArray).push(this.editorModel.createChildFileTransformer((this.formGroup.get('config').get('fileTransformers').get('sources') as FormArray).length)); } removeFileSource(sourceIndex: number): void { (this.formGroup.get('config').get('fileTransformers').get('sources') as FormArray).removeAt(sourceIndex); + + //Reapply validators + TenantEditorModel.reApplyFileTransformerSourcesValidators( + { + formGroup: this.formGroup, + validationErrorModel: this.editorModel.validationErrorModel + } + ) + this.formGroup.get('config').get('fileTransformers').get('sources').markAsDirty(); } // fileTransformers source codes diff --git a/dmp-frontend/src/app/ui/admin/tenant/editor/tenant-editor.model.ts b/dmp-frontend/src/app/ui/admin/tenant/editor/tenant-editor.model.ts index 268d4554d..ec5775981 100644 --- a/dmp-frontend/src/app/ui/admin/tenant/editor/tenant-editor.model.ts +++ b/dmp-frontend/src/app/ui/admin/tenant/editor/tenant-editor.model.ts @@ -1,4 +1,4 @@ -import { UntypedFormBuilder, UntypedFormGroup, Validators } from "@angular/forms"; +import { UntypedFormArray, UntypedFormBuilder, UntypedFormGroup, Validators } from "@angular/forms"; import { Tenant, TenantConfig, TenantConfigPersist, TenantDepositConfig, TenantDepositConfigPersist, TenantFileTransformersConfig, TenantFileTransformersConfigPersist, TenantPersist, TenantSource, TenantSourcePersist } from "@app/core/model/tenant/tenant"; import { BaseEditorModel } from "@common/base/base-form-editor-model"; import { BackendErrorValidator } from "@common/forms/validation/custom-validator"; @@ -55,6 +55,44 @@ export class TenantEditorModel extends BaseEditorModel implements TenantPersist baseContext.validation = baseValidationArray; return baseContext; } + + createChildDeposit(index: number): UntypedFormGroup { + const deposit: TenantSourceEditorModel = new TenantSourceEditorModel(this.validationErrorModel); + return deposit.buildForm({ rootPath: 'config.deposit.sources[' + index + '].' }); + } + + static reApplyDepositSourcesValidators(params: { + formGroup: UntypedFormGroup, + validationErrorModel: ValidationErrorModel, + }): void { + + const { formGroup, validationErrorModel } = params; + const control = formGroup?.get('config').get('deposit'); + TenantDepositConfigEditorModel.reapplySourcesFieldsValidators({ + formArray: control.get('sources') as UntypedFormArray, + rootPath: `config.deposit.`, + validationErrorModel: validationErrorModel + }); + } + + createChildFileTransformer(index: number): UntypedFormGroup { + const deposit: TenantSourceEditorModel = new TenantSourceEditorModel(this.validationErrorModel); + return deposit.buildForm({ rootPath: 'config.fileTransformers.sources[' + index + '].' }); + } + + static reApplyFileTransformerSourcesValidators(params: { + formGroup: UntypedFormGroup, + validationErrorModel: ValidationErrorModel, + }): void { + + const { formGroup, validationErrorModel } = params; + const control = formGroup?.get('config').get('fileTransformers'); + TenantDepositConfigEditorModel.reapplySourcesFieldsValidators({ + formArray: control.get('sources') as UntypedFormArray, + rootPath: `config.fileTransformers.`, + validationErrorModel: validationErrorModel + }); + } } export class TenantConfigEditorModel implements TenantConfigPersist { @@ -167,6 +205,21 @@ export class TenantDepositConfigEditorModel implements TenantDepositConfigPersis baseContext.validation = baseValidationArray; return baseContext; } + + static reapplySourcesFieldsValidators(params: { + formArray: UntypedFormArray, + validationErrorModel: ValidationErrorModel, + rootPath: string + }): void { + const { validationErrorModel, rootPath, formArray } = params; + formArray?.controls?.forEach( + (control, index) => TenantSourceEditorModel.reapplyValidators({ + formGroup: control as UntypedFormGroup, + rootPath: `${rootPath}sources[${index}].`, + validationErrorModel: validationErrorModel + }) + ); + } } export class TenantFileTransformersConfigEditorModel implements TenantFileTransformersConfigPersist { @@ -294,4 +347,23 @@ export class TenantSourceEditorModel implements TenantSourcePersist { baseContext.validation = baseValidationArray; return baseContext; } + + static reapplyValidators(params: { + formGroup: UntypedFormGroup, + validationErrorModel: ValidationErrorModel, + rootPath: string + }): void { + + const { formGroup, rootPath, validationErrorModel } = params; + const context = TenantSourceEditorModel.createValidationContext({ + rootPath, + validationErrorModel + }); + + ['url', 'codes', 'issuerUrl', 'clientId', 'clientSecret', 'scope'].forEach(keyField => { + const control = formGroup?.get(keyField); + control?.clearValidators(); + control?.addValidators(context.getValidation(keyField).validators); + }) + } } diff --git a/dmp-frontend/src/app/ui/supportive-material-editor/supportive-material-editor.component.html b/dmp-frontend/src/app/ui/supportive-material-editor/supportive-material-editor.component.html index fc2b9ae43..82e7ea6c5 100644 --- a/dmp-frontend/src/app/ui/supportive-material-editor/supportive-material-editor.component.html +++ b/dmp-frontend/src/app/ui/supportive-material-editor/supportive-material-editor.component.html @@ -11,8 +11,8 @@ {{enumUtils.toSupportiveMaterialTypeString(type)}} - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} + {{formGroup.get('type').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}
@@ -23,8 +23,8 @@ {{languageCode}} - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} + {{formGroup.get('languageCode').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}
@@ -50,6 +50,8 @@ alignleft aligncenter alignright alignjustify | \ bullist numlist outdent indent | code codesample | searchreplace | preview | removeformat | help' }" [formControl]="formGroup.get('payload')"> + {{formGroup.get('payload').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}