Search code examples
javascriptvue.jsvuejs2quasar-frameworkquasar

Input value disappears in multiple filtering form implemented in Vue.js and Quasar


I'm now trying to make multiple-item filtering in Quasar, Vue's framework.

I'm currently using input and checkbox. There seems to be no problem, but the select item disappears.

The following is the ideal flow.

  1. Apple and apricot are displayed when "a" checkbox is selected.
  2. And if i select apple in input, only apple is displayed.

Where should I fix the code?

Here's Codepen

<div id="q-app">
  <q-layout view="hHh lpR fFf">

    <q-header elevated class="bg-primary text-white">
      <q-toolbar>
        <q-btn dense flat round icon="menu" @click="left = !left"></q-btn>

        <q-toolbar-title>
          Header
        </q-toolbar-title>
      </q-toolbar>
    </q-header>

<q-drawer v-model="left" side="left" bordered>
    <q-scroll-area
            style="height: calc(100% - 53px); margin-top: 53px;">
        <q-list>
            <q-expansion-item
                    expand-separator
                    icon="ion-reorder"
                    label="abc"
                    default-opened
            >
                <div class="row">
                    <q-checkbox
                            v-model="checkFilter"
                            v-for="item in sort_abc"
                            class="col-xs-12 col-sm-6 col-md-6"
                            :key="item"
                            :val="item"
                            :label="item"
                            color="orange"
                    ></q-checkbox>
                </div>
            </q-expansion-item>
        </q-list>
    </q-scroll-area>
    <div class="absolute-top bg-base layout-drawer-toolbar" style="height: 50px;">
        <q-select filled
                  v-model="inputFilter"
                  use-input
                  hide-selected
                  fill-input
                  input-debounce="0"
                  @filter="filterFn"
                  :options="sample_list"
                  class="full-width full-height"
                  placeholder="Search"
                  style="height: 50px;"
                  clearable
                  color="orange"
        >
            <template v-slot:no-option>
                <q-item>
                    <q-item-section class="text-grey">
                        no result
                    </q-item-section>
                </q-item>
            </template>
        </q-select>
    </div>
</q-drawer>

    <q-page-container>
      <template>
        <div class="q-pa-md row items-start q-col-gutter-md">
          <q-card class="my-card" v-model="filteredData" v-for="(item, index) in filteredData">
      <q-card-section>
        <div class="text-h6">{{ item.name }}</div>
        <div class="text-subtitle2">{{ index }}</div>
      </q-card-section>
                            </q-card>
        </div>
      </template>
    </q-page-container>

    <q-footer elevated class="bg-grey-8 text-white">
      <q-toolbar>
        <q-toolbar-title>
          Footer
        </q-toolbar-title>
      </q-toolbar>
    </q-footer>

  </q-layout>
</div>
let Fruits = ['apple', 'apricot', 'banana', 'orange'];

new Vue({
  el: '#q-app',
  data: function () {
    return {
      left: true,
      version: Quasar.version,
      sort_name_select:[],
      sort_abc:['a', 'b', 'c'],
      sort_abc_select:[],
      sample_list:Fruits,
      card_list: [
      {name: "banana", val:"b"},
      {name: "apple", val:"a"},
      {name: "apricot", val:"a"},
      {name: "orange", val:"o"}
      ]
    }
  },
  methods: {
    filterFn(val, update, abort) {
                    update(() => {
                        const needle = val.toLowerCase();
                        this.sample_list = Fruits.filter(v => v.toLowerCase().indexOf(needle) > -1);
                    })
                }
    },
  computed: {
    inputFilter:{
      get: function (x) {
        return this.sort_name_select;
      },
      set: function (y) {
        this.sort_name_select.length = 0;
        this.sort_name_select.push(y);
      }
    },
    checkFilter:{
      get: function (x) {
        return this.sort_abc_select;
      },
      set: function (y) {
        this.sort_abc_select = y;
      }
    },
    filteredData() {
      let self = this;
      return self.card_list
        .filter(function (post) {
          if(self.sort_abc_select.length !== 0){
            if (self.sort_abc_select.includes(post['val'])){
              return post['val'];
            }
          }else{
            return self.card_list;
          }
        })
       .filter(function (post) {
          if(self.sort_name_select.length !== 0){
            if (self.sort_name_select.includes(post['name'])){
              return post['name'];
            }else if(self.sort_name_select.includes(null)){
              return self.card_list;
            }
          }else{
            return self.card_list;
          }
        })
    }
  }
})

Solution

  • In order to show that select label, you computed property should be like :

      computed: {
        inputFilter:{
          get: function (x) {
            return this.sort_name_select[0];
          },
          set: function (y) {
            this.sort_name_select=[];
            this.sort_name_select.push(y);
          }
        },