mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-10 11:33:04 +00:00
101577: Fixed MetadataRepresentationLoaderComponent not updating its @metadataRepresentationComponent components ngOnChanges
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { Component, ComponentFactoryResolver, Inject, Input, OnInit, ViewChild } from '@angular/core';
|
||||
import { Component, ComponentFactoryResolver, Inject, Input, OnInit, ViewChild, OnChanges, SimpleChanges, ComponentRef, ViewContainerRef, ComponentFactory } from '@angular/core';
|
||||
import {
|
||||
MetadataRepresentation,
|
||||
MetadataRepresentationType
|
||||
@@ -8,19 +8,17 @@ import { Context } from '../../core/shared/context.model';
|
||||
import { GenericConstructor } from '../../core/shared/generic-constructor';
|
||||
import { MetadataRepresentationListElementComponent } from '../object-list/metadata-representation-list-element/metadata-representation-list-element.component';
|
||||
import { MetadataRepresentationDirective } from './metadata-representation.directive';
|
||||
import { hasValue } from '../empty.util';
|
||||
import { hasValue, isNotEmpty, hasNoValue } from '../empty.util';
|
||||
import { ThemeService } from '../theme-support/theme.service';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-metadata-representation-loader',
|
||||
// styleUrls: ['./metadata-representation-loader.component.scss'],
|
||||
templateUrl: './metadata-representation-loader.component.html'
|
||||
})
|
||||
/**
|
||||
* Component for determining what component to use depending on the item's entity type (dspace.entity.type), its metadata representation and, optionally, its context
|
||||
*/
|
||||
export class MetadataRepresentationLoaderComponent implements OnInit {
|
||||
private componentRefInstance: MetadataRepresentationListElementComponent;
|
||||
export class MetadataRepresentationLoaderComponent implements OnInit, OnChanges {
|
||||
|
||||
/**
|
||||
* The item or metadata to determine the component for
|
||||
@@ -31,8 +29,8 @@ export class MetadataRepresentationLoaderComponent implements OnInit {
|
||||
}
|
||||
@Input() set mdRepresentation(nextValue: MetadataRepresentation) {
|
||||
this._mdRepresentation = nextValue;
|
||||
if (hasValue(this.componentRefInstance)) {
|
||||
this.componentRefInstance.metadataRepresentation = nextValue;
|
||||
if (hasValue(this.compRef?.instance)) {
|
||||
this.compRef.instance.mdRepresentation = nextValue;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,6 +44,16 @@ export class MetadataRepresentationLoaderComponent implements OnInit {
|
||||
*/
|
||||
@ViewChild(MetadataRepresentationDirective, {static: true}) mdRepDirective: MetadataRepresentationDirective;
|
||||
|
||||
/**
|
||||
* The reference to the dynamic component
|
||||
*/
|
||||
protected compRef: ComponentRef<MetadataRepresentationListElementComponent>;
|
||||
|
||||
protected inAndOutputNames: (keyof this)[] = [
|
||||
'context',
|
||||
'mdRepresentation',
|
||||
];
|
||||
|
||||
constructor(
|
||||
private componentFactoryResolver: ComponentFactoryResolver,
|
||||
private themeService: ThemeService,
|
||||
@@ -57,14 +65,41 @@ export class MetadataRepresentationLoaderComponent implements OnInit {
|
||||
* Set up the dynamic child component
|
||||
*/
|
||||
ngOnInit(): void {
|
||||
const componentFactory = this.componentFactoryResolver.resolveComponentFactory(this.getComponent());
|
||||
this.instantiateComponent();
|
||||
}
|
||||
|
||||
const viewContainerRef = this.mdRepDirective.viewContainerRef;
|
||||
/**
|
||||
* Whenever the inputs change, update the inputs of the dynamic component
|
||||
*/
|
||||
ngOnChanges(changes: SimpleChanges): void {
|
||||
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(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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private instantiateComponent(changes?: SimpleChanges): void {
|
||||
const componentFactory: ComponentFactory<MetadataRepresentationListElementComponent> = this.componentFactoryResolver.resolveComponentFactory(this.getComponent());
|
||||
|
||||
const viewContainerRef: ViewContainerRef = this.mdRepDirective.viewContainerRef;
|
||||
viewContainerRef.clear();
|
||||
|
||||
const componentRef = viewContainerRef.createComponent(componentFactory);
|
||||
this.componentRefInstance = componentRef.instance as MetadataRepresentationListElementComponent;
|
||||
this.componentRefInstance.metadataRepresentation = this.mdRepresentation;
|
||||
this.compRef = viewContainerRef.createComponent(componentFactory);
|
||||
|
||||
if (hasValue(changes)) {
|
||||
this.ngOnChanges(changes);
|
||||
} else {
|
||||
this.connectInputsAndOutputs();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -74,4 +109,16 @@ export class MetadataRepresentationLoaderComponent implements OnInit {
|
||||
private getComponent(): GenericConstructor<MetadataRepresentationListElementComponent> {
|
||||
return this.getMetadataRepresentationComponent(this.mdRepresentation.itemType, this.mdRepresentation.representationType, this.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.filter((name: any) => this[name] !== undefined).forEach((name: any) => {
|
||||
this.compRef.instance[name] = this[name];
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user