cpppatrick
cpppatrick

Reputation: 759

Clear Filter Functionality Not Working Vue

I'm working on a filtering feature in a Vue application. I'm new to Vue, and I have the filter semi-working. It successfully allows me to select an asset type from the dropdown, and will filter the results accordingly. But what's not working is the clearFilters method.

My goal is to reset the assetType to an empty string and the filterResults array to empty, and my thought was that since checking the length of filterResults, when I clear it it would return to displaying the entire un-filtered array.

What am I doing wrong? Any information would be greatly appreciated.

<template>
  <div ref="content">
    <div class="container pt-3 text-center">
      <div class="filter-container">
        <div class="btn-group">
          <button
            v-ripple="'rgba(255, 255, 255, .2)'"
            @click="showAssetType = !showAssetType"
            class="btn btn-secondary dropdown-toggle"
            data-toggle="dropdown"
            aria-haspopup="true"
            aria-expanded="false"
            style="max-height: 40px;">
            {{assetType ? assetType : 'Asset Type'}}
          </button>
          <div class="dropdown-menu" :style="'display:' + (showAssetType ? 'block' : 'none') + ';'">
            <a class="dropdown-item" @click.prevent="setAssetFilter('all')" href="#!">All Assets</a>
            <a class="dropdown-item" @click.prevent="setAssetFilter('USD'); filterByAssetType()" href="#!">USD</a>
            <a class="dropdown-item" @click.prevent="setAssetFilter('GBP'); filterByAssetType()" href="#!">GBP</a>
            <a class="dropdown-item" @click.prevent="setAssetFilter('CAD'); filterByAssetType()" href="#!">CAD</a>
          </div>
        </div>
      </div>
    </div>

  <div id="data-table" v-if="filterResults.length > 0">
    <div v-for="(transaction, index) in filterResults" :key="index">
      <global-history-item>
        <template v-slot:header>
          <h1 class="date">{{formatDate(transaction.date)}}</h1>
            <div class="transaction-header-wrapper">
              <p class="transaction-text">{{formatString(transaction.tx_type)}} Transaction</p>
              <p class="transaction-text" style="text-align: right">{{transaction.coin_type}}</p>
            </div>
        </template>
        <template v-slot:content>
          <global-transaction :transaction='transaction' @updateClassType="updateClassType" />
        </template>
      </global-history-item>
    </div>
  </div>
  <div id="data-table">
    <div v-for="(item, index) in totalHistory" :key="index">
      <div v-if="item.tx_type">
        <global-history-item>
          <template v-slot:header>
            <h1 class="date">{{formatDate(item.date)}}</h1>
              <div class="transaction-header-wrapper">
                <p class="transaction-text">{{formatString(item.tx_type)}} Transaction</p>
              </div>
          </template>
          <template v-slot:content>
            <global-transaction :transaction='item' @updateClassType="updateClassType" />
          </template>
        </global-history-item>
      </div>
      <div v-else-if="item.invoice_id">
        <global-history-item>
          <template v-slot:header>
            <h1 class="date">{{formatDate(item.date)}}</h1>
            <div class="invoice-header-wrapper">
              <p class="invoice-text">Invoice Created</p>
              <p class="invoice-text">Invoice #{{item.invoice_id}}</p>
            </div>
          </template>
          <template v-slot:content>
            <global-invoice :invoice='item' />
          </template>
        </global-history-item>
      </div>
      <div v-else>
        <global-history-item>
          <template v-slot:header>
            <h1 class="date">{{formatDate(item.date)}}</h1>
            <div class="invoice-header-wrapper">
              <p class="invoice-text">Login Event</p>
              <br />
            </div>
          </template>
          <template v-slot:content>
            <global-account-activity :message='"A successful login to your account was made"' />
          </template>
        </global-history-item>
      </div>
    </div>
  </div>
  </div>
</template>

<script>
... imports removed for brevity

export default {
  name: 'Global',
  components: { },
  props: ['totalHistory', 'printFormat'],
  mixins: ['formatDate', 'formatMenuLabel'],
  data () {
    return {
      showAssetType: false,
      showClassType: false,
      activityType: '',
      assetType: '',
      filterResults: [],
      printMode: false
    }
  },
  methods: {
    setAssetFilter (value) {
      this.showAssetType = false
      this.assetType = value
    },
    formatString (str) {
      const firstLetter = str.charAt(0)
      const remainder = str.slice(1)
      return firstLetter.toUpperCase() + remainder
    },
    updateClassType (transactionRecord) {
      this.$store.dispatch('updateTransactionType', transactionRecord)
    },
    updateTransaction (transactionRecord) {
      console.log('in updateTransaction', transactionRecord)
      this.$store.dispatch('updateTransactionNote', transactionRecord)
    },
    filterByAssetType () {
      const selectedCurrency = this.assetType
      if (this.assetType === 'all') {
        this.clearFilters()
      } else {
        this.filterResults = this.totalHistory.filter(function (trans) {
          return trans.currency === selectedCurrency
        })
      }
    },
    clearFilters () {
      return (this.assetType = '') && (this.filterResults = [])
    }
  }
}
</script>

Upvotes: 1

Views: 525

Answers (2)

Tim
Tim

Reputation: 1229

I agree with Jens rewrite of clearFilters(). The original looked odd to me.

I had started creating a sample component to demonstrate possibly simplifying the filtering process when there were no answers. Since I have finished it and it works, I am posting it.

ClearFilters.vue

<template>
  <div class="clear-filters">
    <div class="row">
      <div class="col-md-6">
        <table class="table table-bordered">
          <thead>
            <tr>
              <th>NAME</th>
              <th>CURRENCY</th>
            </tr>
          </thead>
          <tbody>
            <tr v-for="asset in filteredAssets" :key="asset.id">
              <td>{{ asset.name }}</td>
              <td>{{ asset.currency }}</td>
            </tr>
          </tbody>
        </table>
      </div>
      <div class="col-md-6">
        <div class="form-group">
          <label class="criteria-label">FILTER CRITERIA:</label>
          <select class="form-control" v-model="currentCriteria">
            <option v-for="(criteria, index) in criteriaOptions" :key="index" :value="criteria">{{ criteria }}</option>
          </select>
        </div>
        <button type="button" class="btn btn-secondary" @click="resetFilter">Reset</button>
      </div>
    </div>
  </div>
</template>

<script>
  import assets from './clear-filters-data.js';

  export default {
    data() {
      return {
        assets: assets,
        criteriaOptions: [
          'ALL', 'USD', 'GBP', 'CAD'
        ],
        currentCriteria: 'ALL'
      }
    },
    computed: {
      filteredAssets() {
        if (this.currentCriteria === 'ALL') {
          return this.assets;
        }
        else {
          return this.assets.filter( asset => asset.currency === this.currentCriteria);
        }
      }
    },
    methods: {
      resetFilter() {
        this.currentCriteria = 'ALL';
      }
    }
  }
</script>

<style scoped>
  .criteria-label {
    font-weight: bold;
  }
</style>

Test data:

const assets = [
  {
    id: 1,
    name: 'asset1',
    currency: 'USD'
  },
  {
    id: 2,
    name: 'asset2',
    currency: 'USD'
  },
  {
    id: 3,
    name: 'asset3',
    currency: 'USD'
  },
  {
    id: 4,
    name: 'asset4',
    currency: 'GBP'
  },
  {
    id: 5,
    name: 'asset5',
    currency: 'GBP'
  },
  {
    id: 6,
    name: 'asset6',
    currency: 'GBP'
  },
  {
    id: 7,
    name: 'asset7',
    currency: 'CAD'
  },
  {
    id: 8,
    name: 'asset8',
    currency: 'CAD'
  },
  {
    id: 9,
    name: 'asset9',
    currency: 'CAD'
  },
]

export default assets;

Upvotes: 1

Jens van Hellemondt
Jens van Hellemondt

Reputation: 436

So if I am not mistaking, you only want the method clearFilters, to work? If so, try:

    clearFilters () {
      this.assetType = ''
      this.filterResults = []
    }

The logical AND operator (&&) is not to chain expressions. It’s to do an expression if the first expression is truthy.

First expression && second expression, example

  const questionAnswered = true
  console.log(questionAnswered && "Hooray!")
  // will log "Hooray!" (Expression 2)

If you set questionAnswered to false, it will log false (expression 1)

Upvotes: 1

Related Questions