Incorporating a Link/Template Column into Your Unique Table Design

I built a table component following the guidelines from this article: Creating an Angular2 Datatable from Scratch.

While I have added features like sorting and paging to suit my app's needs, I am struggling with implementing a "Template column" to allow for elements like edit/delete links.

I attempted using <ng-content> within the ColumnComponent to pass in link/routerlink templates, but couldn't make it work based on how the table is structured.

You can check out a simplified version of my components here: Plunkr

The current (simplified) structure of my components looks like:

datatable.component.html

<table class="table table-striped table-hover">
    <thead>
        <tr>
            <th *ngFor="let column of columns">
              {{column.header}}
            </th>
        </tr>
    </thead>
    <tbody *ngFor="let row of dataset; let i = index">
        <tr>
            <td *ngFor="let column of columns">
              {{row[column.value]}}
            </td>
        </tr>
    </tbody>
</table>

datatable.component.ts

import { Http, Response } from '@angular/http';
import { Injectable, Component, Input, Output, EventEmitter } from '@angular/core';
import { ColumnComponent } from './column.component';

@Component({
    selector: 'datatable',
    templateUrl: 'src/datatable.component.html'
})
export class DatatableComponent {

    @Input() dataset;
    columns: ColumnComponent[] = [];
    addColumn(column) {
        this.columns.push(column);
    }
}

column.component.ts

import {Component, Input} from '@angular/core';
import {DatatableComponent} from './datatable.component';

@Component({
  selector: 'column',
  template: ``,

})
export class ColumnComponent {
    @Input() value: string;
    @Input() header: string;

    constructor(public table: DatatableComponent) {
        table.addColumn(this);
    }
}

Example Markup For Existing Components

<datatable  [dataset]="photoData">
    <column [value]="'id'" [header]="'ID'"></column>
    <column [value]="'title'" [header]="'Title'"></column>
</datatable>

Desired Markup Example Although not exact, I'm aiming for something like:

<datatable  [dataset]="photoData">
    <column [value]="'id'" [header]="Edit">
         This is a custom edit link column:
         <a [routerLink]="['/edit/', id]">
            <span class='glyphicon glyphicon-pencil'></span>
         </a>
    </column>
    <column [value]="'id'" [header]="'ID'"></column>
    <column [value]="'title'" [header]="'Title'"></column>
</datatable>

Answer №1

To achieve this, I suggest utilizing the ngTemplateOutlet.

Set up references for various templates in your

column.component.ts

@ContentChild('tableHeaderTemplate') headerTemplate: TemplateRef<any>;
@ContentChild('tableBodyTemplate') bodyTemplate: TemplateRef<any>;

This allows us to use custom templates for header or body content if provided.

datatable.component.html

<table class="table table-striped table-hover">
    <thead>
      <tr>
        <th *ngFor="let col of columns">
           <ng-container *ngIf="!col.headerTemplate">{{col.header}}</ng-container> 
           <ng-template *ngIf="col.headerTemplate" [ngTemplateOutlet]="col.headerTemplate" [ngTemplateOutletContext]="{ $implicit: { header: col.header } }"></ng-template>
        </th>
      </tr>
    </thead>
    <tbody *ngFor="let row of dataset; let i = index">
      <tr>
        <td  *ngFor="let col of columns">
          <ng-container *ngIf="!col.bodyTemplate">{{row[col.value]}}</ng-container> 
          <ng-template *ngIf="col.bodyTemplate" [ngTemplateOutlet]="col.bodyTemplate" [ngTemplateOutletContext]="{ $implicit: { value: row[col.value] }, row: row }"></ng-template>
        </td>
      </tr>
    </tbody>
</table> 

For example, a table definition could include:

<datatable  [dataset]="photoData">
    <column [value]="'id'" [header]="'ID'"></column>
    <column [value]="'title'" [header]="'Title'">
        <ng-template #tableHeaderTemplate let-column>
            <span style="color: red">{{ column.header }}</span>
        </ng-template>
    </column>
    <column [value]="'title'" [header]="'Actions'">
      <ng-template #tableBodyTemplate let-column let-row="row">
          <button (click)="remove(row.id)">Remove {{row.id}}</button>
      </ng-template>
    </column>
</datatable>

Check out this Plunker Example

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Steps to activate Angular Progressive Web App service worker

When I set up an Angular project, I executed the following commands in the terminal: ng add @angular/pwa ng build --prod The static website output was published in the /dist folder. After running the URL through PWABuilder, it detected the manifest bu ...

When I bring in a component from my personal library, it will assign the type "any" to it

I'm facing an issue when trying to import a component from my own library. The component within the library is actually sourced from another one (so I import the component, customize it, and then export the customized version). However, upon importi ...

When using translate.get with an array of strings in Angular 5, the function will return both the keys and values, not just

Currently, I am utilizing Angular 5 to manage internationalization through ngx-translate within my code. To elaborate on the issue at hand, I have a data table that pulls information from a web service and displays it correctly. There is also a button tha ...

The NgbTooltip fails to display the arrow icon ( ▼ ) within the NgbPopover's window

There appears to be an issue with the arrow div not functioning properly within NgpPopover body due to conflicting arrow classes for NgbPopover's div.arrow and NgbTooltip's div.arrow. This seems to be a known problem in ng-bootstrap when using bo ...

Testing the mirkoORM entities at a unit level

Trying to perform a unit test on a method within a MikroORM entity, I am attempting to populate a mikroORM collection field with test data. Specifically, I am using jest for this task: describe('Team Tests', () => { it('isLeader shoul ...

Angular router consistently redirecting to the identical module

It's really frustrating me. I've set up 3 basic routes in my app module: routes: Routes = [ { path: '', redirectTo: '/customers', pathMatch: 'full' }, { path: 'customers', loadChildren: './com ...

Unable to access /route upon refreshing page in Angular 7

After developing several components in Angular 7, I decided not to use 'useHash: true' for routing. Everything seemed to be running smoothly when I deployed my Angular app on a live server. However, I encountered an issue when reloading a page a ...

Intercontinental partnership bridging two separate entities

Within my application, there is a primary module: app.component.html <h1>{{globals.title}}</h1> <router-outlet></router-outlet> In app.module.ts @NgModule({ imports: [ BrowserModule, HomeModule, NotesModule, ...

The issue at hand is that the Mongo Atlas model is in place, but for some reason,

https://i.sstatic.net/4m2KT.pngI recently delved into using Next.js and I am a newcomer to backend technologies. I have successfully established a connection with MongoDB Atlas using Mongoose, however, the user object data from the post request is not be ...

Unfortunately, my capabilities do not allow me to execute the command 'ng build --configuration production

This is the issue that I am facing and need assistance: Error: src/app/app.component.html:1:1 - error NG8001: 'fuse-progress-bar' is not recognized as a valid element: If 'fuse-progress-bar' is an Angular component, please ensure that ...

Angular threw an error stating that it encountered an unexpected token 'var' when trying to declare a variable x as

Currently facing a challenge with my Angular application development. I have created a TS File that interacts with my API (imported in the index.html using a script tag) and exported some functions from this file to be used in my components. Despite everyt ...

Having trouble retrieving the "Text" from the "element" with the help of "Protractor"

Greetings! I am currently in the process of creating Protractor automation scripts for an "Angular 4" application. Below is the code from my development: <!--Byndd Title div--> <div class="ui-g-12 ui-md-8 ui-lg-10"> ...

Activate a function with one event that is triggered by another event in Angular 5 and Material Design 2

I am facing an issue where I need to change the value of a radio button based on another radio button selection in Angular 5 with Material Design 2. However, the event is not triggering and there are no console errors being displayed. For example, if I cl ...

The Angular file management API from ng6-file-man seems to be malfunctioning

I have downloaded the API, but I am having trouble grasping the concept of parentpath. I attempted to use Postman to call the API at https://github.com/Chiff/ng6-file-man-express, but without success. There seems to be a "files" folder at the root - is t ...

What causes the discrepancy between the response.headers in Angular and the response headers shown in the browser's developer

this.http.post(this.url+"/login",formData).subscribe( (response: any)=>{ console.log(response.headers); const cookies = response.headers.get('Set-Cookie'); // console.log(response.headers); console.log(c ...

Identify the classification of unfamiliar items

Occasionally, you may find yourself in situations where you have to work with packages that were not designed with TypeScript in mind. For instance, I am currently using the two.js package in a React project with TypeScript strict mode enabled. It has been ...

I encountered an error while trying to deploy my next.js project on Vercel - it seems that the module 'react-icons/Fa' cannot be found, along with

I'm currently in the process of deploying my Next.js TypeScript project on Vercel, but I've encountered an error. Can someone please help me with fixing this bug? Should I try running "npm run build" and then push the changes to GitHub again? Tha ...

RxJS - Only emit if another source does not emit within a specified time frame

Imagine having two observables. Whenever the first one emits, there should be a 2-second pause to check if the other observable emits something within that timeframe. If it does, then no emission should occur. However, if it doesn't emit anything, the ...

Error Message: Angular Unit Test Fails with "Cannot read property 'subscribe' of undefined"In this article, we will

My Angular app's unit tests using Jest are giving me the error "TypeError: Cannot read property 'subscribe' of undefined". Despite searching online, none of the solutions provided seem to work for me. Below is some relevant code: page-view. ...

Angular5 encountered a problem with the ngx-bootstrap DatePicker when handling DateTime objects

I currently have a SQL Server database field called 'JoiningDate' with the type of date (no time included). To collect input from users, I am utilizing the ngx-bootstrap datepicker. However, I am encountering an issue where the datepicker convert ...