I have encountered an issue with my HTML file. The initial content within the ng-container tag is displaying data correctly. However, upon clicking the button to open the details panel, which utilizes the ng-template, only the first data entry from the array is being rendered. It seems like there might be a need to dynamically generate the template, but I am unsure about how to proceed in order to resolve this problem.
<ng-container *ngFor="let member of members; trackBy: trackByFn;">
<div class="flex flex-col py-4 sm:flex-row sm:items-center">
<div class="flex items-center">
<!-- Info details panel button -->
<ng-container *ngIf="members?.length">
<button class="w-5 h-5 ml-1 min-h-5"
[disabled]="member.session.length === 0"
mat-icon-button
(click)="openInfoDetailsPanel()"
#infoDetailsPanelOrigin>
<mat-icon
[ngClass]="{
'text-gray-400 icon-size-8': member.session.length === 0,
'text-green-600 icon-size-8': member.session.length > 0
}"
[svgIcon]="'cast_connected'">
</mat-icon>
</button>
</ng-container>
<!-- Info details panel -->
<ng-template #infoDetailsPanel>
<div class="flex flex-col py-4 px-6 w-full max-w-160 space-y-1.5 border text-md rounded shadow-md overflow-auto bg-card">
<div class="flex">
<span>{{member | json}}</span>
<span>{{member.session | json}}</span>
<ng-container *ngFor="let item of member.session">
<tr>
<td class="px-2 ">{{item.ip}}</td>
<td class="px-2 ">{{convertDateTimeToLocaleDate(item.registrationDate)}}</td>
<td class="px-2 ">{{convertDateTimeToLocaleTime(item.registrationDate)}}</td>
</tr>
</ng-container>
</div>
</div>
</ng-template>
</div>
</div>
</ng-container>
Within the TypeScript file, we have the following function:
@ViewChild('infoDetailsPanelOrigin') private _infoDetailsPanelOrigin: MatButton;
@ViewChild('infoDetailsPanel') private _infoDetailsPanel: TemplateRef<any>;
The function is as follows:
openInfoDetailsPanel(): void
{
// Create the overlay
this._overlayRef = this._overlay.create({
backdropClass : '',
hasBackdrop : true,
scrollStrategy : this._overlay.scrollStrategies.block(),
positionStrategy: this._overlay.position()
.flexibleConnectedTo(this._infoDetailsPanelOrigin._elementRef.nativeElement)
.withFlexibleDimensions(true)
.withViewportMargin(16)
.withLockedPosition(true)
.withPositions([
{
originX : 'start',
originY : 'bottom',
overlayX: 'start',
overlayY: 'top'
},
{
originX : 'start',
originY : 'top',
overlayX: 'start',
overlayY: 'bottom'
},
{
originX : 'end',
originY : 'bottom',
overlayX: 'end',
overlayY: 'top'
},
{
originX : 'end',
originY : 'top',
overlayX: 'end',
overlayY: 'bottom'
}
])
});
// Create a portal from the template
const templatePortal = new TemplatePortal(this._infoDetailsPanel, this._viewContainerRef);
// Attach the portal to the overlay
this._overlayRef.attach(templatePortal);
// Subscribe to the backdrop click
this._overlayRef.backdropClick().subscribe(() => {
// If overlay exists and attached...
if ( this._overlayRef && this._overlayRef.hasAttached() )
{
// Detach it
this._overlayRef.detach();
}
// If template portal exists and attached...
if ( templatePortal && templatePortal.isAttached )
{
// Detach it
templatePortal.detach();
}
});
}