description templates fix reapply validation

This commit is contained in:
amentis 2024-02-06 16:00:52 +02:00
parent f7dc3e5a32
commit b4ccd71f85
12 changed files with 185 additions and 52 deletions

View File

@ -236,8 +236,11 @@ public class ExternalSelectDataPersist extends BaseFieldDataPersist {
protected List<Specification> specifications(ExternalSelectSourceBindingPersist item) {
return Arrays.asList(
this.spec()
.must(() -> !this.isNull(item.getLabel()))
.failOn(ExternalSelectSourceBindingPersist._label).failWith(messageSource.getMessage("Validation_Required", new Object[]{ExternalSelectSourceBindingPersist._label}, LocaleContextHolder.getLocale()))
.must(() -> !this.isEmpty(item.getLabel()))
.failOn(ExternalSelectSourceBindingPersist._label).failWith(messageSource.getMessage("Validation_Required", new Object[]{ExternalSelectSourceBindingPersist._label}, LocaleContextHolder.getLocale())),
this.spec()
.must(() -> !this.isEmpty(item.getValue()))
.failOn(ExternalSelectSourceBindingPersist._value).failWith(messageSource.getMessage("Validation_Required", new Object[]{ExternalSelectSourceBindingPersist._value}, LocaleContextHolder.getLocale()))
);
}
}

View File

@ -20,4 +20,5 @@ Validation_Required={0} is required
Validation_OverPosting=Too much info
Validation_MaxLength={0} too long
Validation_UnexpectedValue=Unexpected value in field {0}
Validation_Unique= {0} must be unique
Validation_Unique= {0} must be unique
Validation.LowerThanMin= value must be equal or larger than {0}

View File

@ -66,7 +66,7 @@
<div #inputs transition-group class="col-12" *ngIf="hasFocus" [@fade-in]>
<div *ngFor="let field of fieldsArray.controls; let i=index;" class="row bg-white field-input mt-3" (click)="setTargetField(field)" transition-group-item>
<app-description-template-editor-field-component class="col-12" [form]="field" [showOrdinal]="false" [indexPath]="indexPath + 'f' + i" [viewOnly]="viewOnly" [expandView]="hasFocus" [canBeDeleted]="fieldsArray.length !=1"
[validationErrorModel]="validationErrorModel" [rootPath]="rootPath" (delete)="deleteField(i)">
[validationErrorModel]="validationErrorModel" [rootPath]="rootPath + 'fields[' + i + '].'" (delete)="deleteField(i)">
<div class="arrows mt-2">
<ul class="list-unstyled list-inline d-flex align-items-center">
<li *ngIf="canGoUp(i)" class="text-muted">

View File

@ -573,7 +573,7 @@ export class DescriptionTemplateEditorCompositeFieldComponent extends BaseCompon
}
}
(<UntypedFormArray>this.form.get('fields')).push(new DescriptionTemplateFieldEditorModel().fromModel(field).buildForm());
(<UntypedFormArray>this.form.get('fields')).push(new DescriptionTemplateFieldEditorModel(this.validationErrorModel).fromModel(field).buildForm({rootPath: this.rootPath + 'fields[' + this.fieldsArray.length + '].'}));
this.inputs.init();
// fieldForm.get('viewStyle').get('renderStyle').updateValueAndValidity();
// fieldForm.get('data').updateValueAndValidity();

View File

@ -1,6 +1,6 @@
import { Component, Input, OnInit } from '@angular/core';
import { UntypedFormArray, UntypedFormGroup } from '@angular/forms';
import { DescriptionTemplateExternalSelectSourceEditorModel } from '../../../description-template-editor.model';
import { DescriptionTemplateExternalSelectDataEditorModel, DescriptionTemplateExternalSelectSourceEditorModel } from '../../../description-template-editor.model';
import { EnumUtils } from '@app/core/services/utilities/enum-utils.service';
import { DescriptionTemplateExternalSelectHttpMethodType } from '@app/core/common/enum/description-template-external-select-http-method-type';
import { DescriptionTemplateExternalSelectAuthType } from '@app/core/common/enum/description-template-external-select-auth-type';
@ -35,5 +35,12 @@ export class DescriptionTemplateEditorExternalSelectFieldComponent implements On
removeSource(index: number) {
(<UntypedFormArray>this.form.get('data').get('sources')).removeAt(index);
DescriptionTemplateExternalSelectDataEditorModel.reapplyValidators({
formGroup: this.form?.get('data') as UntypedFormGroup,
rootPath: `${this.rootPath}data.`,
validationErrorModel: this.validationErrorModel
});
this.form.get('data').get('sources').markAsDirty();
}
}

View File

@ -1,6 +1,6 @@
import { Component, Input, OnInit } from '@angular/core';
import { UntypedFormArray, UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
import { DescriptionTemplateRadioBoxOptionEditorModel } from '../../../description-template-editor.model';
import { DescriptionTemplateRadioBoxDataEditorModel, DescriptionTemplateRadioBoxOptionEditorModel } from '../../../description-template-editor.model';
import { ValidationErrorModel } from '@common/forms/validation/error-model/validation-error-model';
@Component({
@ -26,6 +26,16 @@ export class DescriptionTemplateEditorRadioBoxFieldComponent implements OnInit {
}
deleteRow(intex: number) {
if (this.form.get('data').get('options')) { (<UntypedFormArray>this.form.get('data').get('options')).removeAt(intex); }
if (this.form.get('data').get('options')) {
(<UntypedFormArray>this.form.get('data').get('options')).removeAt(intex);
DescriptionTemplateRadioBoxDataEditorModel.reapplyRadioBoxValidators({
formGroup: this.form.get('data') as UntypedFormGroup,
rootPath: `${this.rootPath}data.`,
validationErrorModel: this.validationErrorModel
});
this.form.get('data').get('options').markAsDirty();
}
}
}

View File

@ -1,6 +1,6 @@
import { Component, Input, OnInit } from '@angular/core';
import { UntypedFormArray, UntypedFormGroup } from '@angular/forms';
import { DescriptionTemplateSelectOptionEditorModel } from '../../../description-template-editor.model';
import { DescriptionTemplateSelectDataEditorModel, DescriptionTemplateSelectOptionEditorModel } from '../../../description-template-editor.model';
import { ValidationErrorModel } from '@common/forms/validation/error-model/validation-error-model';
@Component({
@ -24,6 +24,16 @@ export class DescriptionTemplateEditorSelectFieldComponent implements OnInit {
}
deleteRow(intex: number) {
if (this.form.get('data').get('options')) { (<UntypedFormArray>this.form.get('data').get('options')).removeAt(intex); }
if (this.form.get('data').get('options')) {
(<UntypedFormArray>this.form.get('data').get('options')).removeAt(intex);
DescriptionTemplateSelectDataEditorModel.reapplySelectValidators({
formGroup: this.form?.get('data') as UntypedFormGroup,
rootPath: `${this.rootPath}data.`,
validationErrorModel: this.validationErrorModel
});
this.form.get('data').get('options').markAsDirty();
}
}
}

View File

@ -2,7 +2,7 @@ import { Component, Input, OnInit } from '@angular/core';
import { UntypedFormArray, UntypedFormBuilder, UntypedFormControl, UntypedFormGroup } from '@angular/forms';
import { DescriptionTemplateUploadOption } from '@app/core/model/description-template/description-template';
import { ConfigurationService } from "@app/core/services/configuration/configuration.service";
import { DescriptionTemplateUploadOptionEditorModel } from '../../../description-template-editor.model';
import { DescriptionTemplateUploadDataEditorModel, DescriptionTemplateUploadOptionEditorModel } from '../../../description-template-editor.model';
import { ValidationErrorModel } from '@common/forms/validation/error-model/validation-error-model';
@Component({
@ -92,7 +92,18 @@ export class DescriptionTemplateEditorUploadFieldComponent implements OnInit {
}
deleteRow(index: number) {
if (this.form.get('data').get('types')) { (<UntypedFormArray>this.form.get('data').get('types')).removeAt(index); }
if (this.form.get('data').get('types')) {
(<UntypedFormArray>this.form.get('data').get('types')).removeAt(index);
DescriptionTemplateUploadDataEditorModel.reapplyUploadDataValidators(
{
formGroup: this.form.get('data') as UntypedFormGroup,
validationErrorModel: this.validationErrorModel,
rootPath: `${this.rootPath}data.`,
}
);
this.form.get('data').get('types').markAsDirty();
}
}
public getConfiguration() {

View File

@ -200,7 +200,7 @@
<ng-container *ngIf="form.get('visibilityRules')?.value.length">
<h4 class="col-12" style="font-weight: bold">{{'DESCRIPTION-TEMPLATE-EDITOR.STEPS.FORM.FIELD.FIELDS.RULES-TITLE' | translate}}
</h4>
<app-description-template-editor-visibility-rule-component class="col-12" [form]="form.get('visibilityRules')" [fieldTypeForCheck]="form.get('data').get('fieldType').value" [formArrayOptionsForCheck]="this.form.get('data')?.get('options')" [viewOnly]="viewOnly"></app-description-template-editor-visibility-rule-component>
<app-description-template-editor-visibility-rule-component class="col-12" [form]="form.get('visibilityRules')" [validationErrorModel]="validationErrorModel" [rootPath]="rootPath" [fieldTypeForCheck]="form.get('data').get('fieldType').value" [formArrayOptionsForCheck]="this.form.get('data')?.get('options')" [viewOnly]="viewOnly"></app-description-template-editor-visibility-rule-component>
<!-- <div class="col-12" *ngIf="!viewOnly">
<button mat-button class="full-width" (click)="addNewRule()" [disabled]="!form.get('data').get('fieldType').value">{{'DESCRIPTION-TEMPLATE-EDITOR.STEPS.FORM.FIELD.ACTIONS.ADD-RULE' | translate}}</button>
</div> -->

View File

@ -22,6 +22,7 @@ export class DescriptionTemplateEditorRuleComponent implements OnInit {
@Input() formArrayOptionsForCheck: UntypedFormArray;
@Input() viewOnly: boolean;
@Input() validationErrorModel: ValidationErrorModel;
@Input() rootPath: string;
options: OptionItem[];
@ -44,7 +45,13 @@ export class DescriptionTemplateEditorRuleComponent implements OnInit {
deleteRule(index) {
this.form.removeAt(index);
// TODO akis reply validators fix
this.form.controls?.forEach(
(control, index) => DescriptionTemplateRuleEditorModel.reapplyValidators({
formGroup: control as UntypedFormGroup,
rootPath: `${this.rootPath}visibilityRules[${index}].`,
validationErrorModel: this.validationErrorModel
})
);
this.form.markAsDirty();//deactivate guard
}

View File

@ -688,8 +688,8 @@ export class DescriptionTemplateEditorComponent extends BaseEditor<DescriptionTe
const fieldSetsArray = parent.form.get('fieldSets') as UntypedFormArray
//store rootPath for next levels/components
this.rootPath = 'definition.pages['+ pageIndex +'].'+ parentSectionRootPath+ 'fieldSets[' + fieldSetsArray.length + '].fields[' + 0 + '].';
const fieldForm = field.buildForm({ rootPath: this.rootPath});
this.rootPath = 'definition.pages['+ pageIndex +'].'+ parentSectionRootPath+ 'fieldSets[' + fieldSetsArray.length + '].';
const fieldForm = field.buildForm({ rootPath: this.rootPath+ 'fields[' + 0 + '].'});
//give fieldset id and ordinal
const fieldSet: DescriptionTemplateFieldSetEditorModel = new DescriptionTemplateFieldSetEditorModel(this.editorModel.validationErrorModel);
@ -742,6 +742,28 @@ export class DescriptionTemplateEditorComponent extends BaseEditor<DescriptionTe
return null;
}
private getUpdatedSectionFormArray(sectionFormArray: UntypedFormArray, tceId: string) : UntypedFormArray{
for (let i = 0; i < sectionFormArray?.length; i++) {
let sectionFormGroup = sectionFormArray.at(i);
let sectionId = sectionFormGroup.get('id').value;
const parentSections = sectionFormGroup.get('sections') as UntypedFormArray;
if (sectionId == tceId) {
sectionFormArray.removeAt(i);
return sectionFormArray;
// sectionFormArray.at(i).get('ordinal').patchValue(i);
} else if (parentSections && parentSections.length > 0){
const currentSectionFormArray = this.getUpdatedSectionFormArray(parentSections, tceId);
if (currentSectionFormArray != null || currentSectionFormArray != undefined){
return currentSectionFormArray;
}
}
}
return null;
}
onRemoveEntry(tce: ToCEntry) {
const dialogRef = this.dialog.open(ConfirmationDialogComponent, {
@ -818,7 +840,7 @@ export class DescriptionTemplateEditorComponent extends BaseEditor<DescriptionTe
const sections = pages.at(pageIndex).get('sections') as UntypedFormArray;
//remove section
this._updateSelectedItem(tce);
// this._updateSelectedItem(tce);
sections.removeAt(sectionIndex);
//update ordinal
@ -828,27 +850,28 @@ export class DescriptionTemplateEditorComponent extends BaseEditor<DescriptionTe
} else {//NOT FOUND IN FIRST LEVEL CASE
//LOOK FOR SUBSECTION CASE
let parentSectionIndex = -1;
let sectionIndex = -1;
for (let j = 0; j < pages.length; j++) {
const parentSections = pages.at(j).get('sections') as UntypedFormArray;
// let parentSectionIndex = -1;
// let sectionIndex = -1;
// for (let j = 0; j < pages.length; j++) {
// const parentSections = pages.at(j).get('sections') as UntypedFormArray;
for (let i = 0; i < parentSections?.length; i++) {
const sections = (pages.at(j).get('sections') as UntypedFormArray).at(i).get('sections') as UntypedFormArray;
// for (let i = 0; i < parentSections?.length; i++) {
// const sections = (pages.at(j).get('sections') as UntypedFormArray).at(i).get('sections') as UntypedFormArray;
for (let k = 0; i < sections?.length; i++) {
let section = sections.at(i);
let sectionId = section.get('id').value;
// for (let k = 0; i < sections?.length; i++) {
// let section = sections.at(i);
// let sectionId = section.get('id').value;
// if (sectionId == tce.id) {
// sectionIndex = k;
// parentSectionIndex = i;
// pageIndex = j;
// break;
// }
// }
// }
// }
if (sectionId == tce.id) {
sectionIndex = k;
parentSectionIndex = i;
pageIndex = j;
break;
}
}
}
}
// let parentFormArray = tce.form.parent as UntypedFormArray;
@ -860,15 +883,28 @@ export class DescriptionTemplateEditorComponent extends BaseEditor<DescriptionTe
// break;
// }
// }
if (sectionIndex >= 0) {
this._updateSelectedItem(tce);
const parentFormArray = (pages.at(pageIndex).get('sections') as UntypedFormArray).at(parentSectionIndex).get('sections') as UntypedFormArray;
parentFormArray.removeAt(sectionIndex);
// if (sectionIndex >= 0) {
// this._updateSelectedItem(tce);
// const parentFormArray = (pages.at(pageIndex).get('sections') as UntypedFormArray).at(parentSectionIndex).get('sections') as UntypedFormArray;
// parentFormArray.removeAt(sectionIndex);
//update odrinal
// //update odrinal
for (let i = 0; i < parentFormArray.length; i++) {
parentFormArray.at(i).get('ordinal').patchValue(i);
// for (let i = 0; i < parentFormArray.length; i++) {
// parentFormArray.at(i).get('ordinal').patchValue(i);
// }
// }
for (let j = 0; j < pages.length; j++) {
const parentSections = pages.at(j).get('sections') as UntypedFormArray;
const sectionFormArray = this.getUpdatedSectionFormArray(parentSections, tce.id);
if (sectionFormArray){
//update ordinal
for (let i = 0; i < sectionFormArray.length; i++) {
sectionFormArray.at(i).get('ordinal').patchValue(i);
}
break;
}
}

View File

@ -774,8 +774,8 @@ export class DescriptionTemplateFieldEditorModel implements DescriptionTemplateF
this.validationErrorModel
).fromModel(item).buildForm({
rootPath: `${rootPath}visibilityRules[${index}].`
}), context.getValidation('visibilityRules')
)
})
), context.getValidation('visibilityRules').validators
)
});
}
@ -864,6 +864,42 @@ export class DescriptionTemplateFieldEditorModel implements DescriptionTemplateF
validationErrorModel: validationErrorModel
});
if(formGroup?.get('data').get('fieldType').value != undefined){
switch (formGroup?.get('data').get('fieldType').value) {
case DescriptionTemplateFieldType.UPLOAD:
DescriptionTemplateUploadDataEditorModel.reapplyUploadDataValidators({
formGroup: formGroup?.get('data') as UntypedFormGroup,
rootPath: `${rootPath}data.`,
validationErrorModel: validationErrorModel
});
case DescriptionTemplateFieldType.RADIO_BOX:
DescriptionTemplateRadioBoxDataEditorModel.reapplyRadioBoxValidators({
formGroup: formGroup?.get('data') as UntypedFormGroup,
rootPath: `${rootPath}data.`,
validationErrorModel: validationErrorModel
});
case DescriptionTemplateFieldType.SELECT:
DescriptionTemplateSelectDataEditorModel.reapplySelectValidators({
formGroup: formGroup?.get('data') as UntypedFormGroup,
rootPath: `${rootPath}data.`,
validationErrorModel: validationErrorModel
});
case DescriptionTemplateFieldType.EXTERNAL_SELECT:
DescriptionTemplateExternalSelectDataEditorModel.reapplyValidators({
formGroup: formGroup?.get('data') as UntypedFormGroup,
rootPath: `${rootPath}data.`,
validationErrorModel: validationErrorModel
});
case DescriptionTemplateFieldType.EXTERNAL_DATASETS:
DescriptionTemplateExternalDatasetDataEditorModel.reapplyValidators({
formGroup: formGroup?.get('data') as UntypedFormGroup,
rootPath: `${rootPath}data.`,
validationErrorModel: validationErrorModel
});
}
}
(formGroup.get('visibilityRules') as FormArray).controls?.forEach(
(control, index) => DescriptionTemplateRuleEditorModel.reapplyValidators({
formGroup: control as UntypedFormGroup,
@ -1227,7 +1263,7 @@ export class DescriptionTemplateExternalSelectDataEditorModel extends Descriptio
control?.addValidators(context.getValidation(keyField).validators);
});
(formGroup.get('options') as FormArray).controls?.forEach(
(formGroup.get('sources') as FormArray).controls?.forEach(
(control, index) => DescriptionTemplateExternalSelectSourceEditorModel.reapplyValidators({
formGroup: control as UntypedFormGroup,
rootPath: `${rootPath}sources[${index}].`,
@ -1559,12 +1595,12 @@ export class DescriptionTemplateRadioBoxDataEditorModel extends DescriptionTempl
}
static reapplyRadioBoxValidators(params: {
formArray: UntypedFormArray,
formGroup: UntypedFormGroup,
validationErrorModel: ValidationErrorModel,
rootPath: string
}): void {
const { validationErrorModel, rootPath, formArray } = params;
formArray?.controls?.forEach(
const { validationErrorModel, rootPath, formGroup } = params;
(formGroup.get('options') as FormArray).controls?.forEach(
(control, index) => DescriptionTemplateRadioBoxOptionEditorModel.reapplyValidators({
formGroup: control as UntypedFormGroup,
rootPath: `${rootPath}options[${index}].`,
@ -1705,7 +1741,7 @@ export class DescriptionTemplateSelectDataEditorModel extends DescriptionTemplat
return baseContext;
}
static reapplyDepedencyValidators(params: {
static reapplySelectValidators(params: {
formGroup: UntypedFormGroup,
validationErrorModel: ValidationErrorModel,
rootPath: string
@ -1867,19 +1903,31 @@ export class DescriptionTemplateUploadDataEditorModel extends DescriptionTemplat
}
static reapplyUploadDataValidators(params: {
formArray: UntypedFormArray,
formGroup: UntypedFormGroup,
validationErrorModel: ValidationErrorModel,
rootPath: string
}): void {
const { validationErrorModel, rootPath, formArray } = params;
formArray?.controls?.forEach(
const { validationErrorModel, rootPath, formGroup } = params;
const context = DescriptionTemplateUploadDataEditorModel.createValidationContext({
rootPath,
validationErrorModel
});
(formGroup.get('types') as FormArray).controls?.forEach(
(control, index) => DescriptionTemplateUploadOptionEditorModel.reapplyValidators({
formGroup: control as UntypedFormGroup,
rootPath: `${rootPath}types[${index}].`,
validationErrorModel: validationErrorModel
})
);
['maxFileSizeInMB'].forEach(keyField => {
const control = formGroup?.get(keyField);
control?.clearValidators();
control?.addValidators(context.getValidation(keyField).validators);
});
}
}