突出显示搜索文字 - 角度2

时间:2017-07-07 02:45:28

标签: javascript angular html5 typescript

信使根据用户提供的输入显示搜索结果。在显示结果时,需要突出显示已搜索的单词。 这些是使用的html和组件。

Component.html

 <div *ngFor = "let result of resultArray">
<div>Id : result.id </div>
<div>Summary : result.summary </div>
<div> Link : result.link </div>
</div>

Component.ts

resultArray : any = [{"id":"1","summary":"These are the results for the searched text","link":"http://www.example.com"}]

通过发送搜索文本作为输入来获取此resultArray来命中后端服务。根据搜索文本,获取结果。需要突出显示搜索到的文字,类似于谷歌搜索。请找截图

enter image description here

如果我搜索“成员”一词,则会突出显示“成员”一词的出现。如何使用角度2实现相同。请提出一个想法。

7 个答案:

答案 0 :(得分:31)

您可以通过创建管道并将该管道应用于ngfor内的数组的摘要部分来实现。以下是Pipe的代码:

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

@Pipe({
    name: 'highlight'
})

export class HighlightSearch implements PipeTransform {

    transform(value: any, args: any): any {
        if (!args) {return value;}
        var re = new RegExp(args, 'gi'); //'gi' for case insensitive and can use 'g' if you want the search to be case sensitive.
        return value.replace(re, "<mark>" + args + "</mark>");
    }
}

然后在标记中将它应用于这样的字符串:

<div innerHTML="{{ str | highlight : 'search'}}"></div>

替换&#39;搜索&#39;用你要强调的词。

希望这会有所帮助。

答案 1 :(得分:8)

所选答案存在以下问题:

  1. 如果搜索字符串中没有提供任何内容,它将返回undefined
  2. 搜索应该不区分大小写,但不应替换原始字符串大小写。
  3. 我建议使用以下代码

    transform(value: string, args: string): any {
        if (args && value) {
            let startIndex = value.toLowerCase().indexOf(args.toLowerCase());
            if (startIndex != -1) {
                let endLength = args.length;
                let matchingString = value.substr(startIndex, endLength);
                return value.replace(matchingString, "<mark>" + matchingString + "</mark>");
            }
    
        }
        return value;
    }
    

答案 2 :(得分:1)

innerHTML方法的一个难点在于为<mark>标记设置样式。另一种方法是将其放在一个组件中,从而在样式中提供更多选项。

<强>突出-text.component.html

<mark *ngIf="matched">{{matched}}</mark>{{unmatched}}

<强>突出-text.component.ts

import { Component, Input, OnChanges, OnInit } from "@angular/core";

@Component({
    selector: "highlighted-text",
    templateUrl: "./highlighted-text.component.html",
    styleUrls: ["./highlighted-text.component.css"]
})
export class HighlightedTextComponent implements OnChanges {
    @Input() needle: String;
    @Input() haystack: String;
    public matched;
    public unmatched;

    ngOnChanges(changes) {
        this.match();
    }

    match() {
        this.matched = undefined;
        this.unmatched = this.haystack;
        if (this.needle && this.haystack) {
            const needle = String(this.needle);
            const haystack = String(this.haystack);
            const startIndex = haystack.toLowerCase().indexOf(needle.toLowerCase());
            if (startIndex !== -1) {
                const endLength = needle.length;
                this.matched = haystack.substr(startIndex, endLength);
                this.unmatched = haystack.substr(needle.length);
            }
        }
    }
}

<强>突出-text.component.css

mark {
    display: inline;
    margin: 0;
    padding: 0;       
    font-weight: 600;
}

<强>用法

<highlighted-text [needle]=searchInput [haystack]=value></highlighted-text>

答案 3 :(得分:0)

扩展Kamal的答案

转换方法中的值可能是一个数字,也许是转换为字符串String(value)是安全的事情。

transform(value: string, args: string): any {
    if (args && value) {
        value = String(value); // make sure its a string
        let startIndex = value.toLowerCase().indexOf(args.toLowerCase());
        if (startIndex != -1) {
            let endLength = args.length;
            let matchingString = value.substr(startIndex, endLength);
            return value.replace(matchingString, "<mark>" + matchingString + "</mark>");
        }

    }
    return value;
}

答案 4 :(得分:0)

如果您的字符串中包含多个单词,而不是使用接受数组并突出显示结果中每个单词的管道。

您可以将以下管道用于多个搜索词:-

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

@Pipe({
    name: 'highlight'
})

export class HighlightText implements PipeTransform {

    transform(value: any, args: any): any {
        if (!args) {return value;}
        for(const text of args) {
            var reText = new RegExp(text, 'gi');
            value = value.replace(reText, "<mark>" + text + "</mark>");
            //for your custom css
            // value = value.replace(reText, "<span class='highlight-search-text'>" + text + "</span>"); 


        }
        return value;
    }
}

分割字符串以生成字符串数组。

var searchTerms = searchKey.split(' ');

用法:

<div [innetHTML]="result | highlight:searchTerms"></div>

如果您想使用自定义类:

.highlight-search-text {
  color: black;
  font-weight: 600;
}

祝一切顺利!

答案 5 :(得分:0)

我建议像这样转义搜索字符串

 RegExp.escape = function(string) {
  if(string !== null){ return string.toString().replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
  } else return null
};

@Pipe({
    name: 'highlight'
})
export class HighlightPipe implements PipeTransform {
  constructor(private sanitizer: DomSanitizer){ }

  transform(value: any, args: any): any {
    if (!args || value == null) {
      return value;
    }
    // Match in a case insensitive maneer
    const re = new RegExp(RegExp.escape(args), 'gi');

      const  match = value.match(re);



    // If there's no match, just return the original value.
    if (!match) {
      return value;
    }

    const replacedValue = value.replace(re, "<mark>" + match[0] + "</mark>")
    return this.sanitizer.bypassSecurityTrustHtml(replacedValue)
  }
}

答案 6 :(得分:0)

以先前的答案(HighlightedText-Component)为基础,我得出以下结论:

def pairs(k, arr):
    return len(set(arr).intersection(element + k for element in arr))

这样,针的多个匹配也将突出显示。该组件的用法类似于上一个答案中的用法:

import { Component, Input, OnChanges } from "@angular/core";

@Component({
    selector: 'highlighted-text',
    template: `
        <ng-container *ngFor="let match of result">
            <mark *ngIf="(match === needle); else nomatch">{{match}}</mark>
            <ng-template #nomatch>{{match}}</ng-template>
        </ng-container>
    `,
})
export class HighlightedTextComponent implements OnChanges {
    @Input() needle: string;
    @Input() haystack: string;
    public result: string[];

    ngOnChanges() {
        const regEx = new RegExp('(' + this.needle + ')', 'i');
        this.result = this.haystack.split(regEx);
    }
}

对我来说,这种使用组件的方法感觉更安全,因为我不必使用“ innerHtml”。