From 85859ce078f4e1818f5fa0940e5122687a4d5db5 Mon Sep 17 00:00:00 2001 From: Diamantis Tziotzios Date: Thu, 3 Feb 2022 20:06:27 +0200 Subject: [PATCH] visibiliity service performance improvements --- .../form-composite-field.component.ts | 29 ++-- .../form-field/form-field.component.html | 4 +- .../form-field/form-field.component.ts | 161 ++++++++++-------- .../form-section-inner.component.ts | 32 ++-- .../form-section/form-section.component.ts | 127 +++++++------- .../visibility-rules.service.ts | 45 +++-- 6 files changed, 232 insertions(+), 166 deletions(-) diff --git a/dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-composite-field/form-composite-field.component.ts b/dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-composite-field/form-composite-field.component.ts index 2cd1cc02f..b81e800c3 100644 --- a/dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-composite-field/form-composite-field.component.ts +++ b/dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-composite-field/form-composite-field.component.ts @@ -1,15 +1,17 @@ -import { Component, Input, OnInit } from '@angular/core'; -import { FormArray, FormGroup, AbstractControl, FormArrayName } from '@angular/forms'; -import { DatasetDescriptionCompositeFieldEditorModel, DatasetDescriptionFieldEditorModel } from '../../dataset-description-form.model'; +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input } from '@angular/core'; +import { FormArray, FormGroup } from '@angular/forms'; +import { BaseComponent } from '@common/base/base.component'; +import { takeUntil } from 'rxjs/operators'; import { ToCEntry } from '../../dataset-description.component'; import { VisibilityRulesService } from '../../visibility-rules/visibility-rules.service'; @Component({ selector: 'app-form-composite-field', templateUrl: './form-composite-field.component.html', - styleUrls: ['./form-composite-field.component.scss'] + styleUrls: ['./form-composite-field.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush }) -export class FormCompositeFieldComponent { +export class FormCompositeFieldComponent extends BaseComponent { @Input() datasetProfileId: String; @Input() form: FormGroup; @@ -19,13 +21,18 @@ export class FormCompositeFieldComponent { constructor( public visibilityRulesService: VisibilityRulesService, + private changeDetector: ChangeDetectorRef //private markForConsiderationService: MarkForConsiderationService, ) { + super(); + this.visibilityRulesService.getElementVisibilityMapObservable().pipe(takeUntil(this._destroyed)).subscribe(x => { + this.changeDetector.markForCheck(); + }); } ngOnInit() { - if(this.tocentry){ + if (this.tocentry) { this.form = this.tocentry.form as FormGroup; } } @@ -50,7 +57,7 @@ export class FormCompositeFieldComponent { deleteCompositeFieldFormGroup() { - const compositeFieldId = ((this.form.get('multiplicityItems') as FormArray).get(''+0) as FormGroup).getRawValue().id; + const compositeFieldId = ((this.form.get('multiplicityItems') as FormArray).get('' + 0) as FormGroup).getRawValue().id; const fieldIds = (this.form.get('fields') as FormArray).controls.map(control => control.get('id').value) as string[]; const numberOfItems = this.form.get('multiplicityItems').get('' + 0).get('fields').value.length; @@ -62,7 +69,7 @@ export class FormCompositeFieldComponent { this.visibilityRulesService.removeAllIdReferences(compositeFieldId); - fieldIds.forEach( x => this.visibilityRulesService.removeAllIdReferences(x)); + fieldIds.forEach(x => this.visibilityRulesService.removeAllIdReferences(x)); } deleteMultipeFieldFromCompositeFormGroup() { @@ -77,10 +84,10 @@ export class FormCompositeFieldComponent { fieldIds.forEach(x => this.visibilityRulesService.removeAllIdReferences(x)); (parent as FormArray).removeAt(index); - (parent as FormArray).controls.forEach((control, i)=>{ - try{ + (parent as FormArray).controls.forEach((control, i) => { + try { control.get('ordinal').setValue(i); - }catch{ + } catch { throw 'Could not find ordinal'; } }); diff --git a/dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-field/form-field.component.html b/dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-field/form-field.component.html index 3f12a64f7..f66811504 100644 --- a/dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-field/form-field.component.html +++ b/dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-field/form-field.component.html @@ -1,5 +1,5 @@ -
+
{{this.form.get('title').value}}
info diff --git a/dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-field/form-field.component.ts b/dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-field/form-field.component.ts index f6e0bcbe8..794fd19d5 100644 --- a/dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-field/form-field.component.ts +++ b/dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-field/form-field.component.ts @@ -1,5 +1,5 @@ -import { Component, Input, OnInit } from '@angular/core'; +import { ChangeDetectionStrategy, Component, Input, OnInit, SimpleChanges } from '@angular/core'; import { FormGroup, FormArray, FormControl } from '@angular/forms'; import { DatasetProfileComboBoxType } from '@app/core/common/enum/dataset-profile-combo-box-type'; import { DatasetProfileFieldViewStyle } from '@app/core/common/enum/dataset-profile-field-view-style'; @@ -19,7 +19,7 @@ import { SingleAutoCompleteConfiguration } from '@app/library/auto-complete/sing import { VisibilityRulesService } from '@app/ui/misc/dataset-description-form/visibility-rules/visibility-rules.service'; import { BaseComponent } from '@common/base/base.component'; import { TranslateService } from '@ngx-translate/core'; -import { map, takeUntil } from 'rxjs/operators'; +import { distinctUntilChanged, map, takeUntil } from 'rxjs/operators'; import { Observable } from 'rxjs'; import { ExternalSourceItemModel } from '@app/core/model/external-sources/external-source-item'; import { ExternalDatasetCriteria } from '@app/core/query/external-dataset/external-dataset-criteria'; @@ -39,7 +39,8 @@ import { AutoCompleteSingleData } from '@app/core/model/dataset-profile-definiti @Component({ selector: 'app-form-field', templateUrl: './form-field.component.html', - styleUrls: ['./form-field.component.scss'] + styleUrls: ['./form-field.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush }) export class FormFieldComponent extends BaseComponent implements OnInit { @@ -49,6 +50,14 @@ export class FormFieldComponent extends BaseComponent implements OnInit { @Input() isChild: Boolean = false; @Input() autocompleteOptions: AutoCompleteSingleData; + visible: boolean = true; + _renderStyle: DatasetProfileFieldViewStyle = null; + + get renderStyle() { + //console.log('renderStyle'); + return this._renderStyle; + } + // change: Subscription; // trackByFn = (index, item) => item ? item['id'] : null; @@ -95,9 +104,22 @@ export class FormFieldComponent extends BaseComponent implements OnInit { private datasetService: DatasetService, private dmpService: DmpService, private currencyService: CurrencyService - ) { super(); } + ) { + super(); + + this.visibilityRulesService.getElementVisibilityMapObservable().pipe(takeUntil(this._destroyed)).subscribe(x => { + this.visible = this.visibilityRulesService.checkElementVisibility(this.form?.get('id')?.value); + }); + } + + ngOnChanges(changes: SimpleChanges) { + if (changes['form']) { + this._renderStyle = this.form.get('viewStyle')?.value?.renderStyle; + } + } ngOnInit() { + if (this.form.get('value').value) { this.visibilityRulesService.updateValueAndVisibility(this.form.get('id').value, this.form.get('value').value); } @@ -127,20 +149,20 @@ export class FormFieldComponent extends BaseComponent implements OnInit { this.singleAutoCompleteConfiguration = { filterFn: this.searchFromAutocomplete.bind(this), initialItems: () => this.searchFromAutocomplete(''), - displayFn: (item) => {try{return (item != null && item.length > 1) ? JSON.parse(item).label : item['label']}catch{return ''}}, - titleFn: (item) => {try{return item['label'] }catch{return''}}, - valueAssign: (item) => {try{return JSON.stringify(item)}catch{return''}}, - subtitleFn: (item) => {try{return item['source'] ? this.language.instant('DATASET-WIZARD.EDITOR.FIELDS.EXTERNAL-AUTOCOMPLETE-SUBTITLE') + item['source'] : this.language.instant('DATASET-WIZARD.EDITOR.FIELDS.EXTERNAL-AUTOCOMPLETE-NO-SOURCE')}catch{return''}} + displayFn: (item) => { try { return (item != null && item.length > 1) ? JSON.parse(item).label : item['label'] } catch { return '' } }, + titleFn: (item) => { try { return item['label'] } catch { return '' } }, + valueAssign: (item) => { try { return JSON.stringify(item) } catch { return '' } }, + subtitleFn: (item) => { try { return item['source'] ? this.language.instant('DATASET-WIZARD.EDITOR.FIELDS.EXTERNAL-AUTOCOMPLETE-SUBTITLE') + item['source'] : this.language.instant('DATASET-WIZARD.EDITOR.FIELDS.EXTERNAL-AUTOCOMPLETE-NO-SOURCE') } catch { return '' } } }; } else { this.multipleAutoCompleteConfiguration = { filterFn: this.searchFromAutocomplete.bind(this), initialItems: () => this.searchFromAutocomplete(''), - displayFn: (item) =>{try{return typeof (item) == 'string' ? JSON.parse(item)['label'] : item['label']}catch{return''}}, - titleFn: (item) =>{ try{return typeof (item) == 'string' ? JSON.parse(item)['label'] : item['label']}catch{return''}}, - valueAssign: (item) =>{ try{return typeof (item) == 'string' ? item : JSON.stringify(item)}catch{return''}}, - subtitleFn: (item) => { try{return item['source'] ? this.language.instant('DATASET-WIZARD.EDITOR.FIELDS.EXTERNAL-AUTOCOMPLETE-SUBTITLE') + item['source'] : this.language.instant('DATASET-WIZARD.EDITOR.FIELDS.EXTERNAL-AUTOCOMPLETE-NO-SOURCE')}catch{return''}} + displayFn: (item) => { try { return typeof (item) == 'string' ? JSON.parse(item)['label'] : item['label'] } catch { return '' } }, + titleFn: (item) => { try { return typeof (item) == 'string' ? JSON.parse(item)['label'] : item['label'] } catch { return '' } }, + valueAssign: (item) => { try { return typeof (item) == 'string' ? item : JSON.stringify(item) } catch { return '' } }, + subtitleFn: (item) => { try { return item['source'] ? this.language.instant('DATASET-WIZARD.EDITOR.FIELDS.EXTERNAL-AUTOCOMPLETE-SUBTITLE') + item['source'] : this.language.instant('DATASET-WIZARD.EDITOR.FIELDS.EXTERNAL-AUTOCOMPLETE-NO-SOURCE') } catch { return '' } } } } } @@ -150,49 +172,49 @@ export class FormFieldComponent extends BaseComponent implements OnInit { this.externalDatasetAutoCompleteConfiguration = { filterFn: this.searchDatasetExternalDatasets.bind(this), initialItems: () => this.searchDatasetExternalDatasets(''),//.filter(resultItem => (excludedItems || []).map(x => x.id).indexOf(resultItem.id) === -1), - displayFn: (item) => { try{return typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name}catch{return''}}, - titleFn: (item) => { try{return typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name}catch{return''}}, - subtitleFn: (item) => { try{return item.source ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item.source : item.tag ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item.tag : this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.NO-SOURCE')}catch{return''}}, - valueAssign: (item) => { try{return typeof (item) == 'string' ? item : JSON.stringify(item)}catch{return''}} + displayFn: (item) => { try { return typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name } catch { return '' } }, + titleFn: (item) => { try { return typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name } catch { return '' } }, + subtitleFn: (item) => { try { return item.source ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item.source : item.tag ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item.tag : this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.NO-SOURCE') } catch { return '' } }, + valueAssign: (item) => { try { return typeof (item) == 'string' ? item : JSON.stringify(item) } catch { return '' } } }; break; case DatasetProfileFieldViewStyle.DataRepositories: this.dataRepositoriesAutoCompleteConfiguration = { filterFn: this.searchDatasetExternalDataRepositories.bind(this), initialItems: () => this.searchDatasetExternalDataRepositories(''), - displayFn: (item) => { try{return typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name}catch{return''}}, - titleFn: (item) => { try{return typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name}catch{return''}}, - subtitleFn: (item) => { try{return item.source ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item.source : item.tag ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item.tag : this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.NO-SOURCE')}catch{return''}}, - valueAssign: (item) => { try{return typeof (item) == 'string' ? item : JSON.stringify(item)}catch{return''}} + displayFn: (item) => { try { return typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name } catch { return '' } }, + titleFn: (item) => { try { return typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name } catch { return '' } }, + subtitleFn: (item) => { try { return item.source ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item.source : item.tag ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item.tag : this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.NO-SOURCE') } catch { return '' } }, + valueAssign: (item) => { try { return typeof (item) == 'string' ? item : JSON.stringify(item) } catch { return '' } } }; break; case DatasetProfileFieldViewStyle.Registries: this.registriesAutoCompleteConfiguration = { filterFn: this.searchDatasetExternalRegistries.bind(this), initialItems: () => this.searchDatasetExternalRegistries(''), - displayFn: (item) => { try{return typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name}catch{return''}}, - titleFn: (item) => { try{return typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name}catch{return''}}, - subtitleFn: (item) => { try{return item.source ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item.source : this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.NO-SOURCE')}catch{return''}}, - valueAssign: (item) => { try{return typeof (item) == 'string' ? item : JSON.stringify(item)}catch{return''}} + displayFn: (item) => { try { return typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name } catch { return '' } }, + titleFn: (item) => { try { return typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name } catch { return '' } }, + subtitleFn: (item) => { try { return item.source ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item.source : this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.NO-SOURCE') } catch { return '' } }, + valueAssign: (item) => { try { return typeof (item) == 'string' ? item : JSON.stringify(item) } catch { return '' } } }; break; case DatasetProfileFieldViewStyle.Services: this.servicesAutoCompleteConfiguration = { filterFn: this.searchDatasetExternalServices.bind(this), initialItems: () => this.searchDatasetExternalServices(''), - displayFn: (item) => { try{return typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name}catch{return ''}}, - titleFn: (item) => { try{return typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name}catch{return''}}, - subtitleFn: (item) => { try{return item.source ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item.source : item.tag ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item.tag : this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.NO-SOURCE')}catch{return''}}, - valueAssign: (item) => { try{return typeof (item) == 'string' ? item : JSON.stringify(item)}catch{return''}} + displayFn: (item) => { try { return typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name } catch { return '' } }, + titleFn: (item) => { try { return typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name } catch { return '' } }, + subtitleFn: (item) => { try { return item.source ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item.source : item.tag ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item.tag : this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.NO-SOURCE') } catch { return '' } }, + valueAssign: (item) => { try { return typeof (item) == 'string' ? item : JSON.stringify(item) } catch { return '' } } }; break; case DatasetProfileFieldViewStyle.Tags: this.tagsAutoCompleteConfiguration = { filterFn: this.filterTags.bind(this), initialItems: (excludedItems: any[]) => this.filterTags('').pipe(map(result => result.filter(resultItem => (excludedItems || []).map(x => x.id).indexOf(resultItem.id) === -1))), - displayFn: (item) => { try{return this.showTag(item)}catch{return''}}, - titleFn: (item) => { try{return item['name']}catch{return''}}, - valueAssign: (item) => { try{return this.addTag(item)}catch{return''}} + displayFn: (item) => { try { return this.showTag(item) } catch { return '' } }, + titleFn: (item) => { try { return item['name'] } catch { return '' } }, + valueAssign: (item) => { try { return this.addTag(item) } catch { return '' } } }; this.parseTags(); break; @@ -200,20 +222,20 @@ export class FormFieldComponent extends BaseComponent implements OnInit { this.researchersAutoCompleteConfiguration = { filterFn: this.filterResearchers.bind(this), initialItems: (excludedItems: any[]) => this.filterResearchers('').pipe(map(result => result.filter(resultItem => (excludedItems || []).map(x => x.id).indexOf(resultItem.id) === -1))), - displayFn: (item) => { try{return typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name}catch{return''}}, - titleFn: (item) =>{ try{return typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name}catch{return''}}, - subtitleFn: (item) => { try{return item['tag'] ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item['tag'] : (item['key'] ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item['key'] : this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.NO-SOURCE'))}catch{return''}}, - valueAssign: (item) => { try{return typeof (item) == 'string' ? item : JSON.stringify(item)}catch{return''}} + displayFn: (item) => { try { return typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name } catch { return '' } }, + titleFn: (item) => { try { return typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name } catch { return '' } }, + subtitleFn: (item) => { try { return item['tag'] ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item['tag'] : (item['key'] ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item['key'] : this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.NO-SOURCE')) } catch { return '' } }, + valueAssign: (item) => { try { return typeof (item) == 'string' ? item : JSON.stringify(item) } catch { return '' } } }; break; case DatasetProfileFieldViewStyle.Organizations: this.organisationsAutoCompleteConfiguration = { filterFn: this.filterOrganisations.bind(this), initialItems: (excludedItems: any[]) => this.filterOrganisations('').pipe(map(result => result.filter(resultItem => (excludedItems || []).map(x => x.id).indexOf(resultItem.id) === -1))), - displayFn:(item) => { try{return typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name}catch{return''}}, - titleFn: (item) =>{ try{return typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name}catch{return''}}, - subtitleFn: (item) =>{ try{return item['tag'] ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item['tag'] : (item['key'] ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item['key'] : this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.NO-SOURCE'))}catch{return''}}, - valueAssign: (item) =>{ try{return typeof (item) == 'string' ? item : JSON.stringify(item)}catch{return''}} + displayFn: (item) => { try { return typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name } catch { return '' } }, + titleFn: (item) => { try { return typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name } catch { return '' } }, + subtitleFn: (item) => { try { return item['tag'] ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item['tag'] : (item['key'] ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item['key'] : this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.NO-SOURCE')) } catch { return '' } }, + valueAssign: (item) => { try { return typeof (item) == 'string' ? item : JSON.stringify(item) } catch { return '' } } }; break; case DatasetProfileFieldViewStyle.DatasetIdentifier: @@ -226,9 +248,9 @@ export class FormFieldComponent extends BaseComponent implements OnInit { this.currencyAutoCompleteConfiguration = { filterFn: this.searchCurrency.bind(this), initialItems: () => this.searchCurrency(''), - displayFn: (item) => { try{return typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name}catch{return''}}, - titleFn: (item) => { try{return typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name}catch{return''}}, - valueAssign: (item) => { try{return typeof (item) == 'string' ? item : JSON.stringify(item)}catch{return''}} + displayFn: (item) => { try { return typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name } catch { return '' } }, + titleFn: (item) => { try { return typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name } catch { return '' } }, + valueAssign: (item) => { try { return typeof (item) == 'string' ? item : JSON.stringify(item) } catch { return '' } } }; break; case DatasetProfileFieldViewStyle.Validation: @@ -253,7 +275,10 @@ export class FormFieldComponent extends BaseComponent implements OnInit { // this.form = this.visibilityRulesService.getFormGroup(this.field.id); this.form.get('value').valueChanges - .pipe(takeUntil(this._destroyed)) + .pipe( + takeUntil(this._destroyed), + distinctUntilChanged() + ) .subscribe(item => { // if (this.form.get('viewStyle').value.renderStyle === DatasetProfileFieldViewStyle.ComboBox && this.form.get('data').value.type === DatasetProfileComboBoxType.WordList && this.form.get('data').value.multiList) { // item.forEach(element => { @@ -261,7 +286,7 @@ export class FormFieldComponent extends BaseComponent implements OnInit { // }); // } else { - this.visibilityRulesService.updateValueAndVisibility(this.form.get('id').value, item); + this.visibilityRulesService.updateValueAndVisibility(this.form.get('id').value, item); // } }); } @@ -293,7 +318,7 @@ export class FormFieldComponent extends BaseComponent implements OnInit { } autocompleteRequestItem.criteria.like = query; - if(this.autocompleteOptions){ + if (this.autocompleteOptions) { return this.datasetExternalAutocompleteService.queryApi(autocompleteRequestItem); } return this.datasetExternalAutocompleteService.queryAutocomplete(autocompleteRequestItem); @@ -327,20 +352,20 @@ export class FormFieldComponent extends BaseComponent implements OnInit { this.singleAutoCompleteConfiguration = { filterFn: myfunc.bind(this), initialItems: (extraData) => myfunc(''), - displayFn: (item) => { try{return (item != null && item.length > 1) ? JSON.parse(item)[title] : item[title]}catch{return''}}, - titleFn: (item) => { try{return item[title]}catch{return''}}, + displayFn: (item) => { try { return (item != null && item.length > 1) ? JSON.parse(item)[title] : item[title] } catch { return '' } }, + titleFn: (item) => { try { return item[title] } catch { return '' } }, valueAssign: (item) => JSON.stringify(item), - subtitleFn: (item) => { try{return item[subtitle]}catch{return''}} + subtitleFn: (item) => { try { return item[subtitle] } catch { return '' } } }; } else { this.multipleAutoCompleteConfiguration = { filterFn: myfunc.bind(this), initialItems: (extraData) => myfunc(''), - displayFn: (item) => { try{return typeof (item) == 'string' ? JSON.parse(item)[title] : item[title]}catch{return''}}, - titleFn: (item) => { try{return typeof (item) == 'string' ? JSON.parse(item)[title] : item[title]}catch{return''}}, - valueAssign: (item) => { try{return typeof (item) == 'string' ? item : JSON.stringify(item)}catch{return''}}, - subtitleFn: (item) => { try{return item[subtitle]}catch{return''}} + displayFn: (item) => { try { return typeof (item) == 'string' ? JSON.parse(item)[title] : item[title] } catch { return '' } }, + titleFn: (item) => { try { return typeof (item) == 'string' ? JSON.parse(item)[title] : item[title] } catch { return '' } }, + valueAssign: (item) => { try { return typeof (item) == 'string' ? item : JSON.stringify(item) } catch { return '' } }, + subtitleFn: (item) => { try { return item[subtitle] } catch { return '' } } } } } @@ -386,23 +411,23 @@ export class FormFieldComponent extends BaseComponent implements OnInit { } parseTags() { - try{ + try { - let stringValue = this.form.get('value').value; - if (typeof stringValue === 'string') { - stringValue = (stringValue).replace(new RegExp('{', 'g'), '{"').replace(new RegExp('=', 'g'), '":"').replace(new RegExp(',', 'g'), '",').replace(new RegExp(', ', 'g'), ', "').replace(new RegExp('}', 'g'), '"}'); - stringValue = stringValue.replace(new RegExp('}"', 'g'), '}').replace(new RegExp('"{', 'g'), '{'); - } else if (stringValue instanceof Array) { - const tempArray = new Array(); - for (let stringTag of stringValue) { - tempArray.push(JSON.parse(stringTag)); + let stringValue = this.form.get('value').value; + if (typeof stringValue === 'string') { + stringValue = (stringValue).replace(new RegExp('{', 'g'), '{"').replace(new RegExp('=', 'g'), '":"').replace(new RegExp(',', 'g'), '",').replace(new RegExp(', ', 'g'), ', "').replace(new RegExp('}', 'g'), '"}'); + stringValue = stringValue.replace(new RegExp('}"', 'g'), '}').replace(new RegExp('"{', 'g'), '{'); + } else if (stringValue instanceof Array) { + const tempArray = new Array(); + for (let stringTag of stringValue) { + tempArray.push(JSON.parse(stringTag)); + } + stringValue = JSON.stringify(tempArray); } - stringValue = JSON.stringify(tempArray); - } - const tagArray = JSON.parse(stringValue); - this.form.patchValue({'value': tagArray}); - }catch(e){ + const tagArray = JSON.parse(stringValue); + this.form.patchValue({ 'value': tagArray }); + } catch (e) { console.warn('Could not parse tags'); } } @@ -431,7 +456,7 @@ export class FormFieldComponent extends BaseComponent implements OnInit { } else { item = ev; } - if (item.name !== '' ) { + if (item.name !== '') { return item; } } @@ -455,7 +480,7 @@ export class FormFieldComponent extends BaseComponent implements OnInit { validateId() { const identifier = this.getDatasetIdControl('identifier').value; const type = this.getDatasetIdControl('type').value; - this.validationIcon= 'loading'; + this.validationIcon = 'loading'; this.externalSourcesService.validateIdentifier(identifier, type).pipe(takeUntil(this._destroyed)).subscribe(result => { this.validationIcon = result === true ? 'done' : 'clear'; }); diff --git a/dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-section/form-section-inner/form-section-inner.component.ts b/dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-section/form-section-inner/form-section-inner.component.ts index c14967308..f8e8102e1 100644 --- a/dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-section/form-section-inner/form-section-inner.component.ts +++ b/dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-section/form-section-inner/form-section-inner.component.ts @@ -1,22 +1,24 @@ -import { AfterViewInit, Component, Input, OnInit, OnChanges, SimpleChanges } from '@angular/core'; -import { FormGroup, FormArray, AbstractControl } from '@angular/forms'; +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core'; +import { FormArray, FormGroup } from '@angular/forms'; +import { BaseComponent } from '@common/base/base.component'; +import { takeUntil } from 'rxjs/operators'; +import { DatasetDescriptionCompositeFieldEditorModel } from '../../../dataset-description-form.model'; import { FormFocusService } from '../../../form-focus/form-focus.service'; -import { VisibilityRulesService } from '../../../visibility-rules/visibility-rules.service'; -import { DatasetDescriptionSectionEditorModel, DatasetDescriptionCompositeFieldEditorModel } from '../../../dataset-description-form.model'; -import { FormCompositeFieldComponent } from '../../form-composite-field/form-composite-field.component'; import { LinkToScroll } from '../../../tableOfContentsMaterial/table-of-contents'; +import { VisibilityRulesService } from '../../../visibility-rules/visibility-rules.service'; @Component({ selector: 'app-form-section-inner', templateUrl: './form-section-inner.component.html', - styleUrls: ['./form-section-inner.component.scss'] + styleUrls: ['./form-section-inner.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush }) -export class FormSectionInnerComponent implements OnInit, OnChanges { +export class FormSectionInnerComponent extends BaseComponent implements OnInit, OnChanges { //@Input() section: DatasetDescriptionSectionEditorModel; @Input() datasetProfileId: String; // @Input() compositeFieldFormGroup: FormGroup; - @Input() form:FormGroup; + @Input() form: FormGroup; @Input() pathName: string; @Input() path: string; // @Input() i: number; @@ -28,8 +30,14 @@ export class FormSectionInnerComponent implements OnInit, OnChanges { constructor( public visibilityRulesService: VisibilityRulesService, + private changeDetector: ChangeDetectorRef, private formFocusService: FormFocusService - ) { } + ) { + super(); + this.visibilityRulesService.getElementVisibilityMapObservable().pipe(takeUntil(this._destroyed)).subscribe(x => { + this.changeDetector.markForCheck(); + }); + } ngOnInit() { // if (this.section) { @@ -75,10 +83,10 @@ export class FormSectionInnerComponent implements OnInit, OnChanges { deleteMultipeFieldFromCompositeFormGroup(compositeFildIndex: number, fildIndex: number) { const multiplicityItemsArray = ((this.form.get('compositeFields').get('' + compositeFildIndex).get('multiplicityItems'))) multiplicityItemsArray.removeAt(fildIndex); - multiplicityItemsArray.controls.forEach((control, i)=>{ - try{ + multiplicityItemsArray.controls.forEach((control, i) => { + try { control.get('ordinal').setValue(i); - }catch{ + } catch { throw 'Could not find ordinal'; } }); diff --git a/dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-section/form-section.component.ts b/dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-section/form-section.component.ts index 1b2260e2f..dfb4adefd 100644 --- a/dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-section/form-section.component.ts +++ b/dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-section/form-section.component.ts @@ -1,22 +1,23 @@ -import { AfterViewInit, Component, Input, OnInit, OnChanges, SimpleChanges, Output, EventEmitter } from '@angular/core'; -import { FormGroup, FormArray, AbstractControl } from '@angular/forms'; -import { FormFocusService } from '../../form-focus/form-focus.service'; -import { VisibilityRulesService } from '../../visibility-rules/visibility-rules.service'; -import { DatasetDescriptionSectionEditorModel, DatasetDescriptionCompositeFieldEditorModel } from '../../dataset-description-form.model'; -import { FormCompositeFieldComponent } from '../form-composite-field/form-composite-field.component'; -import { LinkToScroll } from '../../tableOfContentsMaterial/table-of-contents'; -import { ToCEntry, ToCEntryType } from '../../dataset-description.component'; -import { VisibilityRuleSource } from '../../visibility-rules/models/visibility-rule-source'; -import { VisibilityRule } from '../../visibility-rules/models/visibility-rule'; +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges } from '@angular/core'; +import { FormArray, FormGroup } from '@angular/forms'; import { Rule } from '@app/core/model/dataset-profile-definition/rule'; +import { BaseComponent } from '@common/base/base.component'; +import { takeUntil } from 'rxjs/operators'; +import { DatasetDescriptionCompositeFieldEditorModel } from '../../dataset-description-form.model'; +import { ToCEntry, ToCEntryType } from '../../dataset-description.component'; +import { FormFocusService } from '../../form-focus/form-focus.service'; +import { LinkToScroll } from '../../tableOfContentsMaterial/table-of-contents'; +import { VisibilityRuleSource } from '../../visibility-rules/models/visibility-rule-source'; +import { VisibilityRulesService } from '../../visibility-rules/visibility-rules.service'; @Component({ selector: 'app-form-section', templateUrl: './form-section.component.html', - styleUrls: ['./form-section.component.scss'] + styleUrls: ['./form-section.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush }) -export class FormSectionComponent implements OnInit, OnChanges { +export class FormSectionComponent extends BaseComponent implements OnInit, OnChanges { //@Input() section: DatasetDescriptionSectionEditorModel; @Input() datasetProfileId: String; @@ -33,21 +34,27 @@ export class FormSectionComponent implements OnInit, OnChanges { @Output() askedToScroll = new EventEmitter(); - + tocentriesType = ToCEntryType; - @Input() TOCENTRY_ID_PREFIX=""; + @Input() TOCENTRY_ID_PREFIX = ""; constructor( public visibilityRulesService: VisibilityRulesService, - private formFocusService: FormFocusService - ) { } + private formFocusService: FormFocusService, + private changeDetector: ChangeDetectorRef + ) { + super(); + this.visibilityRulesService.getElementVisibilityMapObservable().pipe(takeUntil(this._destroyed)).subscribe(x => { + this.changeDetector.markForCheck(); + }); + } ngOnInit() { // if (this.section) { // this.form = this.visibilityRulesService.getFormGroup(this.section.id); // } - if(this.tocentry){//maybe not needed as well + if (this.tocentry) {//maybe not needed as well this.form = this.tocentry.form as FormGroup; } } @@ -75,30 +82,30 @@ export class FormSectionComponent implements OnInit, OnChanges { const compositeFieldToBeCloned = (this.form.get('compositeFields').get('' + fieldsetIndex) as FormGroup).getRawValue(); const multiplicityItemsArray = ((this.form.get('compositeFields').get('' + fieldsetIndex).get('multiplicityItems'))); - const ordinal = multiplicityItemsArray.length? multiplicityItemsArray.controls.reduce((ordinal, currentControl)=>{ + const ordinal = multiplicityItemsArray.length ? multiplicityItemsArray.controls.reduce((ordinal, currentControl) => { const currentOrdinal = currentControl.get('ordinal').value as number; - if(currentOrdinal>= ordinal){ - return currentOrdinal +1; + if (currentOrdinal >= ordinal) { + return currentOrdinal + 1; } return ordinal as number; - },0) : 0; - const idMappings = [] as {old: string, new: string}[]; - const compositeField: DatasetDescriptionCompositeFieldEditorModel = new DatasetDescriptionCompositeFieldEditorModel().cloneForMultiplicity(compositeFieldToBeCloned, ordinal ,idMappings); + }, 0) : 0; + const idMappings = [] as { old: string, new: string }[]; + const compositeField: DatasetDescriptionCompositeFieldEditorModel = new DatasetDescriptionCompositeFieldEditorModel().cloneForMultiplicity(compositeFieldToBeCloned, ordinal, idMappings); // ** COMPOSITE FIELD IS SHOWN OR HIDDEN FROM ANOTHER ELEMENT const compositeFieldVisibilityDependencies = this.visibilityRulesService.getVisibilityDependency(compositeFieldToBeCloned); - if(compositeFieldVisibilityDependencies && compositeFieldVisibilityDependencies.length){ + if (compositeFieldVisibilityDependencies && compositeFieldVisibilityDependencies.length) { - compositeFieldVisibilityDependencies.forEach(x =>{ + compositeFieldVisibilityDependencies.forEach(x => { const visRule: Rule = { targetField: compositeField.id, sourceField: x.sourceControlId, requiredValue: x.sourceControlValue, - type: '' + type: '' } this.visibilityRulesService.addNewRule(visRule); }); @@ -111,24 +118,24 @@ export class FormSectionComponent implements OnInit, OnChanges { - try{ - - if(dependency && dependency.length){ - + try { + + if (dependency && dependency.length) { + // * INNER VISIBILITY DEPENDENCIES // * IF INNER INPUT HIDES ANOTHER INNER INPUT - const innerDependency = compositeFieldToBeCloned.fields.reduce((innerD, currentElement )=>{ - - const innerDependecies = dependency.filter(d => d.sourceControlId === currentElement.id); - return[...innerD, ...innerDependecies]; - },[]) as VisibilityRuleSource[]; - - if(innerDependency.length){ + const innerDependency = compositeFieldToBeCloned.fields.reduce((innerD, currentElement) => { + + const innerDependecies = dependency.filter(d => d.sourceControlId === currentElement.id); + return [...innerD, ...innerDependecies]; + }, []) as VisibilityRuleSource[]; + + if (innerDependency.length) { //Build visibility source - const updatedRules = innerDependency.map(x => { - const newId = idMappings.find(y=> y.old === x.sourceControlId); - return {...x, sourceControlId: newId.new}; + const updatedRules = innerDependency.map(x => { + const newId = idMappings.find(y => y.old === x.sourceControlId); + return { ...x, sourceControlId: newId.new }; }); // const visRule: VisibilityRule = { // targetControlId: idMappings.find(x => x.old === element.id).new, @@ -140,33 +147,33 @@ export class FormSectionComponent implements OnInit, OnChanges { return { requiredValue: x.sourceControlValue, sourceField: x.sourceControlId, - targetField: idMappings.find(l=> l.old === element.id).new, + targetField: idMappings.find(l => l.old === element.id).new, type: '' } as Rule; }); - rules.forEach(rule =>{ + rules.forEach(rule => { this.visibilityRulesService.addNewRule(rule); }) - + // this.visibilityRulesService.appendVisibilityRule(visRule); } - + } - + // * OUTER DEPENDENCIES // * IF INNER INPUT HIDES OUTER INPUTS const innerIds = idMappings.map(x => x.old) as string[]; - const outerTargets = this.visibilityRulesService.getVisibilityTargets(element.id).filter( x=> !innerIds.includes(x)); + const outerTargets = this.visibilityRulesService.getVisibilityTargets(element.id).filter(x => !innerIds.includes(x)); - outerTargets.forEach(target =>{ + outerTargets.forEach(target => { const outerRules = (this.visibilityRulesService.getVisibilityDependency(target) as VisibilityRuleSource[]).filter(x => x.sourceControlId === element.id); const updatedRules = outerRules.map(x => { - return {...x ,sourceControlId: idMappings.find(y => y.old === element.id).new}; + return { ...x, sourceControlId: idMappings.find(y => y.old === element.id).new }; }); // const visRule: VisibilityRule = { @@ -175,7 +182,7 @@ export class FormSectionComponent implements OnInit, OnChanges { // } - const rules = updatedRules.map(x =>{ + const rules = updatedRules.map(x => { return { requiredValue: x.sourceControlValue, sourceField: x.sourceControlId, @@ -184,12 +191,12 @@ export class FormSectionComponent implements OnInit, OnChanges { } as Rule; }) - rules.forEach(rule =>{ + rules.forEach(rule => { this.visibilityRulesService.addNewRule(rule); }) // this.visibilityRulesService.appendVisibilityRule(visRule); - + }); @@ -198,16 +205,16 @@ export class FormSectionComponent implements OnInit, OnChanges { // * IF INNER INPUT IS HIDDEN BY OUTER INPUT - if(dependency && dependency.length){ + if (dependency && dependency.length) { const fieldsThatHideInnerElement = dependency.filter(x => !innerIds.includes(x.sourceControlId)); - - if( fieldsThatHideInnerElement.length){ - fieldsThatHideInnerElement.forEach(x =>{ + + if (fieldsThatHideInnerElement.length) { + fieldsThatHideInnerElement.forEach(x => { const visRule: Rule = { targetField: idMappings.find(l => l.old === element.id).new, sourceField: x.sourceControlId, requiredValue: x.sourceControlValue, - type: '' + type: '' } const shouldBeVisibile = this.visibilityRulesService.checkTargetVisibilityProvidedBySource(x.sourceControlId, element.id); this.visibilityRulesService.addNewRule(visRule, shouldBeVisibile); @@ -239,10 +246,10 @@ export class FormSectionComponent implements OnInit, OnChanges { deleteMultipeFieldFromCompositeFormGroup(compositeFildIndex: number, fildIndex: number) { const multiplicityItemsArray = ((this.form.get('compositeFields').get('' + compositeFildIndex).get('multiplicityItems'))); multiplicityItemsArray.removeAt(fildIndex); - multiplicityItemsArray.controls.forEach((control, i)=>{ - try{ + multiplicityItemsArray.controls.forEach((control, i) => { + try { control.get('ordinal').setValue(i); - }catch{ + } catch { throw 'Could not find ordinal'; } }); @@ -258,7 +265,7 @@ export class FormSectionComponent implements OnInit, OnChanges { - onAskedToScroll(id:string){ + onAskedToScroll(id: string) { this.panelExpanded = true; this.askedToScroll.emit(id); } diff --git a/dmp-frontend/src/app/ui/misc/dataset-description-form/visibility-rules/visibility-rules.service.ts b/dmp-frontend/src/app/ui/misc/dataset-description-form/visibility-rules/visibility-rules.service.ts index d902e51a3..d4797d354 100644 --- a/dmp-frontend/src/app/ui/misc/dataset-description-form/visibility-rules/visibility-rules.service.ts +++ b/dmp-frontend/src/app/ui/misc/dataset-description-form/visibility-rules/visibility-rules.service.ts @@ -2,7 +2,7 @@ import { ApplicationRef, Injectable, NgZone } from '@angular/core'; import { AbstractControl, FormArray, FormGroup } from '@angular/forms'; import { DatasetProfileFieldViewStyle } from '@app/core/common/enum/dataset-profile-field-view-style'; import { isNumeric } from '@app/utilities/enhancers/utils'; -import { Subject } from 'rxjs'; +import { Observable, Subject } from 'rxjs'; import { Rule } from '../../../../core/model/dataset-profile-definition/rule'; import { VisibilityRule } from './models/visibility-rule'; import { VisibilityRuleSource } from './models/visibility-rule-source'; @@ -16,7 +16,8 @@ export class VisibilityRulesService { private visibilityRuleContext: VisibilityRulesContext; private form: AbstractControl; - private elementVisibilityMap = new Map(); + public elementVisibilityMap = new Map(); + private elementVisibilityMapSubject = new Subject>(); private elementComputationalMap = new Map>(); /// keep saved the values of each form control validity value private _changeMade$ = new Subject(); @@ -28,6 +29,10 @@ export class VisibilityRulesService { } + getElementVisibilityMapObservable(): Observable> { + return this.elementVisibilityMapSubject.asObservable(); + } + public checkElementVisibility(id: string): boolean { if (this.visibilityRuleContext.rules.filter(item => item.targetControlId === id).length === 0) { return true; } return this.elementVisibilityMap.has(id) ? this.elementVisibilityMap.get(id) : false; @@ -41,8 +46,12 @@ export class VisibilityRulesService { } public updateValueAndVisibility(id: string, value: any) { + console.log('updateValueAndVisibility'); const visibilityRules = this.visibilityRuleContext.rules.filter(item => item.sourceVisibilityRules.filter(source => source.sourceControlId === id).length > 0); - visibilityRules.forEach(item => this.evaluateVisibility(item, value, id)); + if (visibilityRules.length > 0) { + visibilityRules.forEach(item => this.evaluateVisibility(item, value, id)); + this.elementVisibilityMapSubject.next(this.elementVisibilityMap); + } } private evaluateVisibility(visibilityRule: VisibilityRule, value: any, sourceId: string) {// source controlId is the same @@ -72,7 +81,7 @@ export class VisibilityRulesService { const shouldBeVisible = visibilityDependencySource.reduce((isVisible, x) => { const shouldBeHidden = value !== null && (this.parseValue(value) !== this.parseValue(x.sourceControlValue)); - return this.VISIBILITY_RULE_LOGIC === 'OR'? (isVisible || !shouldBeHidden) : (isVisible && !shouldBeHidden); + return this.VISIBILITY_RULE_LOGIC === 'OR' ? (isVisible || !shouldBeHidden) : (isVisible && !shouldBeHidden); // if(value !== null && ) }, this.VISIBILITY_RULE_LOGIC === 'AND'); visibilityMap.set(sourceId, shouldBeVisible); @@ -84,8 +93,10 @@ export class VisibilityRulesService { const isVisible = this._computeVisibility(targetId); this._emitChangesIfNeeded(targetId, isVisible); + const previousVisibility = this.elementVisibilityMap.get(targetId); this.elementVisibilityMap.set(targetId, isVisible); - if (!isVisible) { + + if (!isVisible && previousVisibility !== isVisible) { this.resetControlWithId(this.form, targetId); } @@ -220,11 +231,18 @@ export class VisibilityRulesService { private resetFieldFormGroup(formGroup: FormGroup) { const renderStyle = formGroup.getRawValue().viewStyle.renderStyle; if (renderStyle === DatasetProfileFieldViewStyle.Validation || renderStyle === DatasetProfileFieldViewStyle.DatasetIdentifier) { - formGroup.get('value').setValue({ identifier: '', type: '' }); + const value = { identifier: '', type: '' }; + if (formGroup.get('value').value != value) { + formGroup.get('value').setValue(value, { emitEvent: false }); + this.updateValueAndVisibility(formGroup.get('id').value, value); + } } else { - formGroup.get('value').setValue(formGroup.get('defaultValue').value ? this.parseValue(formGroup.get('defaultValue').value.value) : undefined); + const value = formGroup.get('defaultValue').value ? this.parseValue(formGroup.get('defaultValue').value.value) : undefined; + if (formGroup.get('value').value != value) { + formGroup.get('value').setValue(value, { emitEvent: false }); + this.updateValueAndVisibility(formGroup.get('id').value, value); + } } - } private resetCompositeFieldFormGroup(formGroup: FormGroup) { @@ -342,8 +360,8 @@ export class VisibilityRulesService { let visibilityMap = this.elementComputationalMap.get(targetId); - if(!visibilityMap){ - visibilityMap = new Map(); + if (!visibilityMap) { + visibilityMap = new Map(); this.elementComputationalMap.set(targetId, visibilityMap); } @@ -352,6 +370,7 @@ export class VisibilityRulesService { this._emitChangesIfNeeded(targetId, isVisible); this.elementVisibilityMap.set(targetId, isVisible); + this.elementVisibilityMapSubject.next(this.elementVisibilityMap); } @@ -359,10 +378,10 @@ export class VisibilityRulesService { * Check what sourceId hides or shows the target field * return true if no rule found */ - public checkTargetVisibilityProvidedBySource(sourceId: string, targetId: string): boolean{ - + public checkTargetVisibilityProvidedBySource(sourceId: string, targetId: string): boolean { + const computationalMap = this.elementComputationalMap.get(targetId); - if(computationalMap){ + if (computationalMap) { return !!computationalMap.get(sourceId); }