【问题标题】:Multiple Checkbox Filtering to Narrow Down a Search多个复选框过滤以缩小搜索范围
【发布时间】:2019-09-08 00:48:27
【问题描述】:

感谢 Khalid Ali 迄今为止对我的帮助。

所以我有一系列包含描述、关键字等的歌曲。我有许多复选框,我想用它们来优化搜索。基本上,如果有人选择 Pop 复选框,它将显示所有类型为“pop”的歌曲。但是,如果我还选择 Epic Trailers,它会返回所有类型为“pop”的歌曲和所有带有“epictrailers”的歌曲。我想要的是它只返回两种类型的歌曲。例如 - 流派:“流行,史诗预告片”,

在下面的数组中,您会看到歌曲 2 和歌曲 3 都具有“戏剧性”的情绪。但歌曲2也有“紧张”,歌曲3也有“飙升”。因此,如果我选中 Dramatic 和 Soaring 复选框,我应该只会看到歌曲 3。目前两首歌曲都显示,因为两首歌曲都具有“戏剧性”。

简而言之,我希望它只返回包含所有复选框的歌曲。

我希望这是有道理的......

HTML 片段:

<div id="app">
  <div class="search-music">
    <input type="text" v-model="search" placeholder="Enter a keyword to refine your search"/>
  </div>

  <div class='filterboxes'>
            <div class="genres"><h1>GENRES</h1><br>
            <input type="checkbox" id="rock" key="genre" value="rock" v-model="checkboxFilter">
            <label for="rock">Rock</label><br>
            <input type="checkbox" id="Pop" key="genre" value="pop" v-model="checkboxFilter">
            <label for="Pop">Pop</label><br>
            <input type="checkbox" id="funk" key="genre" value="funk" v-model="checkboxFilter">
            <label for="funk">Funk</label><br>
            <input type="checkbox" id="Jazz" key="genre" value="jazz" v-model="checkboxFilter">
            <label for="Jazz">Jazz</label><br>
          </div>
            <div class="genres"><P></P><br>
            <input type="checkbox" id="Dubstep" key="genre" value="dubstep" v-model="checkboxFilter">
            <label for="Dubstep">Dubstep</label><br>
            <input type="checkbox" id="Classical" key="genre" value="classical" v-model="checkboxFilter">
            <label for="Classical">Classical</label><br>
            <input type="checkbox" id="Country" key="genre" value="country" v-model="checkboxFilter">
            <label for="Country">Country</label><br>
            <input type="checkbox" id="Blues" key="genre" value="blues" v-model="checkboxFilter">
            <label for="Blues">Blues</label><br>
          </div>
          <div class="genres"><P></P><br>
            <input type="checkbox" id="Hip Hop" key="genre" value="hiphop" v-model="checkboxFilter">
            <label for="Hip Hop">Hip Hop</label><br>
            <input type="checkbox" id="Orchestral" key="genre" value="orchestral" v-model="checkboxFilter">
            <label for="Orchestral">Orchestral</label><br>
            <input type="checkbox" id="Epic Trailer" key="genre" value="epictrailer" v-model="checkboxFilter">
            <label for="Epic Trailer">Epic Trailer</label><br>
            <input type="checkbox" id="EDM" key="genre" value="edm" v-model="checkboxFilter">
            <label for="EDM">EDM</label><br>
            </div>
            <div class="genres"><h1>MOODS</h1><br>
            <input type="checkbox" id="Melancholy" key="moods" value="melancholy" v-model="checkboxFilter">
            <label for="Melancholy">Melancholy</label><br>
            <input type="checkbox" id="Upbeat" key="moods" value="upbeat" v-model="checkboxFilter">
            <label for="Upbeat">Upbeat</label><br>
            <input type="checkbox" id="Playful" key="moods" value="playful" v-model="checkboxFilter">
            <label for="Playful">Playful</label><br>
            <input type="checkbox" id="Hopeful" key="moods" value="hopeful" v-model="checkboxFilter">
            <label for="Hopeful">Hopeful</label><br>
          </div>
            <div class="genres"><P></P><br>
            <input type="checkbox" id="Dramatic" key="moods" value="dramatic" v-model="checkboxFilter">
            <label for="Dramatic">Dramatic</label><br>
            <input type="checkbox" id="Disturbing" key="moods" value="disturbing" v-model="checkboxFilter">
            <label for="Disturbing">Disturbing</label><br>
            <input type="checkbox" id="Uplifting" key="moods" value="uplifting" v-model="checkboxFilter">
            <label for="Uplifting">Uplifting</label><br>
            <input type="checkbox" id="Tense" key="moods" value="tense" v-model="checkboxFilter">
            <label for="Tense">Tense</label><br>
          </div>
          <div class="genres"><P></P><br>
            <input type="checkbox" id="Crazy" key="moods" value="crazy" v-model="checkboxFilter">
            <label for="Crazy">Crazy</label><br>
            <input type="checkbox" id="Funny" key="moods" value="funny" v-model="checkboxFilter">
            <label for="Funny">Funny</label><br>
            <input type="checkbox" id="Soaring" key="moods" value="soaring" v-model="checkboxFilter">
            <label for="Soaring">Soaring</label><br>
            <input type="checkbox" id="Childish" key="moods" value="childish" v-model="checkboxFilter">
            <label for="Childish">Childish</label><br>
            </div>
            <div class="genres"><h1>TEMPO</h1><br>
            <input type="checkbox" id="vfast" key="tempo" value="vfast" v-model="checkboxFilter">
            <label for="vfast">Very Fast</label><br>
            <input type="checkbox" id="fast" key="tempo" value="fast" v-model="checkboxFilter">
            <label for="fast">Fast</label><br>
            <input type="checkbox" id="moderate" key="tempo" value="moderate" v-model="checkboxFilter">
            <label for="moderate">Moderate</label><br>
            <input type="checkbox" id="slow" key="tempo" value="slow" v-model="checkboxFilter">
            <label for="slow">Slow</label><br>
          </div>
            <div class="genres"><h1>THEMES</h1><br>
            <input type="checkbox" id="Corporate" key="theme" value="corporate" v-model="checkboxFilter">
            <label for="Corporate">Corporate</label><br>
            <input type="checkbox" id="Technology" key="theme" value="technology" v-model="checkboxFilter">
            <label for="Technology">Technology</label><br>
            <input type="checkbox" id="Food" key="theme" value="food" v-model="checkboxFilter">
            <label for="Food">Food</label><br>
            <input type="checkbox" id="Education" key="theme" value="education" v-model="checkboxFilter">
            <label for="Education">Education</label><br>
          </div>
            <div class="genres"><P></P><br>
            <input type="checkbox" id="Travel" key="theme" value="travel" v-model="checkboxFilter">
            <label for="Travel">Travel</label><br>
            <input type="checkbox" id="Sport" key="theme" value="sport" v-model="checkboxFilter">
            <label for="Sport">Sport</label><br>
            <input type="checkbox" id="Fashion" key="theme" value="fashion" v-model="checkboxFilter">
            <label for="Fashion">Fashion</label><br>
            <input type="checkbox" id="Landscape" key="theme" value="landscape" v-model="checkboxFilter">
            <label for="Landscape">Landscape</label><br>
          </div>
          </div>


  <template v-for='song in filteredSongs'>
    <div class="songlayout" >
      <div class='wrapper'>
        <div>
          <img :src="song.cover_art_url" alt="" class='img-fluid rounded'>
        </div>
        <button class="button_7" @click='openLicense(song.license_url)'>License</button>
        <h1 class='song-title'>{{song.title}}</h1>
        <p class="song-description" >{{song.description}}</p>

        <div class="overlay-play text-center" v-if="isPlaying && (currentSong.id === song.id )" @click='pause'>
          <i class="icon ion-ios-pause"></i>
        </div>

        <div class="overlay-play text-center" @click='play(song)' v-else>
          <i class="icon ion-ios-play"></i>
        </div>
      </div>
    </div>
  </template>
</div>

JS 片段:

new Vue({
  el: '#app',
  data: {
    songs: [
            {
        id: 1,
        title: "Track 1",
        description: "Description 1",
        url:"./mp3/track1.mp3",
        keywords: "achievement, advertising, background, beautiful, beauty, business, business music, commercial, company, confident, corporate, corporate background, corporate presentation, corporate presentations music, corporate video, corporation, corporative, happy",
        genre:"pop, rock",
        moods:"uplifting, upbeat, playful",
        tempo:"moderate",
        theme:"corporate",
      },

      {
        id: 2,
        title: "Track 2",
        description: "Description 2",
        url:"./mp3/track2.mp3",
        keywords: "scary, horror, Armageddon, Big Ending, Dramatic, End Of The World, Escape, Fantasy, Film, Film Score, Foreboding, Haunted House, Haunting, Nervous, Nightmare, Pensive",
        genre:"epictrailer",
        moods:"tense, dramatic, disturbing",
        tempo:"moderate",
        theme:"landscape",
      },
      {
        id: 3,
        title: "Track 3",
        description: "Description 3",
        url: "./mp3/track3.mp3",
        keywords:"Armageddon, Battle, Big Ending, Bomb, Break Out, Busy, Chase, Chilled, Covert Ops, Detective,",
        genre:"epictrailer",
        moods:"dramatic, soaring, hopeful",
        tempo:"moderate",
        theme:"sport",
      },
          ],

    search: "",
    checkboxFilter: [],
  },
  computed: {
    filteredSongs: function(value, key){
    let fltrdSongs;
    if(this.checkboxFilter.length > 0) {
      fltrdSongs = this.songs.filter((song) => {
        let length = this.checkboxFilter.length;
        while(length--){
          if ((song.genre + song.moods + song.theme + song.tempo).indexOf(this.checkboxFilter[length])!=-1)
           {return true;}

        }
      });
    } else {
      fltrdSongs = this.songs;
    }

    return fltrdSongs.filter((song) => {
      return song.keywords.toLowerCase().match(this.search.toLowerCase()) ||
             song.title.toLowerCase().match(this.search.toLowerCase()) ||
             song.description.toLowerCase().match(this.search.toLowerCase())
    });
},},

【问题讨论】:

    标签: javascript html vue.js search filtering


    【解决方案1】:

    您的filteredSongs 计算属性永远不会到达this.checkboxFilter.length if 语句,因为它前面有return 语句。

    将您的 filteredSongs 计算属性替换为以下属性:

    filteredSongs: function(value, key){
        let fltrdSongs;
        if(this.checkboxFilter.length > 0)
          fltrdSongs = this.songs.filter((song) => (song.genre)
                                         .includes(this.checkboxFilter.toString()));
        else
          fltrdSongs = this.songs;
    
        return fltrdSongs.filter((song) => {
          return song.keywords.toLowerCase().match(this.search.toLowerCase()) ||
                 song.title.toLowerCase().match(this.search.toLowerCase()) ||
                 song.description.toLowerCase().match(this.search.toLowerCase())
        });
    }
    

    回复jeanpegg's comment

    使用以下计算属性通过多个复选框过滤歌曲

    filteredSongs: function(value, key){
        let fltrdSongs;
        if(this.checkboxFilter.length > 0) {
          fltrdSongs = this.songs.filter((song) => {
            let length = this.checkboxFilter.length;
            while(length--){
              if ((song.genre).indexOf(this.checkboxFilter[length])!=-1) {
                return true;
              }
            }
          });
        } else {
          fltrdSongs = this.songs;
        }
    
        return fltrdSongs.filter((song) => {
          return song.keywords.toLowerCase().match(this.search.toLowerCase()) ||
                 song.title.toLowerCase().match(this.search.toLowerCase()) ||
                 song.description.toLowerCase().match(this.search.toLowerCase())
        });
    }
    

    回复jeanpegg's comment

    我已经编辑了代码以使用 genremoods

    HTML:将 v-model="checkboxFilter" 更改为 v-model="checkboxFilter.genre"v-model="checkboxFilter.moods"

    JS:将checkboxFilter 数据属性 更改为checkboxFilter: {genre: [], moods: []}。还更改了filteredSongs 计算属性

    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.0.3/vue.js"></script><div id="app">
      <div class="search-music">
        <input type="text" v-model="search" placeholder="Enter a keyword to refine your search"/>
      </div>
    
      <div class='filterboxes'>
                <div class="genres"><h1>GENRES</h1><br>
                <input type="checkbox" id="rock" key="genre" value="rock" v-model="checkboxFilter.genre">
                <label for="rock">Rock</label><br>
                <input type="checkbox" id="Pop" key="genre" value="pop" v-model="checkboxFilter.genre">
                <label for="Pop">Pop</label><br>
                <input type="checkbox" id="funk" key="genre" value="funk" v-model="checkboxFilter.genre">
                <label for="funk">Funk</label><br>
                <input type="checkbox" id="Jazz" key="genre" value="jazz" v-model="checkboxFilter.genre">
                <label for="Jazz">Jazz</label><br>
              </div>
                <div class="genres"><P></P><br>
                <input type="checkbox" id="Dubstep" key="genre" value="dubstep" v-model="checkboxFilter.genre">
                <label for="Dubstep">Dubstep</label><br>
                <input type="checkbox" id="Classical" key="genre" value="classical" v-model="checkboxFilter.genre">
                <label for="Classical">Classical</label><br>
                <input type="checkbox" id="Country" key="genre" value="country" v-model="checkboxFilter.genre">
                <label for="Country">Country</label><br>
                <input type="checkbox" id="Blues" key="genre" value="blues" v-model="checkboxFilter.genre">
                <label for="Blues">Blues</label><br>
              </div>
              <div class="genres"><P></P><br>
                <input type="checkbox" id="Hip Hop" key="genre" value="hiphop" v-model="checkboxFilter.genre">
                <label for="Hip Hop">Hip Hop</label><br>
                <input type="checkbox" id="Orchestral" key="genre" value="orchestral" v-model="checkboxFilter.genre">
                <label for="Orchestral">Orchestral</label><br>
                <input type="checkbox" id="Epic Trailer" key="genre" value="epictrailer" v-model="checkboxFilter.genre">
                <label for="Epic Trailer">Epic Trailer</label><br>
                <input type="checkbox" id="EDM" key="genre" value="edm" v-model="checkboxFilter.genre">
                <label for="EDM">EDM</label><br>
                </div>
                <div class="genres"><h1>MOODS</h1><br>
                <input type="checkbox" id="Melancholy" key="moods" value="melancholy" v-model="checkboxFilter.moods">
                <label for="Melancholy">Melancholy</label><br>
                <input type="checkbox" id="Upbeat" key="moods" value="upbeat" v-model="checkboxFilter.moods">
                <label for="Upbeat">Upbeat</label><br>
                <input type="checkbox" id="Playful" key="moods" value="playful" v-model="checkboxFilter.moods">
                <label for="Playful">Playful</label><br>
                <input type="checkbox" id="Hopeful" key="moods" value="hopeful" v-model="checkboxFilter.moods">
                <label for="Hopeful">Hopeful</label><br>
              </div>
                <div class="genres"><P></P><br>
                <input type="checkbox" id="Dramatic" key="moods" value="dramatic" v-model="checkboxFilter.moods">
                <label for="Dramatic">Dramatic</label><br>
                <input type="checkbox" id="Disturbing" key="moods" value="disturbing" v-model="checkboxFilter.moods">
                <label for="Disturbing">Disturbing</label><br>
                <input type="checkbox" id="Uplifting" key="moods" value="uplifting" v-model="checkboxFilter.moods">
                <label for="Uplifting">Uplifting</label><br>
                <input type="checkbox" id="Tense" key="moods" value="tense" v-model="checkboxFilter.moods">
                <label for="Tense">Tense</label><br>
              </div>
              <div class="genres"><P></P><br>
                <input type="checkbox" id="Crazy" key="moods" value="crazy" v-model="checkboxFilter.moods">
                <label for="Crazy">Crazy</label><br>
                <input type="checkbox" id="Funny" key="moods" value="funny" v-model="checkboxFilter.moods">
                <label for="Funny">Funny</label><br>
                <input type="checkbox" id="Soaring" key="moods" value="soaring" v-model="checkboxFilter.moods">
                <label for="Soaring">Soaring</label><br>
                <input type="checkbox" id="Childish" key="moods" value="childish" v-model="checkboxFilter.moods">
                <label for="Childish">Childish</label><br>
                </div>
                <div class="genres"><h1>TEMPO</h1><br>
                <input type="checkbox" id="vfast" key="tempo" value="vfast" v-model="checkboxFilter">
                <label for="vfast">Very Fast</label><br>
                <input type="checkbox" id="fast" key="tempo" value="fast" v-model="checkboxFilter">
                <label for="fast">Fast</label><br>
                <input type="checkbox" id="moderate" key="tempo" value="moderate" v-model="checkboxFilter">
                <label for="moderate">Moderate</label><br>
                <input type="checkbox" id="slow" key="tempo" value="slow" v-model="checkboxFilter">
                <label for="slow">Slow</label><br>
              </div>
                <div class="genres"><h1>THEMES</h1><br>
                <input type="checkbox" id="Corporate" key="theme" value="corporate" v-model="checkboxFilter">
                <label for="Corporate">Corporate</label><br>
                <input type="checkbox" id="Technology" key="theme" value="technology" v-model="checkboxFilter">
                <label for="Technology">Technology</label><br>
                <input type="checkbox" id="Food" key="theme" value="food" v-model="checkboxFilter">
                <label for="Food">Food</label><br>
                <input type="checkbox" id="Education" key="theme" value="education" v-model="checkboxFilter">
                <label for="Education">Education</label><br>
              </div>
                <div class="genres"><P></P><br>
                <input type="checkbox" id="Travel" key="theme" value="travel" v-model="checkboxFilter">
                <label for="Travel">Travel</label><br>
                <input type="checkbox" id="Sport" key="theme" value="sport" v-model="checkboxFilter">
                <label for="Sport">Sport</label><br>
                <input type="checkbox" id="Fashion" key="theme" value="fashion" v-model="checkboxFilter">
                <label for="Fashion">Fashion</label><br>
                <input type="checkbox" id="Landscape" key="theme" value="landscape" v-model="checkboxFilter">
                <label for="Landscape">Landscape</label><br>
              </div>
              </div>
    
    
      <template v-for='song in filteredSongs'>
        <div class="songlayout" >
          <div class='wrapper'>
            <div>
              <img :src="song.cover_art_url" alt="" class='img-fluid rounded'>
            </div>
            <button class="button_7" @click='openLicense(song.license_url)'>License</button>
            <h1 class='song-title'>{{song.title}}</h1>
            <p class="song-description" >{{song.description}}</p>
    
            <div class="overlay-play text-center" v-if="isPlaying && (currentSong.id === song.id )" @click='pause'>
              <i class="icon ion-ios-pause"></i>
            </div>
    
            <div class="overlay-play text-center" @click='play(song)' v-else>
              <i class="icon ion-ios-play"></i>
            </div>
          </div>
        </div>
      </template>
    </div>
    
    new Vue({
      el: '#app',
      data: {
        isPlaying: '',
        songs: [
                {
            id: 1,
            title: "Track 1",
            description: "Description 1",
            url:"./mp3/track1.mp3",
            keywords: "achievement, advertising, background, beautiful, beauty, business, business music, commercial, company, confident, corporate, corporate background, corporate presentation, corporate presentations music, corporate video, corporation, corporative, happy",
            genre:"pop, rock",
            moods:"uplifting, upbeat, playful",
            tempo:"moderate",
            theme:"corporate",
          },
    
          {
            id: 2,
            title: "Track 2",
            description: "Description 2",
            url:"./mp3/track2.mp3",
            keywords: "scary, horror, Armageddon, Big Ending, Dramatic, End Of The World, Escape, Fantasy, Film, Film Score, Foreboding, Haunted House, Haunting, Nervous, Nightmare, Pensive",
            genre:"epictrailer",
            moods:"tense, dramatic, disturbing",
            tempo:"moderate",
            theme:"landscape",
          },
          {
            id: 3,
            title: "Track 3",
            description: "Description 3",
            url: "./mp3/track3.mp3",
            keywords:"Armageddon, Battle, Big Ending, Bomb, Break Out, Busy, Chase, Chilled, Covert Ops, Detective,",
            genre:"epictrailer",
            moods:"dramatic, soaring, hopeful",
            tempo:"moderate",
            theme:"sport",
          },
              ],
    
        search: "",
        checkboxFilter: {genre: [], moods: []},
      },
    computed: {
      filteredSongs: function(value, key){
        let fltrdSongs = this.songs;
        // checking if "genre" and "moods" arrays have elements in any of them
        if(this.checkboxFilter.genre.length + this.checkboxFilter.moods.length > 0) {
          // checking if "genre" array has elements
          if (this.checkboxFilter.genre.length > 0) {
            fltrdSongs = this.songs.filter((song) => {
              let length = this.checkboxFilter.genre.length;
              while(length--){
                if ((song.genre).indexOf(this.checkboxFilter.genre[length])!=-1) {
                  return true;
                }
              }
            });
          }
          // checking if "moods" array has elements
          if(this.checkboxFilter.moods.length > 0) {
            fltrdSongs = fltrdSongs.filter((song) => {
              let length = this.checkboxFilter.moods.length;
              while(length--){
                if ((song.moods).indexOf(this.checkboxFilter.moods[length])!=-1) {
                  return true;
                }
              }
            });
          }
        }
    
        return fltrdSongs.filter((song) => {
          return song.keywords.toLowerCase().match(this.search.toLowerCase()) ||
                 song.title.toLowerCase().match(this.search.toLowerCase()) ||
                 song.description.toLowerCase().match(this.search.toLowerCase())
          });
       }
      }
    });
    

    【讨论】:

    • 非常感谢!现在可以工作了。如果我能最后一次打扰你,问我如何组合多个复选框?例如,返回一首同时选中流派(流行)和节奏(快)的歌曲?它们独立工作,但在选中两个框时它什么都不返回。再次感谢您帮助我解决最初的问题!
    • 很高兴能为您提供帮助!我已经编辑了我的答案以添加用于通过多个复选框进行过滤的代码。让我知道你是否让它正常工作。谢谢
    • 嗨,Khalid,感谢您到目前为止对我的帮助。我几乎让它完全按照我想要的方式工作。我已经编辑了这个问题,试图解释我希望如何过滤歌曲。你帮了我很大的忙,我真的很感激!!!
    • 嗨,Jean,请检查我新编辑的答案并按照相同的逻辑添加其他过滤器。如果还有什么可以帮助您的,请告诉我。
    • 嗨哈立德!太棒了!非常感谢你帮我解决这个问题。对此,我真的非常感激!你是明星。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多