Angular 5. 如何动态添加链接到包含某个标签的字符串。像 '@'
Angular 5. How to dynamically add links to strings containing a certain tag. like '@'
我有一个模板视图,如下所示
<div class="post-content">
<p>{{ post.content }}</p>
</div>
其中 post.content 是一种字符串。
该字符串可能包含也可能不包含一个或多个引用不同用户的@ 标记。示例:“@用户名”。我想用 link 使这个标签可点击。将其作为锚标记插入:
<a>@username</a>
到目前为止,我已经尝试过手动对它进行字符串操作,并在字符串中插入锚标记。然而,这只是在视图中显示为纯文本。
如何在 Angular 5 中解决这个问题?
您必须使用 innerHTML
属性 将提供的字符串呈现为 HTML,
所以而不是
<p> {{post.content}} </p>
你应该使用
<p [innerHTML]="post.content"></p>
但是这种方法not safe如果处理不当容易出现XSS,
推荐方法:创建管道DOM消毒
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;
}
}
你可以根据自己的逻辑修改stylize
方法
用法:
<p [innerHTML]="sample | linkify"></p>
我做过相关的文字转换
private textLinkify(值:任何):任何{
让 convertedHTML: string = '';
var str = 'Click here to know more.';
var linkStartPos = str.indexOf("{");
var linkEndPos = str.indexOf("}");
let previousText = str.slice(0,linkStartPos);
let linkText = str.slice(linkStartPos+1,linkEndPos);
let afterLinkText = str.substr(linkEndPos+2);
convertedHTML = `${previousText}
`<a href="${value.href}" target="_blank">${linkText}</a> ${afterLinkText}`;
return convertedHTML;
}
's answer is great,虽然它有一个问题:如果link在行尾,\n会导致下一行的下一个词会也被俘虏了。
我也将他们的答案改编为适用于 http links:
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;
}
}
已接受的答案有效,但我建议“转换”功能为:
import { Pipe, PipeTransform, SecurityContext } from '@angular/core';
...
transform(value: any, args?: any): any {
return this._domSanitizer.sanitize(SecurityContext.HTML, this.stylize(value));
}
而不是:
transform(value: any, args?: any): any {
return this._domSanitizer.bypassSecurityTrustHtml(this.stylize(value));
}
我有一个模板视图,如下所示
<div class="post-content">
<p>{{ post.content }}</p>
</div>
其中 post.content 是一种字符串。
该字符串可能包含也可能不包含一个或多个引用不同用户的@ 标记。示例:“@用户名”。我想用 link 使这个标签可点击。将其作为锚标记插入:
<a>@username</a>
到目前为止,我已经尝试过手动对它进行字符串操作,并在字符串中插入锚标记。然而,这只是在视图中显示为纯文本。
如何在 Angular 5 中解决这个问题?
您必须使用 innerHTML
属性 将提供的字符串呈现为 HTML,
所以而不是
<p> {{post.content}} </p>
你应该使用
<p [innerHTML]="post.content"></p>
但是这种方法not safe如果处理不当容易出现XSS,
推荐方法:创建管道DOM消毒
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;
}
}
你可以根据自己的逻辑修改stylize
方法
用法:
<p [innerHTML]="sample | linkify"></p>
我做过相关的文字转换
private textLinkify(值:任何):任何{ 让 convertedHTML: string = ''; var str = 'Click here to know more.'; var linkStartPos = str.indexOf("{"); var linkEndPos = str.indexOf("}");
let previousText = str.slice(0,linkStartPos); let linkText = str.slice(linkStartPos+1,linkEndPos); let afterLinkText = str.substr(linkEndPos+2); convertedHTML = `${previousText} `<a href="${value.href}" target="_blank">${linkText}</a> ${afterLinkText}`; return convertedHTML;
}
我也将他们的答案改编为适用于 http links:
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;
}
}
已接受的答案有效,但我建议“转换”功能为:
import { Pipe, PipeTransform, SecurityContext } from '@angular/core';
...
transform(value: any, args?: any): any {
return this._domSanitizer.sanitize(SecurityContext.HTML, this.stylize(value));
}
而不是:
transform(value: any, args?: any): any {
return this._domSanitizer.bypassSecurityTrustHtml(this.stylize(value));
}