Reputation: 737
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
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
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
**
Upvotes: 1
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