riophae / vue-treeselect

A multi-select component with nested options support for Vue.js
https://vue-treeselect.js.org/
MIT License
2.9k stars 508 forks source link

Features request: keyword highlighting & keyboard navigation #48

Open marekkaczkowski opened 6 years ago

marekkaczkowski commented 6 years ago

Hey again,

It would be nice to have:

Thanks for awesome package :1st_place_medal:

riophae commented 6 years ago

Yeah, I totally agree with you! These two features are nice and actually both have been incorporated in the plan. Recently I have seen so many people facing issues due to the restrictions of options prop, so right now I am working on making options prop reactive, which enables the possibility of external searching, better Vuex support. So I have to implement these new features later. Sorry for that!

marekkaczkowski commented 6 years ago

Sounds like I should fork it :)

riophae commented 6 years ago

@marcelfalliere Welcome!

wickkidd commented 6 years ago

While I think it would be better if highlighting was supported natively (probably still with the option of a slot), you can do it now...

In the template (I only included the props specific to making highlighting work. You'll still need others depending on your use case. Also, the markup is pug.):

treeselect(
  valueFormat="object"
  @search-change="searchChange"
)
  label(
    slot="option-label" 
    slot-scope="{node, labelClassName}" 
    :class="labelClassName" 
    v-html="highlightTerm(searchTerm, node)"
)

Relevant parts in the script:

data() {
  return {
    searchTerm: String
  }
},
methods: {
  searchChange(term, id) {
    this.searchTerm = term
  },
  highlightTerm(term, node) {
    if (term.length) {
      let regex = new RegExp(term, 'gi')
      return node.label.replace(regex, '<span class="highlight">$&</span>')
    } else {
      return node.label
    }
  }
}

Then style the span.highlight however you wish.

Note: Don't confuse the fact that I used a label element with "node.label" as this is simply a coincidence. Also, you'll need vue >= 2.5.0 to use slot-scope on regular elements: https://vuejs.org/v2/guide/components-slots.html#Destructuring-slot-scope