stumbler
stumbler

Reputation: 737

How to hyperlink a table column value in a data table using angular7?

In my application I am fetching the data in a data table. The application front end is running on angular7. Now I want some of the column values should have a link and click on the link a new component will be displayed. Example::

Column1           Column2     Column3
value with Link

How I can Implement this scenario using angular7?

I am going through the routing docs in https://angular.io/guide/router

But does not able to map it with my current requirement.

Upvotes: 1

Views: 14291

Answers (3)

carlupq
carlupq

Reputation: 328

If you have an EMBEDDED link within a larger text, the above won't work for you. This is what worked for me - you can use innerHTML attribute binding:

    <td mat-cell *matCellDef="let element" [innerHTML]="element.name">
    </td>

...and the text will remain text, with the link becoming a link assuming the wrapping anchor html tag is present, otherwise you can write a function in your .ts code to auto-wrap links as follows (presumes a single link as ' http' followed by a space or EOF):

  addHyperlink(txtLinkSansAnchor: string) {
enter code here
    const srchVal = ' http';
    var retVal = txtLinkSansAnchor; // init to self
    hyperlinkProtocol: string = '<a target="_blank" href="----">----</a>';
    if (txtLinkSansAnchor.includes(srchVal)) {
      var startPos = txtLinkSansAnchor.indexOf(srchVal) + 1;
      var endPos = txtLinkSansAnchor.indexOf(' ', startPos + 5);
      if (endPos < startPos) {
        endPos = txtLinkSansAnchor.length;
      }
      var replStringOrig = txtLinkSansAnchor.substring(startPos, endPos);
      var replStringNew = hyperlinkProtocol.split('----').join(replStringOrig);
      var txtLinkWithAnchor = txtLinkSansAnchor.replace(replStringOrig, replStringNew);
      retVal = txtLinkWithAnchor;
    }
    return retVal;
  }

...and then your html template code will look as follows:

<td mat-cell *matCellDef="let element" [innerHTML]="addHyperlink(element.name)">
</td>

Upvotes: 0

Sunny
Sunny

Reputation: 2507

Solution 1: Using Angular Material Table

If you are specifically working with Angular Material and find it tricky to add the hyperlink in data table column then following solution would help

.ts file

import { ProductService } from './../data-service/data-service-product/product.service';
import { Component, OnInit, OnDestroy, ViewChild, AfterViewInit } from '@angular/core';
import { Subscription } from 'rxjs';
import { IProduct } from '../models/IProduct';
import { MatPaginator }  from '@angular/material/paginator';
import { MatSort} from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table';


@Component({
  selector: 'app-admin-products',
  templateUrl: './admin-products.component.html',
  styleUrls: ['./admin-products.component.css']
})
export class AdminProductsComponent implements OnInit, AfterViewInit, OnDestroy {

  products: IProduct[];
  filteredProducts: any[];
  subscriptionVariable: Subscription;

  displayedColumns = ['title', 'price', 'action'];
  dataSource =  new MatTableDataSource();

  @ViewChild(MatPaginator, {static: false}) paginator: MatPaginator;
  @ViewChild(MatSort, {static: false}) sort: MatSort;

  constructor(private productDataService: ProductService) {
    this.subscriptionVariable = this.productDataService.getAll().subscribe(
      p => this.dataSource.data = this.filteredProducts = this.products = p as IProduct[] );
  }

  ngOnInit() {
  }


  // tslint:disable-next-line: use-lifecycle-interface
  ngAfterViewInit() {
    this.dataSource.paginator = this.paginator;
    this.dataSource.sort = this.sort;
  }

  applyFilter(filterValue: string) {
    filterValue = filterValue.trim(); // Remove whitespace
    filterValue = filterValue.toLowerCase(); // Datasource defaults to lowercase matches
    this.dataSource.filter = filterValue;
  }

  ngOnDestroy() {
    this.subscriptionVariable.unsubscribe();
  }   

}

.interface

export interface IProduct {
    category: string;
    imageUrl: string;
    price: number;
    title: string;
}

component.html

<p>
  <a routerLink="/admin/products/new" class="btn btn-primary">
    New Product
  </a>
</p>
<p>

  <mat-form-field>
    <input matInput (keyup)="applyFilter($event.target.value)" placeholder="Filter">
  </mat-form-field>
</p>

    <div class="example-container mat-elevation-z8">

  <mat-table #table [dataSource]="dataSource" matSort>

    <ng-container matColumnDef="title">
      <mat-header-cell *matHeaderCellDef mat-sort-header> Title </mat-header-cell>
      <mat-cell *matCellDef="let element"> {{element.title}} </mat-cell>
    </ng-container>

    <ng-container matColumnDef="price">
      <mat-header-cell *matHeaderCellDef mat-sort-header> Price </mat-header-cell>
      <mat-cell *matCellDef="let element"> {{element.price}} </mat-cell>
    </ng-container>

    <!-- Star Column -->
    <ng-container matColumnDef="action" >
      <mat-header-cell *matHeaderCellDef > Action </mat-header-cell>
      <mat-cell *matCellDef="let element">
        <a [routerLink] ="['/admin/products/', element.key]" routerLinkActive="router-link-active" >Edit</a>
      </mat-cell>
    </ng-container>

    <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
    <mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
  </mat-table>

  <mat-paginator [length]="5" [pageSize]="5" [pageSizeOptions]="[5, 10, 25]">
  </mat-paginator>
</div>

Solution 2: Using html table


Using normal html you can create your own table and then add the functionality accordingly

component.html file

    <table class="table">
      <thead>
        <tr>
          <th>Title</th>
          <th>Price</th>
          <th>Action</th>
        </tr>
      </thead>

      <tbody>
        <tr *ngFor="let product of filteredProducts">
          <td>
            {{ product.title}}
          </td>

          <td>
            {{ product.price}}
          </td>

          <td>
            <a [routerLink] ="['/admin/products/', product.key]" routerLinkActive="router-link-active" >Edit</a>
          </td>
        </tr>
      </tbody>
    </table>

**

Final Result

**

enter image description here

Upvotes: 1

Eliran Eliassy
Eliran Eliassy

Reputation: 1600

If I got you right you are using Angular Material data table, isn't it?

If so, try this:

 <ng-container matColumnDef="prop">
  <mat-header-cell *matHeaderCellDef> Prop Name </mat-header-cell>
  <mat-cell *matCellDef="let element">
    <a routerLink="/your-link">{{element.prop}}</a>
  </mat-cell>
</ng-container>

Upvotes: 3

Related Questions