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,
|
ComponentFactoryResolver,
|
||||||
ElementRef,
|
ElementRef,
|
||||||
Input,
|
Input,
|
||||||
OnDestroy, OnInit,
|
OnDestroy,
|
||||||
Output, ViewChild
|
OnInit,
|
||||||
,
|
Output,
|
||||||
EventEmitter
|
ViewChild,
|
||||||
|
EventEmitter,
|
||||||
|
SimpleChanges,
|
||||||
|
OnChanges,
|
||||||
|
ComponentRef
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
import { ListableObject } from '../listable-object.model';
|
import { ListableObject } from '../listable-object.model';
|
||||||
import { ViewMode } from '../../../../core/shared/view-mode.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 { GenericConstructor } from '../../../../core/shared/generic-constructor';
|
||||||
import { ListableObjectDirective } from './listable-object.directive';
|
import { ListableObjectDirective } from './listable-object.directive';
|
||||||
import { CollectionElementLinkType } from '../../collection-element-link.type';
|
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 { Subscription } from 'rxjs/internal/Subscription';
|
||||||
import { DSpaceObject } from '../../../../core/shared/dspace-object.model';
|
import { DSpaceObject } from '../../../../core/shared/dspace-object.model';
|
||||||
import { take } from 'rxjs/operators';
|
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)
|
* 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
|
* The item or metadata to determine the component for
|
||||||
*/
|
*/
|
||||||
@@ -107,6 +111,25 @@ export class ListableObjectComponentLoaderComponent implements OnInit, OnDestroy
|
|||||||
*/
|
*/
|
||||||
protected subs: Subscription[] = [];
|
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(
|
constructor(
|
||||||
private componentFactoryResolver: ComponentFactoryResolver,
|
private componentFactoryResolver: ComponentFactoryResolver,
|
||||||
private themeService: ThemeService
|
private themeService: ThemeService
|
||||||
@@ -120,6 +143,15 @@ export class ListableObjectComponentLoaderComponent implements OnInit, OnDestroy
|
|||||||
this.instantiateComponent(this.object);
|
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() {
|
ngOnDestroy() {
|
||||||
this.subs
|
this.subs
|
||||||
.filter((subscription) => hasValue(subscription))
|
.filter((subscription) => hasValue(subscription))
|
||||||
@@ -137,28 +169,22 @@ export class ListableObjectComponentLoaderComponent implements OnInit, OnDestroy
|
|||||||
const viewContainerRef = this.listableObjectDirective.viewContainerRef;
|
const viewContainerRef = this.listableObjectDirective.viewContainerRef;
|
||||||
viewContainerRef.clear();
|
viewContainerRef.clear();
|
||||||
|
|
||||||
const componentRef = viewContainerRef.createComponent(
|
this.compRef = viewContainerRef.createComponent(
|
||||||
componentFactory,
|
componentFactory,
|
||||||
0,
|
0,
|
||||||
undefined,
|
undefined,
|
||||||
[
|
[
|
||||||
[this.badges.nativeElement],
|
[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) {
|
this.connectInputsAndOutputs();
|
||||||
(componentRef.instance as any).reloadedObject.pipe(take(1)).subscribe((reloadedObject: DSpaceObject) => {
|
|
||||||
|
if ((this.compRef.instance as any).reloadedObject) {
|
||||||
|
(this.compRef.instance as any).reloadedObject.pipe(take(1)).subscribe((reloadedObject: DSpaceObject) => {
|
||||||
if (reloadedObject) {
|
if (reloadedObject) {
|
||||||
componentRef.destroy();
|
this.compRef.destroy();
|
||||||
this.object = reloadedObject;
|
this.object = reloadedObject;
|
||||||
this.instantiateComponent(reloadedObject);
|
this.connectInputsAndOutputs();
|
||||||
this.contentChange.emit(reloadedObject);
|
this.contentChange.emit(reloadedObject);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -187,4 +213,17 @@ export class ListableObjectComponentLoaderComponent implements OnInit, OnDestroy
|
|||||||
context: Context): GenericConstructor<Component> {
|
context: Context): GenericConstructor<Component> {
|
||||||
return getListableObjectComponent(renderTypes, viewMode, context, this.themeService.getThemeName());
|
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