Angular2将纯文本转换为url的方式(锚链接)

时间:2016-09-01 16:30:22

标签: angular typescript angular2-routing angular2-template angular2-directives

我有时会有一个可以接收这样的文本的组件:

  

text www.website.com

但如果是链接,我想将其转换为网址。像这样。

  

text www.website.com

我读了SO answer,建议使用第三方库,例如anchorme。有没有办法以angular2方式做到这一点?

6 个答案:

答案 0 :(得分:14)

使用简单的正则表达式修改HTML内容存在许多问题。

这是一种使用linkifyjs模块的方法,您需要npm install。请注意,输入被视为纯文本,而输出是HTML文本。

import { Pipe, PipeTransform } from '@angular/core';
import linkifyStr from 'linkifyjs/string';

@Pipe({name: 'linkify'})
export class LinkifyPipe implements PipeTransform {
  transform(str: string): string {
    return str ? linkifyStr(str, {target: '_system'}) : str;
  }
}

注意:如果您需要指定target属性,请添加例如。 {target: '_system'}作为linkifyStr的第二个参数。

答案 1 :(得分:9)

好的,为了制作一个管道,你可以制作一个由

组成的管道组件
  import { Pipe, PipeTransform } from '@angular/core';



    @Pipe({name: 'linkify'})
    export class LinkifyPipe implements PipeTransform {
      transform(link: string): string {
        return this.linkify(link);
      }

      private linkify(plainText): string{
        let replacedText;
        let replacePattern1;
        let replacePattern2;
        let replacePattern3;

        //URLs starting with http://, https://, or ftp://
        replacePattern1 = /(\b(https?|ftp):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gim;
        replacedText = plainText.replace(replacePattern1, '<a href="$1" target="_blank">$1</a>');

        //URLs starting with "www." (without // before it, or it'd re-link the ones done above).
        replacePattern2 = /(^|[^\/])(www\.[\S]+(\b|$))/gim;
        replacedText = replacedText.replace(replacePattern2, '$1<a href="http://$2" target="_blank">$2</a>');

        //Change email addresses to mailto:: links.
        replacePattern3 = /(([a-zA-Z0-9\-\_\.])+@[a-zA-Z\_]+?(\.[a-zA-Z]{2,6})+)/gim;
        replacedText = replacedText.replace(replacePattern3, '<a href="mailto:$1">$1</a>');

        return replacedText;
       }
    }

然后导入这个就像你将指令一样,将其传递给

pipes: [LinkifyPipe]

并插入如下

{{url | linkify}}

答案 2 :(得分:8)

你应该以这种方式使用这个管道:

<div [innerHtml]="note.title | linkify"></div>

答案 3 :(得分:2)

你应该检查angular-linky https://github.com/dzonatan/angular-linky

<span [innerHTML]="yourText | linky"></span>

答案 4 :(得分:1)

好的,这就是我做的事情,留下答案希望它可以帮助别人:

所以我正在使用一个函数来链接我的plaint文本

private linkify(plainText): string{
    let replacedText;
    let replacePattern1;
    let replacePattern2;
    let replacePattern3;

    //URLs starting with http://, https://, or ftp://
    replacePattern1 = /(\b(https?|ftp):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gim;
    replacedText = plainText.replace(replacePattern1, '<a href="$1" target="_blank">$1</a>');

    //URLs starting with "www." (without // before it, or it'd re-link the ones done above).
    replacePattern2 = /(^|[^\/])(www\.[\S]+(\b|$))/gim;
    replacedText = replacedText.replace(replacePattern2, '$1<a href="http://$2" target="_blank">$2</a>');

    //Change email addresses to mailto:: links.
    replacePattern3 = /(([a-zA-Z0-9\-\_\.])+@[a-zA-Z\_]+?(\.[a-zA-Z]{2,6})+)/gim;
    replacedText = replacedText.replace(replacePattern3, '<a href="mailto:$1">$1</a>');

    return replacedText;
}

但是这会返回一个带有html编码的字符串,所以如果我使用<p>{{example}}</p>,它将返回完整的编码(包含锚标签和html)。

所以现在我使用angular2内置的html绑定:

这给了我解决方案

答案 5 :(得分:1)

我搜索过一个解决方案,但无济于事。我需要扩展处理Angular路由[routerLink]和[innerHTML]外部链接的要求,而不需要第三方库。

我的解决方案(摘要):

Angular 2,Angular 5 - 用户动态[innerHTML]生成内容的用户点击事件/事件处理,使用管道和指令生成纯文本并将其转换为点击网址,例如#hashtags,@ Handle,@ Mintion,#luterLink #href和#mailto等

Plunker演示: https://embed.plnkr.co/68lZFY/

<强> AppComponent

import { Component, NgModule, VERSION} from '@angular/core';
import { BrowserModule} from '@angular/platform-browser';

@Component({
    selector: 'my-app',
    template: `<h1>Angular - Dynamic content click event</h1>
                        <p>Angular 2, Angular 5, Typescript - User click events/event handling for dynamic [innerHTML] generated content using pipe and directive to generate and converting plain text to click urls e.g #hashtags,  @Handle, @Mention, #routerLink #href and #mailto etc</p>
                        <ul>
                            <li *ngFor="let item of theList; let $index=index;" [innerHTML]="item | parseUrl" [dynamicContent]="currentView"></li>
                        <ul>`
})
export class AppComponent {
     theList:Array;

        constructor() {
                this.theList = [
                    'Lorem ipsum dolor sit amet, consectetur @adet dolore magna aliqua. Ut enim ad minim veniam',
                    'Lorem ipsum dolor sit amet, consectetur adipiscing http://google.com sed do eiusmod tempor #incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam',
                    'Lorem http://google.com ipsum dolor #sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt gna aliqua. Ut enim ad minim veniam',
                    'Lorem ipsum @dolor sit amet, consectetur @adipiscing elit, sed do eiusmod @tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam',
                    'Lorem ipsum dolor sit amet, smod tempor incididunt #ut labore et dolore @magna #aliqua. Ut enim ad minim veniam',
                    'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam',
                    'Lorem ipsum @dolor sit amet, #consectetur adipiscing elit, sed do eiusmod tempor http://google.com enim ad minim veniam'
                ];
        }

}

<强>指令

import { Directive, ElementRef, HostListener, Input } from '@angular/core';

@Directive({
    selector: '[dynamicContent]'
})
export class DynamicContent {

    constructor(private el: ElementRef) { }

    @Input('dynamicContent') dynamicContent: string;

    @HostListener('click', ['$event']) onClick(e) {

        if (e.target.classList.contains('handle-link')) {
            let link: string = e.target.innerHTML;

            event.preventDefault();
            event.stopPropagation();

            alert("/search/handle/" + link.trim());

            //this.router.navigateByUrl("/search/handle/" + link.trim(), { skipLocationChange: false });

        } else if (e.target.classList.contains('hashtag-link')) {
            let link: string = e.target.innerHTML;

            event.preventDefault();
            event.stopPropagation();

             alert("/search/hashtag/" + link.trim());

            //this.router.navigateByUrl("/search/hashtag/" + link.trim(), { skipLocationChange: false }); 

        }

    }

}

<强>管

export class ParseUrl implements PipeTransform {

    urls: any = /(\b(https?|http|ftp|ftps|Https|rtsp|Rtsp):\/\/[A-Z0-9+&@#\/%?=~_|!:,.;-]*[-A-Z0-9+&@#\/%=~_|])/gim; // Find/Replace URL's in text  
    hashtags: any = /(^|\s)(#[a-z\d][\w-]*)/ig; // Find/Replace #hashtags in text   
    mentions: any = /(^|\s)(@[a-z\d][\w-]*)/ig; // Find/Replace @Handle/Mentions in text    
    emails: any = /(\S+@\S+\.\S+)/gim; // Find/Replace email addresses in text

    transform(text: string) {
        return this.parseUrl(text);
    }

    private parseUrl(text: string) {
        // Find/Replace URL's in text
        if (text.match(this.urls)) {
                text = text.replace(this.urls, function replacer($1, $2, $3) {
                        let url: any = $1;
                        let urlClean: any = url.replace("" + $3 + "://", "");

                        return "<a href=\"" + url + "\" target=\"_blank\">" + urlClean + "</a>";
                });
        }

        // Find/Replace @Handle/Mentions in text
        if (text.match(this.hashtags)) {
            text = text.replace(this.hashtags, "<a href=\"/search/hashtag/$2\" class=\"hashtag-link\">$1$2</a>");
        }

        // Find/Replace #hashtags in text
        if (text.match(this.mentions)) {
            text = text.replace(this.mentions, "<a href=\"/search/handle/$2\" class=\"handle-link\">$1$2</a>");
        }

        // Find/Replace email addresses in text
        if (text.match(this.emails)) {
                text = text.replace(this.emails, "<a href=\"mailto:$1\">$1</a>");
        }

        return text;
    }  
}