Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vue js text highlight filter

I need help writing a text highlight filter using vuejs. The idea is to loop through a given array of words and if there is a match, apply a span with a class to that word. The problem I have is that, I can't seem to return data with html formatting with vuejs. Any ideas will be highly appreciated. I am really stuck with this.

Vue.filter('highlight', function(words, query){
    //loop through **words** and if there is a match in **query**
   //apply a <span> with some style
   //At the end return formatted string to html page
})
like image 655
Makten Avatar asked Jun 15 '16 15:06

Makten


3 Answers

HTML interpolations {{{ foo }}} have been removed in favor of the v-html directive in vuejs2.X, thus from version 2.x, Vue.js allows for raw JavaScript templating (React-style) in addition to HTML templating.
@jeff's answer is correct but for vuejs 1.x versions, but in case {{{}}} didn't work for you guys or if you want to evaluate the tags in the HTML, and from a trusted source, example, if you want to add a <strong></strong> tag, then you need to use v-html, the v-html to ask Vue to evaluate the string as HTML:

<span v-html="$options.filters.highlight(item, val)">{{ item }}</span>

highlight filter:

Vue.filter('highlight', function(word, query){
  var check = new RegExp(query, "ig");
  return word.toString().replace(check, function(matchedText,a,b){
      return ('<strong>' + matchedText + '</strong>');
  });
});

or you can use @Thomas Ferro's filter

like image 131
Kumar_14 Avatar answered Nov 07 '22 23:11

Kumar_14


As Jeff just said, the basic mustaches interprets the data as plain text.

You can add your span by replacing the query with the String.replace() method.

Here's a basic example: https://jsfiddle.net/0jew7LLz/

Vue.filter('highlight', function(words, query) {
    return words.replace(query, '<span class="highlight">' + query + '</span>')
});
like image 13
Thomas Ferro Avatar answered Nov 07 '22 21:11

Thomas Ferro


The idea is to use split and keep the words that the regex matches.

Here is a user safe component that escapes html and highlights a regexp that searches for multiple words:

Vue.component('child', {
  props: ['msg', 'search', 'effect'],
  template: '<span><span v-for="(s, i) in parsedMsg" v-bind:class="getClass(i%2)">{{s}}</span></span>',
  methods: {
    getClass: function(i) {
      var myClass = {};
      myClass[this.effect] = !!i;
      return myClass;
    },
  },
  computed: {
    parsedSearch : function () {
        return '(' + this.search.trim().replace(/ +/g, '|') + ')';
    },
    parsedMsg: function() {
        return this.msg.split(
        new RegExp(this.parsedSearch , 'gi'));
    }
  }
})

new Vue({
  el: '#app',
  }
  // ...
})

Usage example:

<div id="app">
  <child msg="My life so good and awesome, is'nt it great?" search="   life   is   good  " effect='highlight'> </child>
</div>

jsfiddle:

https://jsfiddle.net/50xvqatm/

like image 5
AturSams Avatar answered Nov 07 '22 22:11

AturSams