3

I want to build a search box in angular, that would return the array of item,and also highlight the searcchedTerm in the results array.

For example: In Chrome if you are searching any text, it would highlight with light yellow background. Similar to that.

enter image description here

I have created two pipes, one to filter the result and another to highlight the term in the results which is searched. But i am getting error replace is not a function.

And also, can the two pipes be merged into one?

highlight.pipe.ts

transform(list: any, searchText: string): any[] {
    if (!list) { return []; }
    if (!searchText) { return list; }

    const re = new RegExp(searchText, 'gi');
    const value = list.replace(re, "<span class='yellow'>" + searchText + "</span>" );
    return list;
}

using the pipe in template

<div class="card" *ngFor="let item of list | search: searchedTerm | highlight: searchedTerm">

Cœur
  • 37,241
  • 25
  • 195
  • 267
Raj
  • 1,100
  • 3
  • 20
  • 33
  • Can you add the code where you're trying to do `replace` please? Or just add all of the code from your pipes – user184994 Sep 29 '18 at 13:58
  • i have already given the stackblitz url, where you can find the full code. And also added the code here. – Raj Sep 29 '18 at 14:03
  • Sorry, I missed that. You may be better off using a `directive` rather than a `pipe`. Here is an example you can check in GitHub https://github.com/arthurvaverko/ngx-highlight – user184994 Sep 29 '18 at 14:22

2 Answers2

3

1- In the highlight.pipe.ts

transform(list: any, searchText: string): any[] {
console.log('lists', list);
console.log('searchText', searchText);

if (!list) { return []; }
//to remove highlighted tags before any processing
list = list.map(function (item) {
  item.name = item.name ? String(item.name).replace(/<[^>]+>/gm, '') : '';
  return item;
})
if (!searchText) { return list; }

const re = new RegExp(searchText, 'gi');
const value = list
  .map(function (item) {
    //this will match the values and add the highlight tag for it
    item.name = item.name.replace(re, "<span class='yellow'>" + searchText + "</span>");
    return item
  });
return value;

}

2- Move the .yellow style to style.css to match for the injected html

3- In the app.component.html

<div class="card" *ngFor="let item of list | search: searchedTerm | highlight: searchedTerm">
 <span [innerHTML]="item.name"></span>
</div>

If you want the items to disappear then use the search pipe if you only want it highlighted then the highlight pipe alone is enough

a link for the updated Stackblitz : https://stackblitz.com/edit/angular-searchpipe?file=src%2Fapp%2Fapp.component.html

Enas Osama
  • 211
  • 1
  • 7
  • thanks for the reply. The changes you have done are not saved. You need to Fork(top left button, in blue color) my exampe and then do the changes. only then your changes would be saved. – Raj Sep 30 '18 at 16:36
2

I
Iterate over filtered list by searchedTerm. Place highlighted html into innerHTML.

// html
<div class="card" *ngFor="let item of list | search: searchedTerm">
  <span [innerHTML]="item.name | highlight: searchedTerm"></span>
</div>

II

// HighlightPipe
const re = new RegExp(searchText, 'gi');
return item.replace(re, `<span class='yellow'>${searchText}</span>` );

III

Use deprecated (move to global styles) deep as components by default have Emulated ViewEncapsulation

// css
::ng-deep .yellow{
  background: yellow;
}
Buggy
  • 3,539
  • 1
  • 21
  • 38
  • thanks for the reply. I had the highlight pipe to the array instead of the name. I got it now. thanks – Raj Sep 30 '18 at 16:32