0

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

2
  • You should post relevant code in the question rather than relying exclusively on an external link. What exactly should be filtered here, the main items or the sub-items? I understand that it's the sub-items that should be used for matching purposes but that still leaves ambiguity. If a single sub-item matches then should only that sub-item be shown or the whole parent item? Commented Jul 8, 2019 at 23:01
  • Noted... If a sub-item is a match, I'd like the main index/label displayed and also that particular title and content. Commented Jul 8, 2019 at 23:20

1 Answer 1

2

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

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you ittus. How would I hide the root/parent elements on the object that are not part of the filtered results? For example on your code if you filter using Four Two you get the very last title-content combo and its root/parent 'Main Four'. BUT you still see the other root/parents...how can we hide those? Does the method have to be executed in the first for loop?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.