Explore multiple options and apply filters using Vuex

I've been working on filtering data in my vuex store, but I'm encountering some issues. When I select just one option, it filters and displays the checked item correctly. However, if I check multiple options, it doesn't display anything...

Below is what I have done so far.

UPDATED codesandbox

Here is a complete example of the situation I am facing. You can view it here: https://codesandbox.io/s/vue-template-oxwtk

filter.js

export function getByRooms(articles, room) {
    if (room.length == 0) {
        return articles;
    } else {
        return articles.filter(article => {
            if (article.rooms1.includes(room)) {
                return article;
            }
        })
    }
} 

store.js

I imported the function in store.js and used it as shown below.

state: {
    articles: [],
    rooms: [],
},

mutations: {
    setArticles(state, articles){
        state.articles = articles;
    },
    setRooms(state, room){
        state.rooms = room;
    },
},
getters: {
    loadArticles(state){
        return state.articles;
    },

    // filters
    loadAllFilters(state){
        return getByRooms(state.articles, state.rooms);
    },
},

component In the component, I implemented it as follows.

<p>rooms</p>
<ul class="inputWrap checks">
    <li  :key="index" v-for="(item, index) in uniqueRoom">
        <vs-checkbox v-model="findRooms" :vs-value="item">{{item}}</vs-checkbox>
    </li>
</ul>

findRooms: {
    set(val){
        this.$store.commit("setRooms", val);
    },
    get(){
        return this.$store.state.articles.rooms;
    }
},

Everything seems to be functioning well so far. I can check and filter the data based on selected rooms. But when I select more than one room, it doesn't show anything. Even though the state rooms:[] in store.js is an array, indicating that I should be able to select multiple rooms. However, selecting a second room or more clears out the data filtered by loadAllFilters...

I'm a bit stuck at this point. It may be a simple issue to resolve, but I haven't been able to pinpoint the problem yet.

Answer №1

I took a shot at creating a full example based on the code you provided:

function organizeByRooms(data, rooms) {
  if (rooms.length === 0) {
    return data;
  }
    
  return data.filter(item => {
    return rooms.some(room => item.rooms1.includes(room))
  });
} 

const storage = new Vuex.Store({
  state: {
    data: [
      {rooms1: ['red', 'green', 'blue']},
      {rooms1: ['red']},
      {rooms1: ['yellow', 'green']},
      {rooms1: ['blue', 'yellow']},
      {rooms1: ['red', 'blue']}
    ],
    rooms: [],
  },

  mutations: {
    updateData(state, articles){
      state.data = articles;
    },
    setRoomSelection(state, room){
      state.rooms = room;
    },
  },
  getters: {
    loadData(state){
      return state.data;
    },

    // filters
    loadAllFilters(state){
      return organizeByRooms(state.data, state.rooms);
    },
  }
});

new Vue({
  el: '#app',
  store: storage,
  
  computed: {
    manageRooms: {
      set(val){
        this.$store.commit("setRoomSelection", val);
      },
      get(){
        return this.$store.state.rooms;
      }
    },
    uniqueRoom() {
      const rooms = {};
      
      for (const item of this.$store.state.data) {
        for (const room of item.rooms1) {
          rooms[room] = true;
        }
      }
      
      return Object.keys(rooms);
    }
  }
});
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<link href="https://unpkg.com/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="196f6c7c6a7861592a37203729">[email protected]</a>/dist/vuesax.css" rel="stylesheet">
<script src="https://unpkg.com/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="2254574762100c140c1312">[email protected]</a>/dist/vue.js"></script>
<script src="https://unpkg.com/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="5d2b2838251d6e736c73786d">[email protected]</a>/dist/vuex.js"></script>
<script src="https://unpkg.com/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="2a5c5f4f594b526a190413041a">[email protected]</a>/dist/vuesax.umd.js"></script>
<div id="app">
  <p>rooms</p>
  <ul class="inputWrap checks">
    <li  :key="index" v-for="(item, index) in uniqueRoom">
      <vs-checkbox v-model="manageRooms" :vs-value="item">{{item}}</vs-checkbox>
    </li>
  </ul>
  <ul>
    <li v-for="item in $store.getters.loadAllFilters">
      {{ item.rooms1 }}
    </li>
  </ul>
</div>

In my implementation, I made the assumption that each item should match at least one of the chosen checkboxes rather than all of them. To modify it to match all of them instead, simply switch from using rooms.some to rooms.every.

I noticed an incorrect line:

return this.$store.state.articles.rooms;

I assumed it should be:

return this.$store.state.rooms;

The primary change I made was revising the organizeByRooms function to utilize some.

Also, note that the function within filter should only output a true/false result to decide whether an item should be included or not. In your initial code, you had this:

if (article.rooms1.includes(room)) {
    return article;
}

Returning article is considered truthy, but it would work equally well by just returning true. It could be simplified down to:

return article.rooms1.includes(room);

My upgrade of organizeByRooms extends this logic to check each of the selected rooms rather than assuming there's only one.

Update:

Upon reviewing the CodeSandbox example you added, the issue becomes clearer...

Modify this line:

if (car.color.includes(color)) {

to this:

if (color.includes(car.color)) {

Or even better:

return cars.filter(car => color.includes(car.color))

The problem lies in mistakenly swapping color and car.color.

color represents an array while car.color symbolizes a string. Both strings and arrays have an includes method. The string variant will implicitly transform the argument into a string. For instance, this will yield true:

'red'.includes(['red'])

The array will convert to a string through toString, producing the string 'red' and causing 'red'.includes('red') to equate to true.

However, with two values, the test fails. This translates to:

'red'.includes(['red', 'purple'])

Now the array changes to the string 'red,purple', so it corresponds to 'red'.includes('red,purple'), resulting in false.

Your actual intent was probably to perform the test the other way around, essentially this:

['red', 'purple'].includes('red')

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Inquiring about JavaScript's substring method in String.prototype

let vowels = "AEIOU"; let result = vowels.substring(0, 3); document.write(result); I'm puzzled as to why the output is AEI instead of AEIO. Is this due to the indexing starting from zero in programming languages? ...

Having trouble updating textures when clicking a button in Aframe

I'm attempting to load a gltf model and change the texture on button click using the register component. The model loads and displays as expected, but I'm having trouble reflecting any changes when the button is clicked for the texture change. H ...

Pinia fails to initialize in Vue.js router

I've been experimenting with Pinia for state management in my Vue application, but I've encountered an issue where Pinia is being used before it's initialized in the main.js file. Below is the code snippet from the routes file: import { cre ...

Leveraging jQuery or javascript to display json data in a table with multiple columns

My goal is to convert a JSON data into an HTML table that dynamically creates columns based on the content of the JSON. However, I am facing challenges in looping through the JSON and rendering multiple columns when necessary. The desired output for the e ...

Creating an Ionic 3 canvas using a provider

I recently followed a tutorial on integrating the canvas API into Ionic, which can be found at this link. However, I encountered an issue where all the canvas-related functions had to be placed within the pages class, making it quite cumbersome as these f ...

Using Vue to access values in v-model:

I need to implement validations for a form with 30 fields by using getters and setters. However, it seems I cannot have computed and data values with the same name. Some examples suggest that setting the model and the computed property as the same can wor ...

How can I dynamically alter the color of a table row without using _rowVariant?

I am utilizing a bootstrap-vue table to showcase information retrieved from a JSON file. One piece of information I receive is an integer labeled "Status", and I aim to adjust the row's color based on this variable. For instance, if the Status equals ...

What is the process for passing parameters to a Node.js script when using PHP exec()?

I have encountered an issue with implementing iOS push notifications. My PHP version has ceased functioning, and despite my efforts to troubleshoot and fix it, I have been unsuccessful in getting it operational again. However, I do have a node.js script th ...

Show the div just one time

Hey there, I'm trying to create a StackOverflow-like message display at the top of my page. Everything is set up and configured, but I'm facing an issue - the message only shows up the first time. After that, it disappears. I've read that ...

I possess a high-quality image that I wish to resize while maintaining its resolution and clarity

I'm struggling with optimizing images for retina display on my website. I typically use the drawImage method, but I have a collection of large images (canvas drawn) that I want to use at half their size while maintaining image quality. Does anyone kn ...

Extract information from a JSON file to populate a jQuery Datatable

I am attempting to include data from a JSON file that was created using a Django script. Here is the structure of the JSON file: [ { "6": "yo1", "1": "2019-04-04", "4": "yo1", "3": "yo1", "2": "yo1", "5": "yo1" }, { "6": "yo2" ...

Is it possible for the connectedCallback() method within a Custom Component to have varying interpretations based on the specific context in which it is implemented?

I have recently developed a Custom Component that incorporates a Vue instance: class ContentCardExample extends HTMLElement { connectedCallback() { const card = document.createElement('div'); card.setAttribute("id", "app") card.i ...

Capture of Chrome pages is not possible when the extension has not been activated on the current page due to the absence of the activeTab permission

Hey there! I've encountered a tricky situation while trying to implement a Google extension. Due to technical limitations, I need to open the extension in a separate window as opposed to a disappearing pop-up, which is causing some issues with the fu ...

What is the best way to move a card when it appears on hover?

I recently implemented a map with interactive cards that appear when hovering over hotspots, all thanks to the amazing support I received on this platform. However, I have encountered a problem where the card appears to the right of the hotspot and gets cu ...

A straightforward angular implementation of a non-complicated slider interface

I am working on a web page that needs to display a large list of items. To manage the size, I want to show only 3 items at a time and include next/previous buttons for navigation. Although I am new to Angular, I was able to retrieve and display all the it ...

Ways to access states from a Vuex store within a Vuetify list in VueJs

Here is a snippet from my Vue file: import store from '@/store' export default{ name: 'myList', data: () => ({ show: true, listContent: [{ name: '1', icon: 'pers ...

How can I make a layer visible in OpenLayers?

I can't figure out what I'm doing wrong. I believe everything is written correctly: The HTML code I have looks like this: <b>&nbspSelect Area</b> <select id="mySelect_1" onchange="showSelectedArea();" > <op ...

Trouble with addClass failing to update CSS properties

I'm having trouble updating my add class. I'm attempting to create a sticky navigation bar, but the CSS on my site doesn't seem to be updating. None of the solutions I've found so far have been helpful. The website in question is antete ...

When applying the OWASP ESAPI encodeForHTMLAttribute method, I noticed that symbols are being rendered as their corresponding HTML entity numbers instead of the actual symbols

I recently started exploring OWASP ESAPI for preventing XSS and integrating the JavaScript version into my application. As per Rule #2 in the XSS prevention cheat sheet, it is recommended to "Attribute Escape" before inserting untrusted data into attribut ...

Pulling the month name based on a specific year and week using Javascript

In my HTML form, there are two fields called Year and Week. When the user chooses a Year and Week from the dropdowns, I would like to show the corresponding Month Name for that specific year and week. Is there anyone who can assist me in retrieving the m ...