【问题标题】:Filter array based on multiple options (Vue/JavaScript)基于多个选项的过滤器数组(Vue/JavaScript)
【发布时间】:2019-07-29 19:47:59
【问题描述】:

如果这是重复的帖子,我深表歉意。在发布之前,我搜索了一些不同的东西。我试图弄清楚如何根据两个选项过滤结果。我可以让其中一个选项起作用,但需要两个选项来推动结果。

我有 4 个计算属性:

  • filteredResults:进行过滤的位置
  • 阶段:根据结果收集所有阶段
  • results:原始结果列表(存储在 Vuex 中)
  • 状态:根据结果收集所有状态

在该组件的数据中,我有两个属性绑定到用户选择的内容。我正在过滤那些选定的值。

代码

<template>
  <div class="results">
    <Banner/>
    <div class="container">
      <div class="columns">
        <main role="main" class="column is-8-tablet is-9-widescreen">
          <p class="title is-4">Results for: {{ $route.query.q }}</p>
          <p class="subtitle">{{ results.length }} Trials Avaliable</p>
          <ul>
            <li v-for="trial in results" :key="trial.studyid">
              <div class="card" :data-location="trial.state" :data-phases="trial.phasename">
                <div class="card-content">
                  <div class="content">
                    <h2 class="title is-4">
                      <a href="void:javascript(0)" @click="goToDetail(trial.studyname)">
                        {{ trial.studyname }}
                      </a>
                    </h2>
                    <p>{{ trial.protocoltitle.replace('�', '') }}</p>
                    <p>Available in {{ trial.studyentitylocation.split('`').length -1 }} location(s)</p>
                  </div>
                </div>
              </div>
            </li>
          </ul>
        </main>
        <aside role="complementary" class="column is-4-tablet is-3-widescreen">
          <p class="title is-4">Filter Options</p>
          <button class="accordion">Locations</button>
          <div class="panel">
            <form>
              <div class="control">
                <label class="radio">
                  <input type="radio" name="states" value="All" v-model="checkedLocations">
                  All
                </label>
                <label class="radio" v-for="(state, i) in states" :key="i">
                  <input type="radio" name="states" :value="state" v-model="checkedLocations">
                  {{ state }}
                </label>
              </div>
            </form>
          </div>
          <button class="accordion">Phase</button>
          <div class="panel">
            <form>
              <div class="control">
                <label class="radio">
                  <input type="radio" name="phases" value="All" v-model="checkedPhases">
                  All
                </label>
                <label class="radio" v-for="(phase, i) in phases" :key="i">
                  <input type="radio" name="phases" :value="phase" v-model="checkedPhases">
                  Phase {{ phase }}
                </label>
              </div>
            </form>
          </div>
        </aside>
      </div>
    </div>
  </div>
</template>

<script>
import Banner from '@/components/Banner'

export default {
  name: 'Results',
  components: {
    Banner
  },
  data () {
    return {
      checkedLocations: 'All',
      checkedPhases: 'All'
    }
  },
  mounted () {
    this.activateAccordion()
  },
  computed: {
    results () {
      return this.$store.state.results
    },
    states () {
      let statesArray = []
      this.results.forEach((result) => {
        if (result.state) {
          var state = result.state

          state.forEach((item) => {
            if (statesArray.indexOf(item) === -1) {
              statesArray.push(item)
            }
          })
        }
      })
      return statesArray.sort()
    },
    phases () {
      let phaseArray = []
      this.results.forEach((result) => {
        if (result.phasename) {
          var phase = result.phasename

          phase.forEach((item) => {
            if (phaseArray.indexOf(item) === -1) {
              phaseArray.push(item)
            }
          })
        }
      })
      return phaseArray.sort()
    },
    filteredResults () {
      let results = ''
      if (this.checkedLocations !== 'All') {
        results = this.results.filter((result) => result.state.includes(this.checkedLocations))
        return results
      } else {
        return this.results
      }
    }
  }
}
</script>

这是应用在前端的样子 Trials App

我也是现代 JavaScript 语法的新手,所以请多多关照,哈哈。

【问题讨论】:

    标签: javascript vue.js ecmascript-6 vuex


    【解决方案1】:

    如果我理解你的话,看起来你可以根据checkedPhases添加另一个过滤器,类似于你已经拥有的过滤器?

    【讨论】:

    • 这是我最初的想法,我尝试过,但我可能做错了。我还需要检查 checkPhases 是否也不是“全部”。那么它会是这样的吗? if (this.checkedLocations !== 'All' || this.checkedPhases !== 'All') { results = this.results.filter((result) =&gt; result.state.includes(this.checkedLocations)) return results } else { return this.results }
    • 但是您没有添加第二个过滤器。我想过: results = this.results.filter(result => checkedLocations !== 'ALL' ? result.state.includes(this.checkedLocations) : result).filter(res => checkedPhases !== 'ALL' ? (你的第二个过滤器):res)
    • 对不起,我试图添加代码,然后它意外发布了评论,然后我被拉了一会儿。我会测试一下。
    • 嘿 Ravid,这似乎不起作用。我可以按位置过滤,但是当我尝试同时使用位置和阶段进行过滤时,它只会过滤位置选项。
    【解决方案2】:

    我创建了一个codepen 来尝试展示如何实现它。有一个包含 carID 和 cityID 的项目列表。此外,还有两个选择来过滤结果。当您更改一个选择时,它也会过滤另一个选择的选项。希望对你有帮助,有什么问题就问吧。

    const data = [
      {
       cityID: 1,
       carID:1,
       name: 'Ted'
      },
      {
       cityID: 1,
       carID:2,
       name: 'Tod'
      },
      {
       cityID: 2,
       carID:1,
       name: 'Michel'
      },
     {
       cityID: 3,
       carID:1,
       name: 'Romeu'
      },
      {
       cityID: 2,
       carID:3,
       name: 'Thomas'
      },
      {
       cityID: 3,
       carID:4,
       name: 'Lucy'
      },
      {
       cityID: 4,
       carID:1,
       name: 'Mary'
      },
    ]
    
    const cities = [{ cityID: 1, name:'New York'},{ cityID: 2, name:'Sydney'}, { cityID: 3, name:'Chicago'},{ cityID: 4, name:'Perth'}]
    const cars = [{ carID: 1, name:'Cruze'},{ carID: 2, name:'Mustang'}, { carID: 3, name:'Blazer'},{ carID: 4, name:'Tucson'}]
    
    new Vue({
      el: '#app',
      data: function() {
        return {
          data,
          cities,
          cars,
          city: "",
          car: "",
        }
      },
      methods: {
        findCarName: function (carID) {
          return this.cars.find(car => car.carID === carID).name
        },
        findCityName: function (cityID) {
          return this.cities.find(city => city.cityID === cityID).name
        },
        reset: function () {
          this.city = ""
          this.car = ""
        }
        
      }, 
      computed: {
        filteredData: function() {
          let resultData = this.data
          if (this.city) {
            resultData = resultData.filter(item => item.cityID === this.city)
          }
          if (this.car) {
            resultData = resultData.filter(item => item.carID === this.car)
          }
          return resultData
        },
        
        filteredCars: function () {
          const carIDs = this.filteredData.reduce((acc, next) => {
            if (acc.indexOf(next.carID) === -1){
              return [...acc, next.carID]  
            }
            return acc
          },[])
          
          if (carIDs.length) {
            return carIDs.map(carID => ({carID, name: this.findCarName(carID)}))
          }
          return this.cars
        },
        
        filteredCities: function () {
          const citiesIDs = this.filteredData.reduce((acc, next) => {
            if (acc.indexOf(next.cityID) === -1){
              return [...acc, next.cityID]  
            }
            return acc
          },[])
          
          if (citiesIDs.length) {
            return citiesIDs.map(cityID => ({cityID, name: this.findCityName(cityID)}))
          }
          return this.cities
        }
      }
      
    })
    #app {
      margin: 30px;
    }
    #app .form-group {
      display: flex;
      align-items: center;
    }
    #app .form-group label {
      font-weight: bold;
      color: #337ab7;
      margin-right: 20px;
    }
    #app .filters {
      margin-bottom: 20px;
      display: flex;
      width: 700px;
      justify-content: space-around;
    }
    #app .table {
      width: 700px;
    }
    #app .table thead tr td {
      font-weight: bold;
      color: #337ab7;
    }
    <link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css" rel="stylesheet"/>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
    <div id="app">
      <div class="filters row">
        <div class="form-group">
           <label for="city">City</label>
            <select v-model="city" id="city" class="form-control">
              <option value="">Select City</option>
              <option v-for="item in filteredCities" :key="item.cityID" :value="item.cityID">{{item.name}}</option>
             </select>
          
        </div>  
        <div class="form-group">
          <label for="car">Car</label>    
          <select v-model="car" id="car" class="form-control">
          <option value="">Select Car</option>
          <option v-for="item in filteredCars" :key="item.carID" :value="item.carID">{{item.name}}</option>
          </select>
        </div>
        <div class="form-group">
          <button type="button" class="btn btn-primary" @click="reset">Reset</button>
        </div>
        
      
      </div>
      <table class="table table-striped table-bordered">
        <thead>
          <tr><td>Name</td><td>Car</td><td>City</td></tr>
        </thead>
        <tbody>
          <tr v-for="item in filteredData" :key="data.name">
            <td>{{item.name}}</td>
            <td>{{findCarName(item.carID)}}</td>
            <td>{{findCityName(item.cityID)}}</td>
          </tr>
        </tbody>
      </table>
    <div>
      
      
      

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-01
      • 1970-01-01
      • 2020-03-18
      • 1970-01-01
      • 2017-04-13
      相关资源
      最近更新 更多