From a4a0482d8852cd1bddc60661c27f3f7925e4a3d5 Mon Sep 17 00:00:00 2001 From: Alexandre Vryghem Date: Wed, 17 May 2023 18:10:32 +0200 Subject: [PATCH] 101577: Fixed ListableObjectComponentLoaderComponent not updating its @listableObjectComponent components ngOnChanges --- ...-object-component-loader.component.spec.ts | 2 +- ...table-object-component-loader.component.ts | 35 ++++++++++++++----- 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/src/app/shared/object-collection/shared/listable-object/listable-object-component-loader.component.spec.ts b/src/app/shared/object-collection/shared/listable-object/listable-object-component-loader.component.spec.ts index edf0b3ea7c..a932eb17a4 100644 --- a/src/app/shared/object-collection/shared/listable-object/listable-object-component-loader.component.spec.ts +++ b/src/app/shared/object-collection/shared/listable-object/listable-object-component-loader.component.spec.ts @@ -148,7 +148,7 @@ describe('ListableObjectComponentLoaderComponent', () => { (listableComponent as any).reloadedObject.emit(reloadedObject); tick(); - expect((comp as any).instantiateComponent).toHaveBeenCalledWith(reloadedObject); + expect((comp as any).instantiateComponent).toHaveBeenCalledWith(reloadedObject, undefined); })); it('should re-emit it as a contentChange', fakeAsync(() => { diff --git a/src/app/shared/object-collection/shared/listable-object/listable-object-component-loader.component.ts b/src/app/shared/object-collection/shared/listable-object/listable-object-component-loader.component.ts index 8adbcbeec3..6d6048afa3 100644 --- a/src/app/shared/object-collection/shared/listable-object/listable-object-component-loader.component.ts +++ b/src/app/shared/object-collection/shared/listable-object/listable-object-component-loader.component.ts @@ -19,8 +19,8 @@ import { getListableObjectComponent } from './listable-object.decorator'; import { GenericConstructor } from '../../../../core/shared/generic-constructor'; import { ListableObjectDirective } from './listable-object.directive'; import { CollectionElementLinkType } from '../../collection-element-link.type'; -import { hasValue, isNotEmpty } from '../../../empty.util'; -import { Subscription } from 'rxjs'; +import { hasValue, isNotEmpty, hasNoValue } from '../../../empty.util'; +import { Subscription, combineLatest, of as observableOf, Observable } from 'rxjs'; import { DSpaceObject } from '../../../../core/shared/dspace-object.model'; import { take } from 'rxjs/operators'; import { ThemeService } from '../../../theme-support/theme.service'; @@ -147,8 +147,18 @@ export class ListableObjectComponentLoaderComponent implements OnInit, OnChanges * Whenever the inputs change, update the inputs of the dynamic component */ ngOnChanges(changes: SimpleChanges): void { - if (this.inAndOutputNames.some((name: any) => hasValue(changes[name]))) { - this.connectInputsAndOutputs(); + if (hasNoValue(this.compRef)) { + // sometimes the component has not been initialized yet, so it first needs to be initialized + // before being called again + this.instantiateComponent(this.object, changes); + } else { + // if an input or output has changed + if (this.inAndOutputNames.some((name: any) => hasValue(changes[name]))) { + this.connectInputsAndOutputs(); + if (this.compRef?.instance && 'ngOnChanges' in this.compRef.instance) { + (this.compRef.instance as any).ngOnChanges(changes); + } + } } } @@ -158,7 +168,7 @@ export class ListableObjectComponentLoaderComponent implements OnInit, OnChanges .forEach((subscription) => subscription.unsubscribe()); } - private instantiateComponent(object) { + private instantiateComponent(object: ListableObject, changes?: SimpleChanges): void { this.initBadges(); @@ -177,14 +187,21 @@ export class ListableObjectComponentLoaderComponent implements OnInit, OnChanges [this.badges.nativeElement], ]); - this.connectInputsAndOutputs(); + if (hasValue(changes)) { + this.ngOnChanges(changes); + } else { + this.connectInputsAndOutputs(); + } if ((this.compRef.instance as any).reloadedObject) { - (this.compRef.instance as any).reloadedObject.pipe(take(1)).subscribe((reloadedObject: DSpaceObject) => { + combineLatest([ + observableOf(changes), + (this.compRef.instance as any).reloadedObject.pipe(take(1)) as Observable, + ]).subscribe(([simpleChanges, reloadedObject]: [SimpleChanges, DSpaceObject]) => { if (reloadedObject) { this.compRef.destroy(); this.object = reloadedObject; - this.instantiateComponent(reloadedObject); + this.instantiateComponent(reloadedObject, simpleChanges); this.contentChange.emit(reloadedObject); } }); @@ -220,7 +237,7 @@ export class ListableObjectComponentLoaderComponent implements OnInit, OnChanges */ protected connectInputsAndOutputs(): void { if (isNotEmpty(this.inAndOutputNames) && hasValue(this.compRef) && hasValue(this.compRef.instance)) { - this.inAndOutputNames.forEach((name: any) => { + this.inAndOutputNames.filter((name: any) => this[name] !== undefined).forEach((name: any) => { this.compRef.instance[name] = this[name]; }); }