Reputation: 1251
I'm trying to highlight a text when it matches the text entered in a text input.
So if I have this data
data: function() {
return {
names:['John', 'Johan', 'Diego', 'Edson']
searchFilter:''
}
}
And this html:
<input type="text" v-model="searchFilter">
<div v-for="b in names">
<p v-html="highlight(b)"></p>
</div>
If I type "Joh" in the input, I would like to get in my html:
John
Johan
Diego
Edson
<div>
<p><strong>Joh</strong>n</p>
<p><strong>Joh</strong>an</p>
<p>Diego</p>
<p>Edson</p>
</div>
So far, I have written this method, but it highlights all the word, not just the typed characters.
methods: {
highlight(itemToHighlight) {
if(!this.searchFilter) {
return itemToHighlight;
}
return itemToHighlight.replace(new RegExp(this.searchFilter, "ig"), match => {
return '<strong">' + match + '</strong>';
});
}
}
Any advice would be great. Thanks!
Upvotes: 2
Views: 4871
Reputation: 7165
You could do something like this:
methods: {
highlight(itemToHighlight) {
if(!this.searchFilter) {
return itemToHighlight;
}
return itemToHighlight.replace(new RegExp(this.searchFilter, "ig"), match => {
return '<strong">' + this.searchFilter + '</strong>' + (match.replace(this.searchFilter, ''));
});
}
}
Essentially, the idea being that you are using the matching search term as a base, then getting the portion that doesn't match by replacing the matched string with nothing (''
).
Please note, this wasn't tested, but more of a proof of concept for you. It most likely works.
function nameMatcher(names, searchTerm) {
return names.reduce((all, current) => {
let reggie = new RegExp(searchTerm, "ig");
let found = current.search(reggie) !== -1;
all.push(!found ? current : current.replace(reggie, '<b>' + searchTerm + '</b>'));
return all;
}, []);
}
let allNames = ['John', 'Johan', 'Deon', 'Ripvan'];
let searchTerm = 'Joh';
console.log(nameMatcher(allNames, searchTerm));
By running the example, you will see that the function nameMatcher
correctly replaces the properly matched string within each positive match with the search term surrounded with a <b>
element.
new Vue({
el: ".vue",
data() {
return {
names: ['John', 'Johan', 'Deon', 'Derek', 'Alex', 'Alejandro'],
searchTerm: ''
};
},
methods: {
matchName(current) {
let reggie = new RegExp(this.searchTerm, "ig");
let found = current.search(reggie) !== -1;
return !found ? current : current.replace(reggie, '<b>' + this.searchTerm + '</b>');
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
<div class="container vue">
<input v-model="searchTerm" placeholder="Start typing here...">
<div v-for="(name, key) in names">
<div v-html="matchName(name)"></div>
</div>
</div>
Let me know if you have any questions! Hope this helps!
Upvotes: 3