我有一个单词列表和一个句子列表。我想突出显示列表中句子中的文本。
例如:
句子:“宋南人”
words:[“ song”,“ nam”,“ p”]
我想在打字稿中创建一个管道,以产生类似。
的输出。歌曲 姓名 p 人。
我尝试了以下解决方案:
import { PipeTransform, Pipe } from "@angular/core";
@Pipe({ name: "highlight" })
export class HighlightPipe implements PipeTransform {
transform(text: string, searchWords: string[]): string {
if (searchWords.length && text) {
searchWords.forEach((searchWord: string) => {
text = text.replace(searchWord, (match) => `<span class="highlightText">${match}</span>`);
});
}
return text;
}
}
上述解决方案的问题:
<span>
。<span class='highlightText'>song</span> nam person
<span>
<span class='highlightText'>song</span> <span class='highlightText'>nam</span> person
<s <span class='highlightText'>p</span>an class='highlightText'>song</span> <span class='highlightText'>nam</span> <span class='highlightText'>person</span>
如果有人可以提供此问题的解决方案,将不胜感激。 谢谢
答案 0 :(得分:5)
您最初的想法很好。接受输入文本并对其进行修改(例如输出),以给定的类包装文本。
使用Angular,当您要操作DOM时,有两点需要牢记:
-使用指令(不是管道)
-使用渲染器,永远不要自己操纵DOM
也就是说,这就是我构建指令的方式:
import { Directive, Input, SimpleChanges, Renderer2, ElementRef } from '@angular/core';
@Directive({
selector: '[appHighlight]'
})
export class HighlightDirective {
@Input() searchedWords: string[];
@Input() text: string;
@Input() classToApply: string;
constructor(private el: ElementRef, private renderer: Renderer2) { }
ngOnChanges(changes: SimpleChanges): void {
if (!this.searchedWords || !this.searchedWords.length || !this.classToApply) {
this.renderer.setProperty(this.el.nativeElement, 'innerHTML', this.text);
return;
}
this.renderer.setProperty(
this.el.nativeElement,
'innerHTML',
this.getFormattedText()
);
}
getFormattedText() {
const re = new RegExp(`(${ this.searchedWords.join('|') })`, 'g');
return this.text.replace(re, `<span class="${this.classToApply}">$1</span>`);
}
}
然后可以在HTML中调用:
<p
appHighlight
[searchedWords]="['song', 'name', 'p']"
text="song name person"
classToApply="selected"
></p>
当然,您也可以构建动态版本:
TS:
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
text = new FormControl('song name person')
searchedWordsControl = new FormControl('')
searchedWords$: Observable<string[]> = this
.searchedWordsControl
.valueChanges
.pipe(
map((search: string) => search.trim().split(' '))
)
}
HTML:
Text:
<input type="text" placeholder="Text" [formControl]="text">
Searched words:
<input type="text" placeholder="Searched words" [formControl]="searchedWordsControl">
<p
appHighlight
[searchedWords]="searchedWords$ | async"
[text]="text.value"
classToApply="selected"
></p>
这是一个包含静态和动态版本的Stackblitz示例:
https://stackblitz.com/edit/angular-rdfyuq