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>

Demo

但是这种方法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>

Demo Stackblitz

  1. 我做过相关的文字转换

    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));
}