Join the Stack Overflow Community
Stack Overflow is a community of 6.6 million programmers, just like you, helping each other.
Join them; it only takes a minute:
Sign up

Excuse any syntax errors, It works perfectly, but I could have made an error copying over.

Problem: I have a component, 'dropdown', that is repeated three times with v-for='(item, index) in search' which is an array with three objects. Below in the 'filterInput' method, The for loop and if statement does indeed work as intended, HOWEVER, I do not know how to target the 'dropdown' element that matches the search[i]. I need to remove the search[i]'s element in the DOM when the search[i].text doesn't match the input.

<div id='app'>
  <input type='text' placeholder='Start typing here...' v-model='input'
    @click='drop()' v-on:blur='close()'>
  <ul id="dropdown" class='nodisplay'>
    <dropdown v-for='(item, index) in search' v-bind:item='item' v-   
      bind:index='index'></dropdown>
  </ul>
</div>

Vue.component('dropdown', {
  props: ['item', 'index'],
  template: `<li><a href="#"> {{item.text}}</a></li>`
})

var app = new Vue({
  el: '#app',
  data: {
  input: '', //reactive
  search: [
    {id: 1, text: 'Jacob'},
    {id: 2, text: 'Jeff'},
    {id: 3, text: 'Tom'}
  ]
  },
  methods: {
    drop: function() {
      let dropdown = document.getElementById('dropdown');
      dropdown.classList.toggle('nodisplay');
    },
    close: function() {
      let dropdown = document.getElementById('dropdown');
      dropdown.classList.toggle('nodisplay');
      document.querySelector('input').value = '';
    },
    filterInput: function(index) {
      //dropdown items in console: app.search[index].text = 'xyz'
      for (let i = 0; i < this.search.length; i++) {
        if (!(this.search[i].text.startsWith(this.input))) {
          //hide or remove this current search element from dropdown
        }
      }
    }
  },
  watch: {
    input: function() {
      this.filterInput();
    }
  }
})

tl;dr; how do I target

share|improve this question

What you are looking for is how to have parent child communication, which I have answered today itself here.

You need to $emit an event from the child component and set the value used in input field, just like the example in documentation.

Here is the code:

HTML

<div id='app'>
  <input type='text' placeholder='Start typing here...' v-model='input'
    @click='drop()' >
  <ul id="dropdown" :class="{'nodisplay': dropDownClosed}">
    <dropdown v-for='(item, index) in search' v-bind:item='item' v-   
      bind:index='index' v-on:getdropdowninput="getdropdowninput"></dropdown>
  </ul>
</div>

JS

dropdown = Vue.component('dropdown', {
  props: ['item', 'index'],
  template: `<div><li ><a @click="selectval(item.text)" href="#"> {{item.text}}</a></li></div>`,
  methods: {
     selectval (value) {
        this.$emit("getdropdowninput", value)
     }
  }
})

var app = new Vue({
  el: '#app',
  data: {
    input: '', //reactive
    dropDownClosed: false,
    search: [
      {id: 1, text: 'Jacob'},
      {id: 2, text: 'Jeff'},
      {id: 3, text: 'Tom'}
    ]
  },
  methods: {
    drop: function() {
      this.dropDownClosed = true
    },
    getdropdowninput: function(value) { 
       this.dropDownClosed = false
       this.input = value;
    },
    filterInput: function(index) {
      //dropdown items in console: app.search[index].text = 'xyz'
      for (let i = 0; i < this.search.length; i++) {
        if (!(this.search[i].text.startsWith(this.input))) {
          //hide or remove this current search element from dropdown
        }
      }
    }
  },
  watch: {
    input: function() {
      this.filterInput();
    }
  }
})

Here is the working fiddle.

Use dynamic classes: I have also modified how to add/remove a class dynamically in vue way, instead of document.getElementById. Notice in following line:

<ul id="dropdown" :class="{'nodisplay': dropDownClosed}">

nodisplay class will be applied when dropDownClosed variable will be true and it will be removed when dropDownClosed variable will be false.

How to Filter:

To filter, you can use a computed property in the v-for and whenever input changes you can filter the search array, like following

  computed: {
     filteredInput: function(){
       if(this.input === '' || !this.input){
          return this.search
       } else {
          var self = this
          return this.search.filter(
             function( s ) {
             return s.text.indexOf( self.input ) !== -1; }
          );
       }       
     }

See working fiddle here.

share|improve this answer
    
This is great! However, am I able to use this to have my dropdown list respond and only display if the search.text starts with the current input? – Chris Johnson Dec 22 '16 at 19:54
    
I'm sorry that I don't understand fully. I'm trying to remove list items from the dropdown when a user types in the input. If I type 'J', I want 'Tom' to be removed from the dropdown, and vice versa. I don't understand how I can select the correct list item created by my component to set to display: none if it does not start with the input. – Chris Johnson Dec 22 '16 at 20:37
    
@ChrisJohnson check the updated fiddle and answer: jsfiddle.net/rk77dkuz/3 – Saurabh Dec 23 '16 at 3:06

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.