Home > database >  What is happening with this search filter in Vue 2?. Cant render items?
What is happening with this search filter in Vue 2?. Cant render items?

Time:10-23

I have been trying to solve this problem for more than a week, but finally I am forced to ask for help.

I am just implementing a search filter in Vue 2, using Vuetify, but something is going wrong

This is how the search filter looks:

  <v-text-field v-model="search" label="Look for name..."></v-text-field>

I have a variable called search in the component data that is two-binding with the text-field v-model

Secondly, I have an array of items:

items: [
  {
    default: true,
    name: 'Text 1',
  },
  {
    default: false,
    name: 'Text 2',
  },
  {
    default: false,
    name: 'Text 3',
  },
  {
    default: false,
    name: 'Text 4',
  },
],

I render the list in a div using v-for

<div v-for="(item, index) in filteredItems">
    <div style="display: flex">
      <input
        type="radio"
        :checked="item.default"
        @click="changeDefault(item, index)"
      />
      <h1>{{ item.name }}</h1>
    </div>
  </div>

This is how the component looks: List and search filter rendered

How the filter works? Here is the code

filteredItems() {
  if (this.search) {
    return this.items.filter((item) => {
      return item.name.toLowerCase().match(this.search);
    });
  } else {
    return this.items;
  }
},

As you can see in the rendered list, items have a radio button which can be selected. When some of them are clicked, we call a function called changeDefault whose code is this (just get the default true item and set it to false, and the new one to true)

changeDefault(item, index) {
  let indexOfDefaultTrue = this.items.findIndex((item) => item.default === true);
  this.items[indexOfDefaultTrue].default = false;
  this.items[index].default = true;
},

All seems to be working, but the issue is that, if i search for Text 2 (for instance) and click the radio button, it turns to active, but when i clear the filter, it seems like nothing happened It only happens if i use the search method, if i click an item on the initial list, radio button changes properly. Text 2 search After i clear the search

It looks like the list didnt render the new items or something like that? Im big stucked. Thank you very much, i wish someone can help me!

<template>
  <v-app>
    <v-main>
      <v-text-field v-model="search" label="Look for name..."></v-text-field>
      <div v-for="(item, index) in filteredItems">
        <div style="display: flex">
          <input
            type="radio"
            :checked="item.default"
            @click="changeDefault(item, index)"
          />
          <h1>{{ item.name }}</h1>
        </div>
      </div>
    </v-main>
  </v-app>
</template>

<script>
export default {
  name: 'App',

  components: {},

  data: () => ({
    search: '',

    items: [
      {
        default: true,
        name: 'Text 1',
      },
      {
        default: false,
        name: 'Text 2',
      },
      {
        default: false,
        name: 'Text 3',
      },
      {
        default: false,
        name: 'Text 4',
      },
    ],
  }),
  methods: {
    changeDefault(item, index) {
      console.log(item);
      let indexOfDefaultTrue = this.items.findIndex((item) => item.default === true);
      console.log(indexOfDefaultTrue);
      this.items[indexOfDefaultTrue].default = false;
      this.items[index].default = true;
      console.log(this.items);
    },
  },
  computed: {
    filteredItems() {
      if (this.search) {
        return this.items.filter((item) => {
          return item.name.toLowerCase().match(this.search);
        });
      } else {
        return this.items;
      }
    },
  },
};
</script>

CodePudding user response:

Full Answer:

The problem with the code is that you are using the item index within function 'changeDefault', you should instead use the name of the item, because the index is dynamic, so if you search for 'Text 2', the index that would be used is 0, and not 1:

function changeDefault(clickedItem) {
  
      let indexOfDefaultTrue   = items.findIndex((item) => item.default === true);
      let indexOfbuttonClicked = items.findIndex((item) => item.name === clickedItem.name);

      items[indexOfDefaultTrue].default = false;
      items[indexOfbuttonClicked].default = true;

    }

And the input radio:

   <input
            type="radio"
            :checked="item.default"
            @click="changeDefault(item)"
          />

Linked to the code: https://sfc.vuejs.org/#eNqtVMFuozAQ/ZWRLyFSCurunrKh2lX3UqnSXnqre3BhaGjBRrZJEyH fcc2BGi36qUgJcx45nnmzbM79rtp4kOLbMt2JtNlY8GgbZsrLsu6UdpCBxqLDf2IzJYH3ECm6qa1mEMPhVY1rCh9xSWXmZLGQmmxNpCeE6J7LsE/3fgBkGMh2spuweoWN5Nfihq3sLrDo4VLAg3e/hzxP4hCVOYjjG9fgPH9CzB vMN4WI EGRQ623vGimi1Wv cuCzKyqLG/GbgdKQ KlpJ5CoZrUMp065lAVFAjA ianEICI m0WoZRhQH8Chy1hrSq3ngIjR2ncRW3apX1NfCYLSOa2Gz/XIjqntM7iejByRaPipiCuOyJ0bcO/YG2V7IJ/wT I2yqsxeAhVvmq6QVCdzPP4thuA7UhUtpOdOZX7jAmbN saG2UGapl6JU9kzzMfWWiWvw/afYzqyPOCsYO8Mgx2m5DDu3xf9MJUU9HQuaJGxKGme45o4b0OccrlLwrGmA00GgTSVsEhW4K/rFhrrKWeuJtiVkhQHh4ta5VilnIWRcwaVePSOW6VeoFDa6z2OY84Sj 6z8/JAubRKgZ6nTWB1TX9LdXN2zhryjD1VSHl5aajmEx2wCo LsLG8uQfAnhqXpkVeKs6Wa9tsj44zWp8L4G3YLz87ClpK0A96GTv16svZX1513UwHfb9LyDfrLKHWJn4Gy41pNprpZRsWruGLWjTxs1GSLuog/mGBiNuOp4szuoqdzdne2sZsk8QUmbven02s9FNCX7FupS1pUmjqi0etXg1qAg5duVPI n9gVOSo

CodePudding user response:

It sounds like 'filteredItems' is not reactive, is it a computed function? As it sounds like it's not rerunning every time 'this.search' is changing.

If you have a larger example of the code, I can take a look.

  • Related