Skip to content

Commit 2ca91fd

Browse files
101577: Fixed MetadataRepresentationLoaderComponent not updating its @metadataRepresentationComponent components ngOnChanges
1 parent a4a0482 commit 2ca91fd

11 files changed

+85
-32
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
<ng-template #descTemplate>
22
<span class="text-muted">
33
<span class="item-list-job-title">
4-
<span [innerHTML]="metadataRepresentation.firstMetadataValue(['dc.description'])"></span>
4+
<span [innerHTML]="mdRepresentation.firstMetadataValue(['dc.description'])"></span>
55
</span>
66
</span>
77
</ng-template>
8-
<ds-truncatable [id]="metadataRepresentation.id">
8+
<ds-truncatable [id]="mdRepresentation.id">
99
<a [routerLink]="[itemPageRoute]"
10-
[innerHTML]="metadataRepresentation.getValue()"
11-
[ngbTooltip]="metadataRepresentation.allMetadata(['dc.description']).length > 0 ? descTemplate : null"></a>
10+
[innerHTML]="mdRepresentation.getValue()"
11+
[ngbTooltip]="mdRepresentation.allMetadata(['dc.description']).length > 0 ? descTemplate : null"></a>
1212
</ds-truncatable>

src/app/entity-groups/research-entities/metadata-representations/org-unit/org-unit-item-metadata-list-element.component.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ describe('OrgUnitItemMetadataListElementComponent', () => {
3434
beforeEach(() => {
3535
fixture = TestBed.createComponent(OrgUnitItemMetadataListElementComponent);
3636
comp = fixture.componentInstance;
37-
comp.metadataRepresentation = mockItemMetadataRepresentation;
37+
comp.mdRepresentation = mockItemMetadataRepresentation;
3838
fixture.detectChanges();
3939
});
4040

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
<ng-template #descTemplate>
22
<span class="text-muted">
3-
<span *ngIf="metadataRepresentation.allMetadata(['person.jobTitle']).length > 0"
3+
<span *ngIf="mdRepresentation.allMetadata(['person.jobTitle']).length > 0"
44
class="item-list-job-title">
5-
<span *ngFor="let value of metadataRepresentation.allMetadataValues(['person.jobTitle']); let last=last;">
5+
<span *ngFor="let value of mdRepresentation.allMetadataValues(['person.jobTitle']); let last=last;">
66
<span [innerHTML]="value"><span [innerHTML]="value"></span></span>
77
</span>
88
</span>
99
</span>
1010
</ng-template>
11-
<ds-truncatable [id]="metadataRepresentation.id">
11+
<ds-truncatable [id]="mdRepresentation.id">
1212
<a [routerLink]="[itemPageRoute]"
13-
[innerHTML]="metadataRepresentation.getValue()"
14-
[ngbTooltip]="metadataRepresentation.allMetadata(['person.jobTitle']).length > 0 ? descTemplate : null"></a>
13+
[innerHTML]="mdRepresentation.getValue()"
14+
[ngbTooltip]="mdRepresentation.allMetadata(['person.jobTitle']).length > 0 ? descTemplate : null"></a>
1515
</ds-truncatable>

src/app/entity-groups/research-entities/metadata-representations/person/person-item-metadata-list-element.component.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ describe('PersonItemMetadataListElementComponent', () => {
3636
beforeEach(() => {
3737
fixture = TestBed.createComponent(PersonItemMetadataListElementComponent);
3838
comp = fixture.componentInstance;
39-
comp.metadataRepresentation = mockItemMetadataRepresentation;
39+
comp.mdRepresentation = mockItemMetadataRepresentation;
4040
fixture.detectChanges();
4141
});
4242

src/app/shared/metadata-representation/metadata-representation-loader.component.ts

Lines changed: 59 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Component, ComponentFactoryResolver, Inject, Input, OnInit, ViewChild } from '@angular/core';
1+
import { Component, ComponentFactoryResolver, Inject, Input, OnInit, ViewChild, OnChanges, SimpleChanges, ComponentRef, ViewContainerRef, ComponentFactory } from '@angular/core';
22
import {
33
MetadataRepresentation,
44
MetadataRepresentationType
@@ -8,19 +8,17 @@ import { Context } from '../../core/shared/context.model';
88
import { GenericConstructor } from '../../core/shared/generic-constructor';
99
import { MetadataRepresentationListElementComponent } from '../object-list/metadata-representation-list-element/metadata-representation-list-element.component';
1010
import { MetadataRepresentationDirective } from './metadata-representation.directive';
11-
import { hasValue } from '../empty.util';
11+
import { hasValue, isNotEmpty, hasNoValue } from '../empty.util';
1212
import { ThemeService } from '../theme-support/theme.service';
1313

1414
@Component({
1515
selector: 'ds-metadata-representation-loader',
16-
// styleUrls: ['./metadata-representation-loader.component.scss'],
1716
templateUrl: './metadata-representation-loader.component.html'
1817
})
1918
/**
2019
* Component for determining what component to use depending on the item's entity type (dspace.entity.type), its metadata representation and, optionally, its context
2120
*/
22-
export class MetadataRepresentationLoaderComponent implements OnInit {
23-
private componentRefInstance: MetadataRepresentationListElementComponent;
21+
export class MetadataRepresentationLoaderComponent implements OnInit, OnChanges {
2422

2523
/**
2624
* The item or metadata to determine the component for
@@ -31,8 +29,8 @@ export class MetadataRepresentationLoaderComponent implements OnInit {
3129
}
3230
@Input() set mdRepresentation(nextValue: MetadataRepresentation) {
3331
this._mdRepresentation = nextValue;
34-
if (hasValue(this.componentRefInstance)) {
35-
this.componentRefInstance.metadataRepresentation = nextValue;
32+
if (hasValue(this.compRef?.instance)) {
33+
this.compRef.instance.mdRepresentation = nextValue;
3634
}
3735
}
3836

@@ -46,6 +44,16 @@ export class MetadataRepresentationLoaderComponent implements OnInit {
4644
*/
4745
@ViewChild(MetadataRepresentationDirective, {static: true}) mdRepDirective: MetadataRepresentationDirective;
4846

47+
/**
48+
* The reference to the dynamic component
49+
*/
50+
protected compRef: ComponentRef<MetadataRepresentationListElementComponent>;
51+
52+
protected inAndOutputNames: (keyof this)[] = [
53+
'context',
54+
'mdRepresentation',
55+
];
56+
4957
constructor(
5058
private componentFactoryResolver: ComponentFactoryResolver,
5159
private themeService: ThemeService,
@@ -57,14 +65,41 @@ export class MetadataRepresentationLoaderComponent implements OnInit {
5765
* Set up the dynamic child component
5866
*/
5967
ngOnInit(): void {
60-
const componentFactory = this.componentFactoryResolver.resolveComponentFactory(this.getComponent());
68+
this.instantiateComponent();
69+
}
70+
71+
/**
72+
* Whenever the inputs change, update the inputs of the dynamic component
73+
*/
74+
ngOnChanges(changes: SimpleChanges): void {
75+
if (hasNoValue(this.compRef)) {
76+
// sometimes the component has not been initialized yet, so it first needs to be initialized
77+
// before being called again
78+
this.instantiateComponent(changes);
79+
} else {
80+
// if an input or output has changed
81+
if (this.inAndOutputNames.some((name: any) => hasValue(changes[name]))) {
82+
this.connectInputsAndOutputs();
83+
if (this.compRef?.instance && 'ngOnChanges' in this.compRef.instance) {
84+
(this.compRef.instance as any).ngOnChanges(changes);
85+
}
86+
}
87+
}
88+
}
89+
90+
private instantiateComponent(changes?: SimpleChanges): void {
91+
const componentFactory: ComponentFactory<MetadataRepresentationListElementComponent> = this.componentFactoryResolver.resolveComponentFactory(this.getComponent());
6192

62-
const viewContainerRef = this.mdRepDirective.viewContainerRef;
93+
const viewContainerRef: ViewContainerRef = this.mdRepDirective.viewContainerRef;
6394
viewContainerRef.clear();
6495

65-
const componentRef = viewContainerRef.createComponent(componentFactory);
66-
this.componentRefInstance = componentRef.instance as MetadataRepresentationListElementComponent;
67-
this.componentRefInstance.metadataRepresentation = this.mdRepresentation;
96+
this.compRef = viewContainerRef.createComponent(componentFactory);
97+
98+
if (hasValue(changes)) {
99+
this.ngOnChanges(changes);
100+
} else {
101+
this.connectInputsAndOutputs();
102+
}
68103
}
69104

70105
/**
@@ -74,4 +109,16 @@ export class MetadataRepresentationLoaderComponent implements OnInit {
74109
private getComponent(): GenericConstructor<MetadataRepresentationListElementComponent> {
75110
return this.getMetadataRepresentationComponent(this.mdRepresentation.itemType, this.mdRepresentation.representationType, this.context, this.themeService.getThemeName());
76111
}
112+
113+
/**
114+
* Connect the in and outputs of this component to the dynamic component,
115+
* to ensure they're in sync
116+
*/
117+
protected connectInputsAndOutputs(): void {
118+
if (isNotEmpty(this.inAndOutputNames) && hasValue(this.compRef) && hasValue(this.compRef.instance)) {
119+
this.inAndOutputNames.filter((name: any) => this[name] !== undefined).forEach((name: any) => {
120+
this.compRef.instance[name] = this[name];
121+
});
122+
}
123+
}
77124
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
<ds-listable-object-component-loader [object]="metadataRepresentation" [viewMode]="viewMode"></ds-listable-object-component-loader>
1+
<ds-listable-object-component-loader [object]="mdRepresentation" [viewMode]="viewMode"></ds-listable-object-component-loader>

src/app/shared/object-list/metadata-representation-list-element/item/item-metadata-list-element.component.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ describe('ItemMetadataListElementComponent', () => {
2323
beforeEach(waitForAsync(() => {
2424
fixture = TestBed.createComponent(ItemMetadataListElementComponent);
2525
comp = fixture.componentInstance;
26-
comp.metadataRepresentation = mockItemMetadataRepresentation;
26+
comp.mdRepresentation = mockItemMetadataRepresentation;
2727
fixture.detectChanges();
2828
}));
2929

src/app/shared/object-list/metadata-representation-list-element/item/item-metadata-representation-list-element.component.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { MetadataRepresentationListElementComponent } from '../metadata-representation-list-element.component';
2-
import { Component, OnInit } from '@angular/core';
2+
import { Component, OnInit, Input } from '@angular/core';
33
import { ItemMetadataRepresentation } from '../../../../core/shared/metadata-representation/item/item-metadata-representation.model';
44
import { getItemPageRoute } from '../../../../item-page/item-page-routing-paths';
55

@@ -11,14 +11,14 @@ import { getItemPageRoute } from '../../../../item-page/item-page-routing-paths'
1111
* An abstract class for displaying a single ItemMetadataRepresentation
1212
*/
1313
export class ItemMetadataRepresentationListElementComponent extends MetadataRepresentationListElementComponent implements OnInit {
14-
metadataRepresentation: ItemMetadataRepresentation;
14+
@Input() mdRepresentation: ItemMetadataRepresentation;
1515

1616
/**
1717
* Route to the item's page
1818
*/
1919
itemPageRoute: string;
2020

2121
ngOnInit(): void {
22-
this.itemPageRoute = getItemPageRoute(this.metadataRepresentation);
22+
this.itemPageRoute = getItemPageRoute(this.mdRepresentation);
2323
}
2424
}
Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
import { Component } from '@angular/core';
1+
import { Component, Input } from '@angular/core';
22
import { MetadataRepresentation } from '../../../core/shared/metadata-representation/metadata-representation.model';
3+
import { Context } from '../../../core/shared/context.model';
34

45
@Component({
56
selector: 'ds-metadata-representation-list-element',
@@ -9,8 +10,13 @@ import { MetadataRepresentation } from '../../../core/shared/metadata-representa
910
* An abstract class for displaying a single MetadataRepresentation
1011
*/
1112
export class MetadataRepresentationListElementComponent {
13+
/**
14+
* The optional context
15+
*/
16+
@Input() context: Context;
17+
1218
/**
1319
* The metadata representation of this component
1420
*/
15-
metadataRepresentation: MetadataRepresentation;
21+
@Input() mdRepresentation: MetadataRepresentation;
1622
}
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
<div>
2-
<span class="dont-break-out">{{metadataRepresentation.getValue()}}</span>
2+
<span class="dont-break-out">{{mdRepresentation.getValue()}}</span>
33
</div>

0 commit comments

Comments
 (0)