mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 10:04:11 +00:00
ensure dynamic components are updated when their inputs change
This commit is contained in:
@@ -3,10 +3,14 @@ import {
|
||||
ComponentFactoryResolver,
|
||||
ElementRef,
|
||||
Input,
|
||||
OnDestroy, OnInit,
|
||||
Output, ViewChild
|
||||
,
|
||||
EventEmitter
|
||||
OnDestroy,
|
||||
OnInit,
|
||||
Output,
|
||||
ViewChild,
|
||||
EventEmitter,
|
||||
SimpleChanges,
|
||||
OnChanges,
|
||||
ComponentRef
|
||||
} from '@angular/core';
|
||||
import { ListableObject } from '../listable-object.model';
|
||||
import { ViewMode } from '../../../../core/shared/view-mode.model';
|
||||
@@ -15,7 +19,7 @@ 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 } from '../../../empty.util';
|
||||
import { hasValue, isNotEmpty } from '../../../empty.util';
|
||||
import { Subscription } from 'rxjs/internal/Subscription';
|
||||
import { DSpaceObject } from '../../../../core/shared/dspace-object.model';
|
||||
import { take } from 'rxjs/operators';
|
||||
@@ -29,7 +33,7 @@ import { ThemeService } from '../../../theme-support/theme.service';
|
||||
/**
|
||||
* Component for determining what component to use depending on the item's entity type (dspace.entity.type)
|
||||
*/
|
||||
export class ListableObjectComponentLoaderComponent implements OnInit, OnDestroy {
|
||||
export class ListableObjectComponentLoaderComponent implements OnInit, OnChanges, OnDestroy {
|
||||
/**
|
||||
* The item or metadata to determine the component for
|
||||
*/
|
||||
@@ -107,6 +111,25 @@ export class ListableObjectComponentLoaderComponent implements OnInit, OnDestroy
|
||||
*/
|
||||
protected subs: Subscription[] = [];
|
||||
|
||||
/**
|
||||
* The reference to the dynamic component
|
||||
*/
|
||||
protected compRef: ComponentRef<Component>;
|
||||
|
||||
/**
|
||||
* The list of input and output names for the dynamic component
|
||||
*/
|
||||
protected inAndOutputNames: string[] = [
|
||||
'object',
|
||||
'index',
|
||||
'linkType',
|
||||
'listID',
|
||||
'showLabel',
|
||||
'context',
|
||||
'viewMode',
|
||||
'value',
|
||||
];
|
||||
|
||||
constructor(
|
||||
private componentFactoryResolver: ComponentFactoryResolver,
|
||||
private themeService: ThemeService
|
||||
@@ -120,6 +143,15 @@ export class ListableObjectComponentLoaderComponent implements OnInit, OnDestroy
|
||||
this.instantiateComponent(this.object);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.subs
|
||||
.filter((subscription) => hasValue(subscription))
|
||||
@@ -137,28 +169,22 @@ export class ListableObjectComponentLoaderComponent implements OnInit, OnDestroy
|
||||
const viewContainerRef = this.listableObjectDirective.viewContainerRef;
|
||||
viewContainerRef.clear();
|
||||
|
||||
const componentRef = viewContainerRef.createComponent(
|
||||
this.compRef = viewContainerRef.createComponent(
|
||||
componentFactory,
|
||||
0,
|
||||
undefined,
|
||||
[
|
||||
[this.badges.nativeElement],
|
||||
]);
|
||||
(componentRef.instance as any).object = object;
|
||||
(componentRef.instance as any).index = this.index;
|
||||
(componentRef.instance as any).linkType = this.linkType;
|
||||
(componentRef.instance as any).listID = this.listID;
|
||||
(componentRef.instance as any).showLabel = this.showLabel;
|
||||
(componentRef.instance as any).context = this.context;
|
||||
(componentRef.instance as any).viewMode = this.viewMode;
|
||||
(componentRef.instance as any).value = this.value;
|
||||
|
||||
if ((componentRef.instance as any).reloadedObject) {
|
||||
(componentRef.instance as any).reloadedObject.pipe(take(1)).subscribe((reloadedObject: DSpaceObject) => {
|
||||
this.connectInputsAndOutputs();
|
||||
|
||||
if ((this.compRef.instance as any).reloadedObject) {
|
||||
(this.compRef.instance as any).reloadedObject.pipe(take(1)).subscribe((reloadedObject: DSpaceObject) => {
|
||||
if (reloadedObject) {
|
||||
componentRef.destroy();
|
||||
this.compRef.destroy();
|
||||
this.object = reloadedObject;
|
||||
this.instantiateComponent(reloadedObject);
|
||||
this.connectInputsAndOutputs();
|
||||
this.contentChange.emit(reloadedObject);
|
||||
}
|
||||
});
|
||||
@@ -187,4 +213,17 @@ export class ListableObjectComponentLoaderComponent implements OnInit, OnDestroy
|
||||
context: Context): GenericConstructor<Component> {
|
||||
return getListableObjectComponent(renderTypes, viewMode, context, this.themeService.getThemeName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect the in and outputs of this component to the dynamic component,
|
||||
* to ensure they're in sync
|
||||
*/
|
||||
protected connectInputsAndOutputs(): void {
|
||||
if (isNotEmpty(this.inAndOutputNames) && hasValue(this.compRef) && hasValue(this.compRef.instance)) {
|
||||
this.inAndOutputNames.forEach((name: any) => {
|
||||
this.compRef.instance[name] = this[name];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user