AlbertLucianto / vue-text-highlight

Text highlighter library for Vue.js :lipstick:
https://albertlucianto.github.io/vue-text-highlight
MIT License
326 stars 35 forks source link

Any way to use with v-html description ? #48

Open frufin opened 3 years ago

frufin commented 3 years ago

Hi Albert, How would it be possible to search query inside bound text (v-html) ?

zhangzef commented 3 years ago

I have the same question

adamkhan commented 3 years ago

+1. v-html is how Vue is supposed to work, given that they deprecated the triple moustache. I at least can't really use Text Highlight without this.

adlairise commented 3 years ago

I had this problem as well - seems like it should get fixed at some point, but I used this work around:

My desired vue markup would have looked like this:

<text-highlight :queries="queries">
  <div class="card-summary" v-html="item.Summary"></div>
</text-highlight>`

So instead I added a highlightBody filter in the script export default that replaces that should be highlighted with a wrapping tag that it finds using regex. The markup looks like:

<div class="card-summary" v-html="$options.filters.highlightText(item.Summary, queries)"></div>

and the filter looks like:

filters: {
  highlightText: function (str, queries) {
    const query = queries[0];
    const check = new RegExp(query, 'ig');
    return str.toString().replace(check, function (matchedText, a, b){
      return (`<mark class="text__highlight">${ matchedText }</mark>`);
    });
    return str;
  }
}

In my case I only needed the first query, so if you need more you may have to do a loop of all queries and do a replace on the string each time. Also, this solution leaves out the index and text properties on the <mark> that vue-text-highlight includes on the nodes. Depending on your implementation you may need to add further logic to include those values, but in my use case I didn't.

However, importantly it allows for the same styling that's used in other places with . Additionally, it's important to keep in mind that this is not a bulletproof solution - this logic exists entirely outside of vue-text-highlight, meaning that any place where you change logic/classnames with options like highlightClass or highlightComponent, you will have to reimplement the logic in the above filter.

Verdoso commented 3 months ago

A little late but thank you very much @adlairise, it worked like a charm. I modified the function a little bit to take into account the case when no query is passed, otherwise I was having issues:

  filters: {
    highlightText: function (str, queries) {
      if (queries && queries.length > 0) {
        const query = queries[0];
        const check = new RegExp(query, "ig");
        return str.toString().replace(check, function (matchedText, a, b) {
          return `<mark class="text__highlight">${matchedText}</mark>`;
        });
      } else {
        return str;
      }
    },
  },

I have also used just one query, as I want to be able to search using spaces, so all is good.

Cheers!