Search code examples
vue.jsvue-component

Return a Computed Value From a Loop in Vue


I have a list of categories through which I am looping to see which checkboxes under each category is checked so I can display the checked total next to my category name.

Currently I am trying to figure out what is the best way to return my data. I am using a computed property but I know that when I return a value in a computed property that my loop will only run once, when I need it to return all the values separately (in my case I currently have 3 categories, so I need it to return 3 separate values).

My code loops through the selected items per category and then makes an array of selected objects such as below. I then get the length. What I'm struggling with is the proper way to return the selected item count per category. [{"selected-0":true},{"selected-0":true},{"selected-0":true}]

<div class="search-filters__group-category" v-on:click="toggleFilterAccordion(index)"
  :aria-expanded="isAccordionOpen.includes(index)"
  :aria-controls="`collapse-${facetGroup.name.replace(' ', '')}`">
  <h3 class="header header--4"> {{facetGroup.name}}<span v-for="selected in numSelectedFacetsDisplayPerType">({{ selected }})</span></h3>                        
</div>

numSelectedFacetsDisplayPerType: {
            get: function() {
                 const facets = store.state[this.moduleGroup].facets;
               
                 let result = [];
                 let newArray = [];

                 for (let i = 0; i < facets.length; i++) {
                    let facetValues = facets[i].values;
                    
                    for (let j = 0; j < facetValues.length; j++) {

                        let selected = facetValues[j]["selected"];
                        let keyVal = "selected-"+i;
                        newArray = [];

                        if (selected === true) {
                            facetValues.map(function(x) {
                                result = {}
                                if (x.selected === true) {
                                  result[keyVal] = x.selected;
                                  newArray.push(result);
                                }
                            })
                         }
                    }
                    return newArray.length;
                }
               
            }
        }

Solution

  • Here's how you can modify your computed property to return an array of counts:

    numSelectedFacetsDisplayPerType: {
      get: function() {
        const facets = store.state[this.moduleGroup].facets;
        let counts = []; // Array to store counts for each category
        
        for (let i = 0; i < facets.length; i++) {
          let facetValues = facets[i].values;
          let count = 0; // Initialize count for this category
          
          for (let j = 0; j < facetValues.length; j++) {
            if (facetValues[j]["selected"] === true) {
              count++;
            }
          }
          
          counts.push(count); // Add count for this category to the counts array
        }
        
        return counts;
      }
    }
    

    And here's how you can display the counts next to each category name.

    <div class="search-filters__group-category" v-on:click="toggleFilterAccordion(index)"
      :aria-expanded="isAccordionOpen.includes(index)"
      :aria-controls="`collapse-${facetGroup.name.replace(' ', '')}`">
      <h3 class="header header--4"> {{facetGroup.name}}
        <span v-for="(count, categoryIndex) in numSelectedFacetsDisplayPerType">
          ({{ count }})
          <!-- Display comma after count if not the last category -->
          <span v-if="categoryIndex !== numSelectedFacetsDisplayPerType.length - 1">,</span>
        </span>
      </h3>                        
    </div>
    

    I hope this helps you.