【问题标题】:Highlight the search text - angular 2突出显示搜索文本 - angular 2
【发布时间】:2017-12-11 05:16:19
【问题描述】:

信使会根据用户输入的内容显示搜索结果。需要在显示结果的同时突出显示正在搜索的单词。 这些是使用的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 是通过发送搜索文本作为输入从命中后端服务中获取的。根据搜索文本,获取结果。需要突出显示搜索到的文本,类似于 google 搜索。请找到截图,

如果我搜索“member”这个词,“member”这个词的出现会被突出显示。如何使用 Angular 2 实现相同的效果。请就此提出一个想法。

【问题讨论】:

  • 我发现这个gist 工作得很好

标签: javascript angular html typescript


【解决方案1】:

您可以通过创建一个管道并将该管道应用到ngfor 内数组的summary 部分来做到这一点。这是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>$&</mark>");
    }
}

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

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

将“搜索”替换为您要突出显示的单词。

希望这会有所帮助。

【讨论】:

  • 这也将找到的子字符串替换为搜索的子字符串,应用错误的大小写。
  • 清晰简单的答案!
  • @afe return value.replace(new RegExp(args, 'gi'), "$&");将替换为相同的情况
  • 正在搜索 .将选择所有内容,并且什么都不搜索将为每个字符创建标记(因为这很简单,一个简单的 if (!args) {return value;} 在函数的开头)
  • @Jeremy 补充说。感谢您的意见。
【解决方案2】:

所选答案存在以下问题:

  1. 如果搜索字符串中没有提供任何内容,它将返回 undefined
  2. 搜索应该不区分大小写,但不应替换原始字符串的大小写。

我建议改用以下代码

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

【讨论】:

  • 这与单词的多次出现不匹配,但它确实提供了一个很好的观点,即试图通过覆盖大小写来防止搜索消除。我提交了一个使用区分大小写的正则表达式来尝试解决问题的答案。当搜索很时髦时,会退回到不区分大小写。
【解决方案3】:

innerHTML 方法的一个难点是设置&lt;mark&gt; 标记的样式。另一种方法是将其放置在组件中,从而在样式方面提供更多选择。

highlighted-text.component.html

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

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

highlighted-text.component.css

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

用法

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

【讨论】:

    【解决方案4】:

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

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

    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 [innerHTML]="result | highlight:searchTerms"></div>
    

    如果你想使用自定义类:

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

    一切顺利!

    【讨论】:

    • 应该是[innerHTML] 而不是[innetHTML]
    • 提示:如果您将"&lt;mark&gt;" + text + "&lt;/mark&gt;" 更改为"&lt;mark&gt;$&amp;&lt;/mark&gt;",它将保留突出显示部分的大小写。
    【解决方案5】:

    在之前的答案(HighlightedText-Component)的基础上,我得到了这个:

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

    这样,针的多个匹配项也会被突出显示。这个组件的用法和上一个答案类似:

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

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

    【讨论】:

      【解决方案6】:

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

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

      【讨论】:

        【解决方案7】:

        为了扩展卡马尔的答案,

        进入转换方法的值可以是一个数字,也许转换为字符串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;
        }
        

        【讨论】:

          猜你喜欢
          • 2018-06-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-04-08
          • 1970-01-01
          • 2012-06-25
          • 2016-07-31
          相关资源
          最近更新 更多