vue.jsvue-material

vue md-autocomplete keyup.enter not working


I'm trying to wrap up an auto-complete feature on my app and can't seem to get @keyup.enter to execute a function. The documentation doesn't touch on this. Here's my code below.

    <md-autocomplete
      v-model="selected"
      :md-options="users"
      :md-fuzzy-search="false"
      @keyup.enter="click_select()"
      >
      <label id="placehold" v-if="selected == null || selected == ''">Start typing...</label>

      <template slot="md-autocomplete-item" slot-scope="{ item, term }">
        <md-highlight-text :md-term="term">{{ item }}</md-highlight-text>
      </template>

      <template slot="md-autocomplete-empty" slot-scope="{ term }" v-if="term != null">
        "{{ term }}" is not currently on file. <a @click="noop()">You can add them here</a>.
      </template>
    </md-autocomplete>

    <div class="md-layout md-gutter">
      <transition name="fade">
        <a class="selectlink" v-if="selected != null && selected !='' && view_link" id="link-effect-4" v-on:click="show_data()">Select</a>
        <a class="selectlink" v-if="selected != null && selected !='' && view_next_link" id="link-effect-4">Next</a>
      </transition>
    </div>

Solution

  • Why your solution isn’t working

    In order to listen on an event on a component (md-autocomplete), that component must emit the event. From a glimpse at the source it doesn’t appear to do so. If any child component (for instance, an <input>) emits the event, but the outer component doesn’t pass it through, you will never see it.

    A Vue solution that might not work here

    You can, however, still attach event listeners to the slots you pass into the component. It would look like this:

    <template slot="md-autocomplete-item" @keyup.enter="click_select()" …>
    

    I haven’t looked thoroughly through the docs, but I cannot find a suitable location for that, either.

    Vanilla JS will work

    As a last resort, you can attach an event listener to a DOM node that is a parent of the component you actually want to listen to. Suppose md-autocomplete was mounted in a <div id="parentDiv">, you could do

    function listenerFunction(event) {
      if (event.keyCode === 13) {
      // keycode 13 is the return key
        click_select()
      }
    }
    
    document.getElementById('parentDiv').addEventListener('keyup', listenerFunction)
    

    Caveats

    It might also be appropriate to check whether the event originated where you think it should (that is, in the component’s search bar) by means of event.target or event.composedPath

    In any case you should remember to detach the event listener when the component is destroyed, or else you might have the function called multiple times when the component is later re-mounted:

    beforeDestroy() {
      document.getElementById('parentDiv').removeEventListener('keyup', listenerFunction)
    }
    

    This is also why listenerFunction must be given a name. You cannot remove an event listener that was attached using an anonymous function.