Matt
Matt

Reputation: 463

Angular 2 Highlight Multiple Values Using Pipe

I currently have a simple search function implemented here that allows a user to search for courses. The user can input queries multiple queries separated by commas, and I am filtering the results if there exists a match to each tokenized query (done iteratively):

search($event) {
      var re = /\s*,\s*/;
      let splitQuery = this.searchText.split(re);
      let numQueries = splitQuery.length;
      let tempCourses = this.courses;
      for (var i = 0;i < numQueries; i ++){
        tempCourses = this.rankAndFilter(tempCourses, splitQuery[i].toUpperCase())
      }
      this.courseResults = this.sortByRank(tempCourses);

I would also like for all the queries to be highlighted in the search results as well, to be viewable to the user. This is the original highlight pipe and I have tried to modify it, but it doesn't return each individual word highlighted.

transform(value: string, args: string): any {

var re = /\s*,\s*/;

    if (args && value){
        let splitQuery = args.split(re);
        let numQueries = splitQuery.length;
        let returnedHighlighted: String = value; 
        console.log(`number of queries: ${numQueries}`)
        for (var i = 0; i < numQueries; i++){

          console.log(`${i}: ${splitQuery[i]}`)
          let startIndex = value.toUpperCase().indexOf(splitQuery[i].toUpperCase());
          if (startIndex != -1) {
                let endLength = args.length;
                let matchingString = value.substr(startIndex, endLength);
                returnedHighlighted = returnedHighlighted.replace(matchingString, "<mark>" + matchingString + "</mark>");
           }  
        }
        return returnedHighlighted
    }
    return value; }

A test case would be the query linear algebra returns 89A Statistics and 54 Mathematics, a query linear algebra, probability returns both courses but with the individual words highlighted, and the query linear algebra, probability, data science would only return 89A Statistics with each individual query highlighted.

In reality this will be applied to over tens of thousands of courses, so any pointers / implementations for time efficiency for either the highlighting or filtering would also be appreciated.

Thank you!

Upvotes: 1

Views: 945

Answers (2)

Matt
Matt

Reputation: 463

Building off @Eliseo's answer to handle edge cases such as "query," and "query, ":

 transform(value: string, args: string): any {

     if (args && value){
           let re_noSpace = /\s*,\s*/;
           let queryList = args.split(re_noSpace).filter(String);
           let re_matchQueries = new RegExp(queryList.join('|'),"gi");
           return value.replace(re_matchQueries,(x)=>"<mark>"+x+"</mark>");
      }
      return value; 
 }

Upvotes: 0

Eliseo
Eliseo

Reputation: 57971

You can do it in one step. Create a regExpresion that search the different values an replace by the < mark>value< /mark>

@Pipe({ name: 'highlight' })
export class HighlightPipe implements PipeTransform {

    transform(value: string, args: string): any {

    if (args && value){
       var re = new RegExp(args.split(',').join('|'),"gi");
        //e.g. if args was linear,equa, the regExpr will become  /linear|equa/gi
        return value.replace(re,(x)=>"<mark>"+x+"</mark>");
    }
    return value; 
  }
}

NOTE: You must check if use an especial characters $, ...

Upvotes: 3

Related Questions