I have a template view which looks like this
<div class="post-content">
<p>{{ post.content }}</p>
</div>
where post.content is a type of string.
The string may or may not contain one or more @ tag which references different users. example: '@username'. I want to make this tag clickable with a link. Sort of insert it as an anchor tag:
<a>@username</a>
so far I have tried to string manipulate it manually, and inserting the anchor tag inside the string. However this just shows up as plain text in the view.
How do I go about this in Angular 5?
AngularJS ng-href DirectiveThe ng-href directive should be used instead of href if you have AngularJS code inside the href value. The ng-href directive makes sure the link is not broken even if the user clicks the link before AngularJS has evaluated the code.
In computing, a hyperlink, or simply a link, is a digital reference to data that the user can follow or be guided by clicking or tapping. A hyperlink points to a whole document or to a specific element within a document. Hypertext is text with hyperlinks.
You have to use the innerHTML
property to render the provided string as HTML,
so instead of
<p> {{post.content}} </p>
You should use
<p [innerHTML]="post.content"></p>
Demo
However, this method is not safe and is prone to XSS if not handled properly,
The recommended method: Create a pipe with DOM Sanitization
linkify.pipe.ts
import { Pipe, PipeTransform } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';
@Pipe({
name: 'linkify'
})
export class LinkifyPipe implements PipeTransform {
constructor(private _domSanitizer: DomSanitizer) {}
transform(value: any, args?: any): any {
return this._domSanitizer.bypassSecurityTrustHtml(this.stylize(value));
}
// Modify this method according to your custom logic
private stylize(text: string): string {
let stylizedText: string = '';
if (text && text.length > 0) {
for (let t of text.split(" ")) {
if (t.startsWith("@") && t.length>1)
stylizedText += `<a href="#${t.substring(1)}">${t}</a> `;
else
stylizedText += t + " ";
}
return stylizedText;
}
else return text;
}
}
You can modify the stylize
method according to your logic.
Usage:
<p [innerHTML]="sample | linkify"></p>
Demo Stackblitz
cyberpirate92's answer is great, though it has one issue: if a link is at the end of the line, the \n will cause the next word on the next line will get captured as well.
I adapted their answer to work on http links as well:
import { Pipe, PipeTransform } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';
@Pipe({ name: 'linkify' })
export class LinkifyPipe implements PipeTransform {
constructor(private _domSanitizer: DomSanitizer) {}
transform(value: any, args?: any): any {
return this._domSanitizer.bypassSecurityTrustHtml(this.stylize(value));
}
// Modify this method according to your custom logic
private stylize(text: string): string {
let stylizedText: string = '';
if (text && text.length > 0) {
for (let line of text.split("\n")) {
for (let t of line.split(" ")) {
if (t.startsWith("http") && t.length>7) {
stylizedText += `<a href="${t}">${t}</a> `;
}
else
stylizedText += t + " ";
}
stylizedText += '<br>';
}
return stylizedText;
}
else return text;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With