mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 10:04:11 +00:00
101577: Fixed MetadataRepresentationLoaderComponent not updating its @metadataRepresentationComponent components ngOnChanges
This commit is contained in:
@@ -1,12 +1,12 @@
|
|||||||
<ng-template #descTemplate>
|
<ng-template #descTemplate>
|
||||||
<span class="text-muted">
|
<span class="text-muted">
|
||||||
<span class="item-list-job-title">
|
<span class="item-list-job-title">
|
||||||
<span [innerHTML]="metadataRepresentation.firstMetadataValue(['dc.description'])"></span>
|
<span [innerHTML]="mdRepresentation.firstMetadataValue(['dc.description'])"></span>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
<ds-truncatable [id]="metadataRepresentation.id">
|
<ds-truncatable [id]="mdRepresentation.id">
|
||||||
<a [routerLink]="[itemPageRoute]"
|
<a [routerLink]="[itemPageRoute]"
|
||||||
[innerHTML]="metadataRepresentation.getValue()"
|
[innerHTML]="mdRepresentation.getValue()"
|
||||||
[ngbTooltip]="metadataRepresentation.allMetadata(['dc.description']).length > 0 ? descTemplate : null"></a>
|
[ngbTooltip]="mdRepresentation.allMetadata(['dc.description']).length > 0 ? descTemplate : null"></a>
|
||||||
</ds-truncatable>
|
</ds-truncatable>
|
||||||
|
@@ -34,7 +34,7 @@ describe('OrgUnitItemMetadataListElementComponent', () => {
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
fixture = TestBed.createComponent(OrgUnitItemMetadataListElementComponent);
|
fixture = TestBed.createComponent(OrgUnitItemMetadataListElementComponent);
|
||||||
comp = fixture.componentInstance;
|
comp = fixture.componentInstance;
|
||||||
comp.metadataRepresentation = mockItemMetadataRepresentation;
|
comp.mdRepresentation = mockItemMetadataRepresentation;
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@@ -1,15 +1,15 @@
|
|||||||
<ng-template #descTemplate>
|
<ng-template #descTemplate>
|
||||||
<span class="text-muted">
|
<span class="text-muted">
|
||||||
<span *ngIf="metadataRepresentation.allMetadata(['person.jobTitle']).length > 0"
|
<span *ngIf="mdRepresentation.allMetadata(['person.jobTitle']).length > 0"
|
||||||
class="item-list-job-title">
|
class="item-list-job-title">
|
||||||
<span *ngFor="let value of metadataRepresentation.allMetadataValues(['person.jobTitle']); let last=last;">
|
<span *ngFor="let value of mdRepresentation.allMetadataValues(['person.jobTitle']); let last=last;">
|
||||||
<span [innerHTML]="value"><span [innerHTML]="value"></span></span>
|
<span [innerHTML]="value"><span [innerHTML]="value"></span></span>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
<ds-truncatable [id]="metadataRepresentation.id">
|
<ds-truncatable [id]="mdRepresentation.id">
|
||||||
<a [routerLink]="[itemPageRoute]"
|
<a [routerLink]="[itemPageRoute]"
|
||||||
[innerHTML]="metadataRepresentation.getValue()"
|
[innerHTML]="mdRepresentation.getValue()"
|
||||||
[ngbTooltip]="metadataRepresentation.allMetadata(['person.jobTitle']).length > 0 ? descTemplate : null"></a>
|
[ngbTooltip]="mdRepresentation.allMetadata(['person.jobTitle']).length > 0 ? descTemplate : null"></a>
|
||||||
</ds-truncatable>
|
</ds-truncatable>
|
||||||
|
@@ -36,7 +36,7 @@ describe('PersonItemMetadataListElementComponent', () => {
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
fixture = TestBed.createComponent(PersonItemMetadataListElementComponent);
|
fixture = TestBed.createComponent(PersonItemMetadataListElementComponent);
|
||||||
comp = fixture.componentInstance;
|
comp = fixture.componentInstance;
|
||||||
comp.metadataRepresentation = mockItemMetadataRepresentation;
|
comp.mdRepresentation = mockItemMetadataRepresentation;
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@@ -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 {
|
import {
|
||||||
MetadataRepresentation,
|
MetadataRepresentation,
|
||||||
MetadataRepresentationType
|
MetadataRepresentationType
|
||||||
@@ -8,19 +8,17 @@ import { Context } from '../../core/shared/context.model';
|
|||||||
import { GenericConstructor } from '../../core/shared/generic-constructor';
|
import { GenericConstructor } from '../../core/shared/generic-constructor';
|
||||||
import { MetadataRepresentationListElementComponent } from '../object-list/metadata-representation-list-element/metadata-representation-list-element.component';
|
import { MetadataRepresentationListElementComponent } from '../object-list/metadata-representation-list-element/metadata-representation-list-element.component';
|
||||||
import { MetadataRepresentationDirective } from './metadata-representation.directive';
|
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';
|
import { ThemeService } from '../theme-support/theme.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ds-metadata-representation-loader',
|
selector: 'ds-metadata-representation-loader',
|
||||||
// styleUrls: ['./metadata-representation-loader.component.scss'],
|
|
||||||
templateUrl: './metadata-representation-loader.component.html'
|
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
|
* 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 {
|
export class MetadataRepresentationLoaderComponent implements OnInit, OnChanges {
|
||||||
private componentRefInstance: MetadataRepresentationListElementComponent;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The item or metadata to determine the component for
|
* The item or metadata to determine the component for
|
||||||
@@ -31,8 +29,8 @@ export class MetadataRepresentationLoaderComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
@Input() set mdRepresentation(nextValue: MetadataRepresentation) {
|
@Input() set mdRepresentation(nextValue: MetadataRepresentation) {
|
||||||
this._mdRepresentation = nextValue;
|
this._mdRepresentation = nextValue;
|
||||||
if (hasValue(this.componentRefInstance)) {
|
if (hasValue(this.compRef?.instance)) {
|
||||||
this.componentRefInstance.metadataRepresentation = nextValue;
|
this.compRef.instance.mdRepresentation = nextValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,6 +44,16 @@ export class MetadataRepresentationLoaderComponent implements OnInit {
|
|||||||
*/
|
*/
|
||||||
@ViewChild(MetadataRepresentationDirective, {static: true}) mdRepDirective: MetadataRepresentationDirective;
|
@ViewChild(MetadataRepresentationDirective, {static: true}) mdRepDirective: MetadataRepresentationDirective;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The reference to the dynamic component
|
||||||
|
*/
|
||||||
|
protected compRef: ComponentRef<MetadataRepresentationListElementComponent>;
|
||||||
|
|
||||||
|
protected inAndOutputNames: (keyof this)[] = [
|
||||||
|
'context',
|
||||||
|
'mdRepresentation',
|
||||||
|
];
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private componentFactoryResolver: ComponentFactoryResolver,
|
private componentFactoryResolver: ComponentFactoryResolver,
|
||||||
private themeService: ThemeService,
|
private themeService: ThemeService,
|
||||||
@@ -57,14 +65,41 @@ export class MetadataRepresentationLoaderComponent implements OnInit {
|
|||||||
* Set up the dynamic child component
|
* Set up the dynamic child component
|
||||||
*/
|
*/
|
||||||
ngOnInit(): void {
|
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();
|
viewContainerRef.clear();
|
||||||
|
|
||||||
const componentRef = viewContainerRef.createComponent(componentFactory);
|
this.compRef = viewContainerRef.createComponent(componentFactory);
|
||||||
this.componentRefInstance = componentRef.instance as MetadataRepresentationListElementComponent;
|
|
||||||
this.componentRefInstance.metadataRepresentation = this.mdRepresentation;
|
if (hasValue(changes)) {
|
||||||
|
this.ngOnChanges(changes);
|
||||||
|
} else {
|
||||||
|
this.connectInputsAndOutputs();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -74,4 +109,16 @@ export class MetadataRepresentationLoaderComponent implements OnInit {
|
|||||||
private getComponent(): GenericConstructor<MetadataRepresentationListElementComponent> {
|
private getComponent(): GenericConstructor<MetadataRepresentationListElementComponent> {
|
||||||
return this.getMetadataRepresentationComponent(this.mdRepresentation.itemType, this.mdRepresentation.representationType, this.context, this.themeService.getThemeName());
|
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];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1 +1 @@
|
|||||||
<ds-listable-object-component-loader [object]="metadataRepresentation" [viewMode]="viewMode"></ds-listable-object-component-loader>
|
<ds-listable-object-component-loader [object]="mdRepresentation" [viewMode]="viewMode"></ds-listable-object-component-loader>
|
||||||
|
@@ -23,7 +23,7 @@ describe('ItemMetadataListElementComponent', () => {
|
|||||||
beforeEach(waitForAsync(() => {
|
beforeEach(waitForAsync(() => {
|
||||||
fixture = TestBed.createComponent(ItemMetadataListElementComponent);
|
fixture = TestBed.createComponent(ItemMetadataListElementComponent);
|
||||||
comp = fixture.componentInstance;
|
comp = fixture.componentInstance;
|
||||||
comp.metadataRepresentation = mockItemMetadataRepresentation;
|
comp.mdRepresentation = mockItemMetadataRepresentation;
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import { MetadataRepresentationListElementComponent } from '../metadata-representation-list-element.component';
|
import { MetadataRepresentationListElementComponent } from '../metadata-representation-list-element.component';
|
||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit, Input } from '@angular/core';
|
||||||
import { ItemMetadataRepresentation } from '../../../../core/shared/metadata-representation/item/item-metadata-representation.model';
|
import { ItemMetadataRepresentation } from '../../../../core/shared/metadata-representation/item/item-metadata-representation.model';
|
||||||
import { getItemPageRoute } from '../../../../item-page/item-page-routing-paths';
|
import { getItemPageRoute } from '../../../../item-page/item-page-routing-paths';
|
||||||
|
|
||||||
@@ -11,7 +11,7 @@ import { getItemPageRoute } from '../../../../item-page/item-page-routing-paths'
|
|||||||
* An abstract class for displaying a single ItemMetadataRepresentation
|
* An abstract class for displaying a single ItemMetadataRepresentation
|
||||||
*/
|
*/
|
||||||
export class ItemMetadataRepresentationListElementComponent extends MetadataRepresentationListElementComponent implements OnInit {
|
export class ItemMetadataRepresentationListElementComponent extends MetadataRepresentationListElementComponent implements OnInit {
|
||||||
metadataRepresentation: ItemMetadataRepresentation;
|
@Input() mdRepresentation: ItemMetadataRepresentation;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Route to the item's page
|
* Route to the item's page
|
||||||
@@ -19,6 +19,6 @@ export class ItemMetadataRepresentationListElementComponent extends MetadataRepr
|
|||||||
itemPageRoute: string;
|
itemPageRoute: string;
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.itemPageRoute = getItemPageRoute(this.metadataRepresentation);
|
this.itemPageRoute = getItemPageRoute(this.mdRepresentation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
import { Component } from '@angular/core';
|
import { Component, Input } from '@angular/core';
|
||||||
import { MetadataRepresentation } from '../../../core/shared/metadata-representation/metadata-representation.model';
|
import { MetadataRepresentation } from '../../../core/shared/metadata-representation/metadata-representation.model';
|
||||||
|
import { Context } from '../../../core/shared/context.model';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ds-metadata-representation-list-element',
|
selector: 'ds-metadata-representation-list-element',
|
||||||
@@ -9,8 +10,13 @@ import { MetadataRepresentation } from '../../../core/shared/metadata-representa
|
|||||||
* An abstract class for displaying a single MetadataRepresentation
|
* An abstract class for displaying a single MetadataRepresentation
|
||||||
*/
|
*/
|
||||||
export class MetadataRepresentationListElementComponent {
|
export class MetadataRepresentationListElementComponent {
|
||||||
|
/**
|
||||||
|
* The optional context
|
||||||
|
*/
|
||||||
|
@Input() context: Context;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The metadata representation of this component
|
* The metadata representation of this component
|
||||||
*/
|
*/
|
||||||
metadataRepresentation: MetadataRepresentation;
|
@Input() mdRepresentation: MetadataRepresentation;
|
||||||
}
|
}
|
||||||
|
@@ -1,3 +1,3 @@
|
|||||||
<div>
|
<div>
|
||||||
<span class="dont-break-out">{{metadataRepresentation.getValue()}}</span>
|
<span class="dont-break-out">{{mdRepresentation.getValue()}}</span>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -25,7 +25,7 @@ describe('PlainTextMetadataListElementComponent', () => {
|
|||||||
beforeEach(waitForAsync(() => {
|
beforeEach(waitForAsync(() => {
|
||||||
fixture = TestBed.createComponent(PlainTextMetadataListElementComponent);
|
fixture = TestBed.createComponent(PlainTextMetadataListElementComponent);
|
||||||
comp = fixture.componentInstance;
|
comp = fixture.componentInstance;
|
||||||
comp.metadataRepresentation = mockMetadataRepresentation;
|
comp.mdRepresentation = mockMetadataRepresentation;
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user