I couldn't find many resources on this issue, so through a trial-and-error approach, I have come up with the following code and files.
Assuming I am developing "mytheme" custom theme and "myentity" custom entity:
1. Add mytheme/app/entity-groups/some-entity-group/metadata-representations/my-entity/my-entity-item-metadata-list-element.component.ts, something like:
import { Component } from '@angular/core';
import { RouterLink } from '@angular/router';
import { NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap';
import { metadataRepresentationComponent } from 'src/app/shared/metadata-representation/metadata-representation.decorator';
import { MetadataRepresentationType } from 'src/app/core/shared/metadata-representation/metadata-representation.model';
import { ItemMetadataRepresentationListElementComponent } from 'src/app/shared/object-list/metadata-representation-list-element/item/item-metadata-representation-list-element.component';
import { TruncatableComponent } from 'src/app/shared/truncatable/truncatable.component';
@metadataRepresentationComponent('myentity', MetadataRepresentationType.Item)
@Component({
selector: 'ds-my-entity-item-metadata-list-element',
templateUrl: './my-entity-item-metadata-list-element.component.html',
standalone: true,
imports: [TruncatableComponent, RouterLink, NgbTooltipModule],
})
export class MyEntityItemMetadataListElementComponent extends ItemMetadataRepresentationListElementComponent {
}
2. Add mytheme/app/entity-groups/some-entity-group/metadata-representations/my-entity/my-entity-item-metadata-list-element.component.spec.ts, something like:
import {
ChangeDetectionStrategy,
NO_ERRORS_SCHEMA,
} from '@angular/core';
import {
ComponentFixture,
TestBed,
waitForAsync,
} from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { RouterLink } from '@angular/router';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
import { Item } from 'src/app/core/shared/item.model';
import { MetadataValue } from 'src/app/core/shared/metadata.models';
import { ItemMetadataRepresentation } from 'src/app/core/shared/metadata-representation/item/item-metadata-representation.model';
import { TruncatableComponent } from 'src/app/shared/truncatable/truncatable.component';
import { MyEntityItemMetadataListElementComponent } from './my-entity-item-metadata-list-element.component';
const displayName = 'Display Name';
const mockItem = Object.assign(new Item(), { metadata: { 'dc.title': [{ value: displayName }] } });
const virtMD = Object.assign(new MetadataValue(), { value: displayName });
const mockItemMetadataRepresentation = Object.assign(new ItemMetadataRepresentation(virtMD), mockItem);
describe('MyEntityItemMetadataListElementComponent', () => {
let comp: MyEntityItemMetadataListElementComponent;
let fixture: ComponentFixture<MyEntityItemMetadataListElementComponent>;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
imports: [
NgbModule,
MyEntityItemMetadataListElementComponent,
],
schemas: [NO_ERRORS_SCHEMA],
}).overrideComponent(MyEntityItemMetadataListElementComponent, {
remove: {
imports: [TruncatableComponent, RouterLink],
},
add: { changeDetection: ChangeDetectionStrategy.Default },
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(MyEntityItemMetadataListElementComponent);
comp = fixture.componentInstance;
comp.mdRepresentation = mockItemMetadataRepresentation;
fixture.detectChanges();
});
it('should show the entity\'s name as a link', () => {
const linkText = fixture.debugElement.query(By.css('a')).nativeElement.textContent;
expect(linkText).toBe(displayName);
});
it('should show the description on hover over the link in a tooltip', () => {
const link = fixture.debugElement.query(By.css('a'));
link.triggerEventHandler('mouseenter', null);
fixture.detectChanges();
const tooltip = fixture.debugElement.query(By.css('.item-list-display-name')).nativeElement.textContent;
expect(tooltip).toBe(displayName);
});
});
3. Add mytheme/app/entity-groups/some-entity-group/metadata-representations/my-entity/my-entity-item-metadata-list-element.component.html, something like:
<ng-template #descTemplate>
<span class="text-muted">
<span class="item-list-display-name">
<span [innerHTML]="mdRepresentation.firstMetadataValue(['dc.title'])"></span>
</span>
</span>
</ng-template>
<ds-truncatable [id]="mdRepresentation.id">
<a [routerLink]="[itemPageRoute]"
[innerHTML]="mdRepresentation.getValue()"
[ngbTooltip]="mdRepresentation.allMetadata(['dc.title']).length > 0 ? descTemplate : null"></a>
</ds-truncatable>
4. In the mytheme/eager-theme.module.ts add:
import { MyEntityItemMetadataListElementComponent } from './app/entity-groups/some-entity-group/metadata-representations/my-entity/my-entity-item-metadata-list-element.component';
const ENTRY_COMPONENTS = [
MyEntityItemMetadataListElementComponent,
];
This basically works, and custom metadata should obviously be applied where necessary depending on the entity structure. However, I am not familiar with the functionality of all the components imported into the files mentioned above, so if anyone could provide more details on this part (which components are missing, required, useful, etc.), it would be greatly appreciated.