Vue table does not update when checkbox is unchecked

I am currently utilizing Daisy UI and basic VUE to create a checkbox functionality. When I check the checkbox, it successfully filters the table entries; however, when I uncheck or check another checkbox, the filter does not refresh again.

Below is my table component:

import { ref, onMounted, watch } from 'vue';
import currencyHelpers from '../lib/currencyHelpers';

const info = ref({});
const currencies = ref([]);
const headers = [
  { title: 'Name' },
  { title: 'ID' },
  { title: 'ID rego fee' },
  { title: 'ID import fee' },
  { title: 'Converter Name' },
  { title: 'Proof Protocol' },
  { title: 'Options' }
];
const options = [
  { value: 1, label: 'OPTION_FRACTIONAL' },
  { value: 2, label: 'OPTION_ID_ISSUANCE' },
  { value: 4, label: 'OPTION_ID_STAKING' },
  { value: 8, label: 'OPTION_ID_REFERRALS' },
  { value: 16, label: 'OPTION_ID_REFERRALREQUIRED' },
  { value: 32, label: 'OPTION_TOKEN' },
  { value: 128, label: 'OPTION_GATEWAY' },
  { value: 256, label: 'OPTION_PBAAS' },
  { value: 512, label: 'OPTION_PBAAS_CONVERTER' }
];
const selectedCurrency = ref(null);
const currencyDetails = ref('');
const selectedOptions = ref([]); // Array for storing selected options

const handleCurrencyClick = (currency) => {
  console.log(currency.currencydefinition.currencyid)
  const fullyQualifiedName = currency.currencydefinition.fullyqualifiedname;
  console.log("Clicked currency:", fullyQualifiedName);
  selectedCurrency.value = currency;
};

// Function to filter currencies based on selected options
const filterCurrencies = () => {
  if (selectedOptions.value.length === 0) {
    return currencies.value; // Return all currencies if no options are selected
  }

  return currencies.value.filter(currency => {
    return selectedOptions.value.every(option => {
      // Check if the currency has the selected option
      return (currency.currencydefinition.options & option) !== 0;
    });
  });
};

onMounted(async () => {
  info.value = await currencyHelpers.getInfo();
  currencies.value = await currencyHelpers.listCurrencies();
});

// Watch for changes in selectedOptions and filter currencies accordingly
watch(selectedOptions, () => {
  currencies.value = filterCurrencies();
});
<template>
  <div class="overflow-x-auto columns-1">
    <div class="collapse collapse-arrow bg-base-200">
      <input type="checkbox" /> 
      <div class="collapse-title text-xl font-medium">
         Filter Currencies
      </div>
  <div class="collapse-content"> 
      <div class="form-control border mt-1 pt-1">
          <label v-for="(option, index) in options" :key="index">
           <input type="checkbox" :value="option.value" class="checkbox checkbox-primary" v-model="selectedOptions"> <span class="label-text">{{ option.label }}</span>
          </label>
      </div>
  </div>
    </div>
    <div>
      <table class="table">
        <thead>
          <tr>
            <th v-for="header in headers" :key="header.title">{{ header.title }}</th>
          </tr>
        </thead>
        <tbody>
          <tr class="hover" v-for="currency in currencies" :key="currency.currencydefinition.currencyid">
            <td @click="handleCurrencyClick(currency)">{{ currency.currencydefinition.fullyqualifiedname }}</td>
            <td>{{ currency.currencydefinition.currencyid }}</td>
            <td>{{ currency.currencydefinition.idregistrationfees }}</td>
            <td>{{ currency.currencydefinition.idimportfees }}</td>
            <td>{{ currency.currencydefinition.gatewayconvertername }}</td>
            <td>{{ currency.currencydefinition.proofprotocol }}</td>
            <td>{{ currency.currencydefinition.options }}</td>
          </tr>
        </tbody>
      </table>
    </div>
    <div v-if="selectedCurrency">
      <h2>Selected Currency Details</h2>
      <textarea rows="5" cols="50">{{ selectedCurrency }}</textarea>
    </div>
  </div>
</template>

The above implementation uses basic vue/html components. I made the decision to completely eliminate Vuetify from my project in favor of styling my components with Daisy UI classes.

The data fetched from the currencyHelpers Library originates from a TS library. The "options" attribute within the response determines what gets displayed in the table.

Answer №1

My Approach to Developing the Logic

Given the lack of sufficient data for an accurate replication, I opted to create a simplified example instead.

Within my code, users have the flexibility to select options ranging from 1 to 10. If no options are chosen, all currencies will be displayed. However, if at least one option is selected, only the corresponding items from currencies will be shown. To achieve this functionality, I utilized a filtering mechanism similar to your own code, where I replaced the displayed array with a listener.

To prevent the loss of the original currencies data post-override, I securely stored them in a separate array named defaultCurrencies.

Resolution for Missing defaultCurrencies, Overwriting Initial Data

There seems to be a flaw in your logic at this juncture. You retrieve the currencies data in the onMounted hook. Subsequently, whenever you alter the selectedOptions, the currencies data will be overwritten. Consequently, after the initial overwrite, the original data becomes inaccessible, leaving only the filtered values behind. Hence, when the filters are removed, reverting to the original array becomes impossible due to its absence.

const defaultCurrencies = ref([]) // Location of the issue
const currencies = ref([])

const filterCurrencies = () => {
  if (selectedOptions.value.length === 0) {
    return defaultCurrencies.value // Location of the issue
  }

  return defaultCurrencies.value.filter(currency => {
    return selectedOptions.value.every(option => {
      return (currency.currencydefinition.options & option) !== 0
    })
  }) // Location of the issue
}

onMounted(async () => {
  info.value = await currencyHelpers.getInfo()
  defaultCurrencies.value = await currencyHelpers.listCurrencies() // Location of the issue
})

currencies.value = filterCurrencies()
watch(selectedOptions, () => {
  currencies.value = filterCurrencies()
})

Illustrative Scenario # 1 (with watch integration as referenced)

const { createApp, ref, watch } = Vue

const app = createApp({
  setup() {
    const options = ref([
      { value: 1, label: '1' },
      { value: 2, label: '2' },
      { value: 3, label: '3' },
      { value: 4, label: '4' },
      { value: 5, label: '5' },
      { value: 6, label: '6' },
      { value: 7, label: '7' },
      { value: 8, label: '8' },
      { value: 9, label: '9' },
      { value: 10, label: '10' },
    ])
    const selectedOptions = ref([])
    
    // Separating the original data array management from the displayed data array
    const defaultCurrencies = [
      { id: 1, name: 'First' },
      { id: 2, name: 'Second' },
      { id: 3, name: 'Third' },
      { id: 4, name: 'Fourth' },
      { id: 5, name: 'Fifth' },
      { id: 6, name: 'Sixth' },
      { id: 7, name: 'Seventh' },
      { id: 8, name: 'Eighth' },
      { id: 9, name: 'Ninth' },
      { id: 10, name: 'Tenth' },
    ]
    // Displayed data array
    const currencies = ref([])
    // Manipulating the displayed data array (currencies) using defaultCurrencies
    const filterCurrencies = () => {
      if (selectedOptions.value.length === 0) {
        return defaultCurrencies
      }
      return defaultCurrencies.filter(currency => selectedOptions.value.includes(currency.id))
    }
    
    // Incorporating watch feature
    currencies.value = filterCurrencies()
    watch(selectedOptions, () => {
      currencies.value = filterCurrencies()
    })
    
    return { options, selectedOptions, currencies }
  }
})
app.mount('#app')
<script src="https://unpkg.com/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="b3cddbcbbb80ad85bfababb3">[email protected]</a>/dist/vue.global.prod.js"></script>

<div id="app">
  <span v-for="(option, index) in options" :key="index">
    <input type="checkbox" :value="option.value" v-model="selectedOptions">
    <label>{{ option.label }}</label>
  </span>
  
  <p>Selected: {{ selectedOptions }}</p>
  <div>
    <p v-for="(currency, index) in currencies" :key="currency.id">- {{ currency.name }}</p>
  </div>
</div>

Illustrative Scenario # 2 (employing computed method)

const { createApp, ref, computed } = Vue

const app = createApp({
  setup() {
    const options = ref([
      { value: 1, label: '1' },
      { value: 2, label: '2' },
      { value: 3, label: '3' },
      { value: 4, label: '4' },
      { value: 5, label: '5' },
      { value: 6, label: '6' },
      { value: 7, label: '7' },
      { value: 8, label: '8' },
      { value: 9, label: '9' },
      { value: 10, label: '10' },
    ])
    const selectedOptions = ref([])
    
    // Separating the original data array management from the displayed data array
    const defaultCurrencies = [
      { id: 1, name: 'First' },
      { id: 2, name: 'Second' },
      { id: 3, name: 'Third' },
      { id: 4, name: 'Fourth' },
      { id: 5, name: 'Fifth' },
      { id: 6, name: 'Sixth' },
      { id: 7, name: 'Seventh' },
      { id: 8, name: 'Eighth' },
      { id: 9, name: 'Ninth' },
      { id: 10, name: 'Tenth' },
    ]
    // Modifying the displayed data array (currencies) using defaultCurrencies
    const filterCurrencies = () => {
      if (selectedOptions.value.length === 0) {
        return defaultCurrencies
      }
      return defaultCurrencies.filter(currency => selectedOptions.value.includes(currency.id))
    }
    // Displayed data array
    const currencies = computed(filterCurrencies)
    
    return { options, selectedOptions, currencies }
  }
})
app.mount('#app')
<script src="https://unpkg.com/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="72ebeacaf59be4efe5eceaa4e9ebec99eeeeeae6eaefecea">[email protected]</a>/dist/vue.global.prod.js"></script>

<div id="app">
  <span v-for="(option, index) in options" :key="index">
    <input type="checkbox" :value="option.value" v-model="selectedOptions">
    <label>{{ option.label }}</label>
  </span>
  
  <p>Selected: {{ selectedOptions }}</p>
  <div>
    <p v-for="(currency, index) in currencies" :key="currency.id">- {{ currency.name }}</p>
  </div>
</div>

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

Is there a way to prevent Accordion propagation once it has been clicked for the first time?

I am facing a challenge with my accordion setup in Material-UI. I have an Accordion that contains a TextField inside the AccordionSummary. When the TextField is clicked, it opens the AccordionDetails where the rest of the form is displayed. However, I&apos ...

Is concealing content using Javascript or jQuery worth exploring?

While I have been hiding content using display:none; in css, there are concerns that Google may not like this approach. However, due to the needs of jQuery animations, it has been necessary for me. Recently, I have come across a new method for hiding conte ...

Personalize the marker design within the Wikitude SDK using JavaScript

Currently, I am developing an augmented reality view in Android using the wikitude-sdk. As part of the project, I am displaying markers on the screen and now I am looking to customize the marker view using the AR.HtmlDrawable method offered by the ...

Placing information within a nested array with multiple levels of nesting

I'll try to keep this concise, Here is the structure of the schema... import mongoose from 'mongoose' const QuestionSchema = mongoose.Schema({ questionTitle: { type: String, required: " title"}, questionBody: { type: Stri ...

What is the proper way to search for a specific string within a JavaScript array during an iteration?

I am working with an array that is continuously updated with new string elements every 2 seconds. The code snippet below showcases how the updates are processed: //tick world setInterval(function(){ doTradeUpdate(); },5000); function doTradeUpdate(){ ...

Executing a file function from another within a module function in ReactJS

I need to utilize the functions that are defined in the apiGet.js file: export let apiGet = () => { return 'File One'; } These functions are being called in another module called brand.js. Here is the code snippet: require("../action ...

Use Protractor to simulate Loss Connection by clearing LocalStorage in a Spec

Currently, I am utilizing the code window.localStorage.removeItem("name of localStorage variable you want to remove"); to eliminate two distinct localStorage Keys within a particular specification, and it is successfully removing them. Afterwards, I proce ...

Utilizing DOMStringMap data to populate CSS URLs

I am attempting to create a universal CSS modification for a webpage element that resembles: <button data-action="link" class="cardImageContainer coveredImage cardContent itemAction lazy lazy-image-fadein-fast" data-blurhash="lo ...

Categorize elements in an array based on a specific keyword

Struggling with my AngularJS (1) application, I can't seem to figure out how to split an array of items into separate arrays grouped by item. In simpler terms, I have an array with different items and I want to group them by their uuid like this: [ ...

Exploring the intersecting viewports in three.js

I'm attempting to create a camera (GUI camera) that renders above the scene camera. My idea was to make the GUI camera have a transparent background, allowing for visibility through it. However, it's not working as expected. Here is how I define ...

MaterialUI makeStyles in NextJS causes custom css to revert back when the page is refreshed

Currently, I am working on a NextJS website with some unique styling applied through MaterialUI's makeStyles. Initially, everything looks perfect but then all the custom styling is reset on the second load. It seems to be related to the route, as it o ...

The Card Component from Core UI fails to appear in the Print Preview feature

I'm currently experimenting with the Card Component from the Core UI framework. However, I'm facing an issue where the color of the Card component and its associated icon do not appear in the Preview when trying to print the page. I attempted to ...

Ways to direct to a specific div upon clicking an anchor tag following a page reload?

<a href="#goto">Link 1</a> <div id="goto">DIV</div> Whenever I click on the anchor tag, my webpage reloads and displays a new div with the ID of goto. This div was previously hidden but is now visible at the bottom of the page. I ...

Instead of using a computed getter/setter, make use of mapState and mapMutations to simplify

Currently, I am syncing a computed value to a component and using a computed setter when it syncs back from the component. I'm wondering if there is a more concise way to replace a computed getter/setter with mapState and mapMutations. How can this b ...

Is there a way to detect in the browser when headphones have been unplugged?

Is there an event to pause the video when the audio device changes, like if headphones get unplugged? I've looked into other questions, but they don't seem to be for browser. Detecting headphone status in C# Detecting when headphones are plugg ...

Utilizing the @page CSS rule in Vue.js: A step-by-step guide

I am facing an issue with printing a specific page in landscape mode. Here is the code snippet I have been using: @page { margin: 0; size: A4 landscape; } The problem is that this style rule affects all pages in my application because all style se ...

grab the content from a text editor and insert it into a div element

Currently, I am trying to extract text from my content editable div and place it in another div (similar to the one seen on stack overflow). However, I am encountering a frustrating issue. 1. My content div seems to be lagging behind. When I type in my ed ...

A pale tooltip with a light arrow appearing against a soft white backdrop

Can someone help me figure out how to display a white tooltip with a white arrow? I've tried to implement it using the code below, but the white color is not visible against the background. Any suggestions on making it stand out? $(function () { ...

UCS-2 in Node.JS: Understanding Big-Endian Byte Order

Currently, I am utilizing Node.JS. In my project, I require support for big-endian UCS-2 buffers, which is not natively offered by Node's buffers that only support little-endian format. How can I achieve this specific requirement? ...

The ion-slide-box does not function properly the first time the HTML page is loaded

Upon loading the page, my ion-slide-box does not function correctly. However, if I refresh the page, it works as expected. I have tried referring to some links but have been unable to resolve this issue on my own. Any assistance would be greatly appreciate ...