Search code examples
javascriptvue.jsdynamicfilteringv-model

I have to use v-model in computed, otherwise computed doesn't return a value


I am new to JS/Vue. I am trying to make a dynamic search input. I am filtering on input change, filtered is an array of objects fetched from my API. The weird thing is that the computed method does not return any data unless I use this.term before the return, it can be a console.log() or anything else with my v-model. What am I missing ?

var stops = new Array();
  document.addEventListener("DOMContentLoaded", () => {
    fetch('http://localhost:8080/api/stops/')
      .then(response => response.json())
      .then((data) => {
        window.data = data;

        Object.keys(window.data).forEach(k => {
          stops.push(window.data[k]);
        });
      })
      .catch(err => {
        console.log(err);
      });

  });


  Vue.component('sidebar', {
delimiters: ['{(', ')}'],
data: () => {
  return {
    term: '',
  }
},
computed: {
  filtered() {

    <!--followng line needs to be here for the func to return data-- >
    this.term = this.term 

    return stops.filter(p => p.nameno.toLowerCase().includes(this.term.toLowerCase()));
  }

},
template:

  `
    <div id="sidebarContain" >
        <input id="sidebar-search" type="text" v-model="term" >

        <div v-for="tram in filtered" :key="tram.name">
            <span >{(tram.nameno)}</span>
            <span ></span>
        </div>
    </div>
`,
methods: {
},
});

Solution

  • It's because stops isn't in your Vue data object, so it can't react to changes. Move the loading logic into the mounted method, add a stops property to the data object, and set it using this.stops = ... in the mounted method:

    
    Vue.component('sidebar', {
      delimiters: ['{(', ')}'],
      data: () => {
        return {
          term: '',
          stops: []
        }
      },
      computed: {
        filtered() {
          this.term = this.term 
    
          return this.stops.filter(p => p.nameno.toLowerCase().includes(this.term.toLowerCase()));
        }
      },
      mounted() {
        fetch('http://localhost:8080/api/stops/')
          .then(response => response.json())
          .then((data) => {
            window.data = data;
    
            Object.keys(data).forEach(k => {
              this.stops.push(data[k]);
            });
          })
          .catch(err => {
            console.log(err);
          });
      },
      template:
        `
          <div id="sidebarContain" >
              <input id="sidebar-search" type="text" v-model="term" >
    
              <div v-for="tram in filtered" :key="tram.name">
                  <span >{(tram.nameno)}</span>
                  <span ></span>
              </div>
          </div>
      `,
      methods: {
      },
    });