Выделите текст поиска - angular 2

Посланник отображает результаты поиска на основе ввода, заданного пользователем. Необходимо выделить искомое слово, показывая результат. Это 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"}]

Этот результатArray извлекается из бэкэнда-сервиса, отправив текст поиска в качестве входного. На основе текста поиска результат будет получен. Необходимо выделить искомый текст, аналогичный поиску google. Пожалуйста, найдите скриншот,

введите описание изображения здесь

Если я ищу слово "член", то появляется слово "член". Как достичь того же, используя angular 2. Пожалуйста, предложите идею об этом.

Ответ 1

Вы можете сделать это, создав канал и применив этот канал к итоговой части массива внутри 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>

Замените "поиск" словом, которое вы хотите выделить.

Надеюсь, это поможет.

Ответ 2

Выбранный ответ имеет следующие проблемы:

  • Он вернет undefined, если в строке поиска ничего не указано
  • Поиск должен быть нечувствительным к регистру, но не должен заменять исходный случай строки.

я бы предложил вместо этого следующий код

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, - это стиль тега <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>

Ответ 4

Чтобы расширить ответ Камаля,

Значение, входящее в метод преобразования, может быть числом, возможно, приведение в строку 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;
}

Ответ 5

Если в вашей строке несколько слов, используйте конвейер, который принимает массив и выделяет каждое слово в результате.

Вы можете использовать следующую трубу для нескольких поисковых слов: -

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

Всего наилучшего!