简体   繁体   中英

Vue.js nested for loop with search filter

I have a JSON object with nested objects that I am iterating over to pull out data. All is working fine, but I'd like to add a search/filter implementation so that the search is being done on the second level of the nested for loop. I have it somewhat working but im not getting any data returned. Here is an example:

https://codesandbox.io/s/vue-template-s9t9o

In the HelloWorld component is where the search/filter is happening. As you can see its not outputting the rest of the data after it passes through the searchFilter method.

To make it work without the search/filter, change the following on line #6 :

from: <div class="contentSingle" v-for="(c, i) in searchFilter" :key="i">

to: <div class="contentSingle" v-for="(c, i) in cont" :key="i">

Anyone can think of what I can do to make this work? I need to filter by the elements inside each of the content inside the main data object. You can find the data object inside the FauxData/dataContent.js dir.

Thanks a lot.

-S

You should use methods instead of computed:

  methods: {
    filterValue(content) {
      return content.filter(item => {
        let itemUpper = item.content.toUpperCase();
        let searchUpper = this.search.toUpperCase();
        return itemUpper.indexOf(searchUpper) > -1;
      });
    }
  }

and then in HTML code:

  <section id="content">
    <input type="text" id="search" name="search" v-model="search" placeholder="Search Content...">
    <div v-for="(cont, index) in content" :key="index" class="contentWrapper">
      <h1>{{ index }}</h1>
      <div class="contentSingle" v-for="(c, i) in filterValue(cont)" :key="i">
        <h3>{{ c.title }}</h3>
        <div v-html="c.content"></div>
      </div>
    </div>
  </section>

Updated

If you want to hide the empty section, then use computed value:

  computed: {
    filteredData() {
      return Object.keys(this.content).reduce((a, cKey) => {
        const data = this.filterValue(this.content[cKey]);
        if (data.length) {
          a[cKey] = data;
        }
        return a;
      }, {});
    }
  },
  methods: {
    filterValue(content) {
      return content.filter(item => {
        let itemUpper = item.content.toUpperCase();
        let searchUpper = this.search.toUpperCase();
        return itemUpper.indexOf(searchUpper) > -1;
      });
    }
  }

Use filteredData in outer v-for

  <section id="content">
    <input type="text" id="search" name="search" v-model="search" placeholder="Search Content...">
    <div v-for="(cont, index) in filteredData" :key="index" class="contentWrapper">
      <h1>{{ index }}</h1>
      <div class="contentSingle" v-for="(c, i) in cont" :key="i">
        <h3>{{ c.title }}</h3>
        <div v-html="c.content"></div>
      </div>
    </div>
  </section>

Demo on codepen

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM