[英]Highlight search result with Angular filter and hide non matching text?
[英]Highlight the search text - angular 2
信使根据用户提供的输入显示搜索结果。 需要突出显示搜索到的单词,同时显示结果。 这些是使用的 html 和组件。
组件.html
<div *ngFor = "let result of resultArray">
<div>Id : result.id </div>
<div>Summary : result.summary </div>
<div> Link : result.link </div>
</div>
组件.ts
resultArray : any = [{"id":"1","summary":"These are the results for the searched text","link":"http://www.example.com"}]
这个 resultArray 是通过发送搜索文本作为输入来访问后端服务的。 根据搜索文本,获取结果。 需要高亮搜索到的文字,类似google搜索。 请找到截图,
如果我搜索“成员”这个词,“成员”这个词的出现就会突出显示。 如何使用 angular 2 实现相同的效果。请对此提出建议。
您可以通过创建一个管道并将该管道应用到ngfor
中数组的摘要部分来做到这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>$&</mark>");
}
}
然后在标记中将其应用于这样的字符串:
<div innerHTML="{{ str | highlight : 'search'}}"></div>
将“搜索”替换为您要突出显示的单词。
希望这会有所帮助。
所选答案存在以下问题:
我建议改为使用以下代码
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;
}
如果您的字符串中有多个单词,请使用接受数组并突出显示结果中的每个单词的管道。
您可以将以下管道用于多个搜索词:-
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 方法的一个难点在于<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>
基于以前的答案(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”。
为了扩展 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;
}
我建议像这样转义搜索字符串
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)
}
}
改变了对我有用的公认答案。
transform(value: any, args: any): any {
const args1 = args.toLowerCase()
const args2 = this.capitalizeFirstLetter(args)
if(args === args1 || args === args2){
if (!args) {return value;}
var re1 = new RegExp(args1, 'g'); //'gi' for case insensitive and can use 'g' if you want the search to be case sensitive.
var re2 = new RegExp(args2, 'g'); //'gi' for case insensitive and can use 'g' if you want the search to be case sensitive.
let info = value.replace(re1, "<mark>" + args1 + "</mark>");
return info.replace(re2, "<mark>" + args2 + "</mark>");
}
else{
args = args.toLowerCase()
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>");
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.