突出显示搜索文本 - angular 2
Posted
技术标签:
【中文标题】突出显示搜索文本 - angular 2【英文标题】:Highlight the search text - 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 工作得很好 【参考方案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】:所选答案存在以下问题:
-
如果搜索字符串中没有提供任何内容,它将返回 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>
标记的样式。另一种方法是将其放置在组件中,从而在样式方面提供更多选择。
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]
提示:如果您将"<mark>" + text + "</mark>"
更改为"<mark>$&</mark>"
,它将保留突出显示部分的大小写。【参考方案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;
【讨论】:
以上是关于突出显示搜索文本 - angular 2的主要内容,如果未能解决你的问题,请参考以下文章
jQuery 插件 DataTables:如何突出显示当前搜索文本?