根据多个选项过滤数组(Vue/JavaScript) [英] Filter array based on multiple options (Vue/JavaScript)

查看:72
本文介绍了根据多个选项过滤数组(Vue/JavaScript)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果这是重复的帖子,我深表歉意.在发布此内容之前,我搜索了一些不同的内容.我试图弄清楚如何根据两个选项过滤结果.我可以选择一种方法来工作,但同时需要两种方法来推动结果.

If this is a duplicate post I apologize. I searched a couple different things before posting this. I'm trying to figure out how to filter results based off of two options. I can get one of the options to work but need both to drive the results.

我有4个计算的属性:

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

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

In the data on that component I have two properties that are binded to what the user selects. I'm running the filtering off of those selected values.

代码

<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>

这是应用程序在前端的外观 试用版应用程序

Here is what the app looks like on the front end Trials App

我也是现代JavaScript语法的新手,所以请大声笑.

I'm also new to the modern JavaScript syntax so please be nice lol.

推荐答案

我创建了 codepen 尝试展示如何实现它.有包含carID和cityID的项目列表.同样,有两个选择可以过滤结果.当您更改一个选择时,它也会过滤另一个选择的选项.我希望它可以为您提供帮助,如果您有任何疑问,请问.

I have created a codepen to try to show how you can achieve it. There is a list of items containing carID and cityID. Also, there are two selects to filter the result. When you change a select, it will filter the options of the other select as well. I hope it can help you, if you have any question, just ask.

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>
  
  
  

这篇关于根据多个选项过滤数组(Vue/JavaScript)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆