Фильтрация флажков с помощью VueJS

Это мой первый проект VueJS (переход от jQuery), и я пытаюсь отфильтровать сетку с несколькими флажками. Как видно из JavaScript, у меня есть функция filterJobs, которая фильтрует массив со значениями, установленными из того, что проверено (v-model="checkedLocations"). array.includes, кажется, фильтрует одно значение, и я хотел бы отфильтровать несколько значений. Я не хочу выталкивать или нарезать массив, потому что, если они снимут отметку с местоположения, они исчезнут и не будут повторно связываться

let careers = careers || {};

 careers.taleo = (function($){

   let app;

   let init = function() {

    app = new Vue({
      el: '#app',
      data: {
        locations: ['Scottsdale, AZ','Chandler, AZ','Irvine, CA','Denver, CO','Chicago, IL','Rockville, MD','Kansas City, MO','Charlotte, NC','Red Bank, NJ','Henderson, NV','Melville, NY','Allentown, PA','Irving, TX'],
        jobs: null,
        checkedLocations: []
      },
      created: function () {
        this.fetchData();
      },
      methods: {
          fetchData: function () {
            this.jobs = [
              { id: '1', title: 'Circuit Court Clerk', description: 'lorem ipsum', location: 'Charlotte, NC', department: 'Sales and Marketing', date: '23/10/17' },
              { id: '2', title: 'Tie Buyer', description: 'lorem ipsum', location: 'Irvine, CA', department: 'Media Relations', date: '21/10/16' },
              { id: '3', title: 'Leaded Glass Installer', description: 'lorem ipsum', location: 'Kansas City, MO', department: 'Public Relations', date: '16/09/17' },
              { id: '4', title: 'Wheat Inspector', description: 'lorem ipsum', location: 'Red Bank, NJ', department: 'Quality Assurance', date: '12/06/16' },
              { id: '5', title: 'Executive Officer, Special Warfare Team', description: 'lorem ipsum', location: 'Irving, TX', department: 'Public Relations', date: '19/03/18' },
              { id: '6', title: 'Wildlife Control Agent', description: 'lorem ipsum', location: 'Irvine, CA', department: 'Sales and Marketing', date: '07/01/17' },
              { id: '7', title: 'Arresting Gear Operator', description: 'lorem ipsum', location: 'Charlotte, NC', department: 'Asset Management', date: '04/09/17' },
              { id: '8', title: 'Arresting Gear Operator', description: 'lorem ipsum', location: 'Chandler, AZ', department: 'Tech Support', date: '01/04/17' },
              { id: '9', title: 'Biogeographer', description: 'lorem ipsum', location: 'Chicago, IL', department: 'Quality Assurance', date: '01/05/17' },
              { id: '10', title: 'LAN Systems Administrator', description: 'lorem ipsum', location: 'Scottsdale, AZ', department: 'Customer Relations', date: '29/04/18' },
              { id: '11', title: 'Copper Plater', description: 'lorem ipsum', location: 'Irving, TX', department: 'Tech Support', date: '17/08/17' },
              { id: '12', title: 'Leaded Glass Installer', description: 'lorem ipsum', location: 'Rockville, MD', department: 'Sales and Marketing', date: '02/11/16' },
              { id: '13', title: 'Line Cook', description: 'lorem ipsum', location: 'Chandler, AZ', department: 'Advertising', date: '02/12/17' },
              { id: '14', title: 'Special Education Teaching Assistant', description: 'lorem ipsum', location: 'Red Bank, NJ', department: 'Payroll', date: '02/05/17' },
              { id: '15', title: 'Clarinetist', description: 'lorem ipsum', location: 'Melville, NY', department: 'Payroll', date: '30/05/17' },
              { id: '16', title: 'Arresting Gear Operator', description: 'lorem ipsum', location: 'Henderson, NV', department: 'Payroll', date: '23/02/18' },
              { id: '17', title: 'Wheat Inspector', description: 'lorem ipsum', location: 'Red Bank, NJ', department: 'Tech Support', date: '12/08/16' },
              { id: '18', title: 'Wildlife Control Agent', description: 'lorem ipsum', location: 'Melville, NY', department: 'Payroll', date: '03/05/17' },
              { id: '19', title: 'Print Retoucher', description: 'lorem ipsum', location: 'Chicago, IL', department: 'Sales and Marketing', date: '19/06/16' },
              { id: '20', title: 'Mathematical Statistician', description: 'lorem ipsum', location: 'Scottsdale, AZ', department: 'Tech Support', date: '10/07/16' }
            ];
          },
          filterJobs: function(event) {
            app.jobs = app.jobs.filter(function (job) {
              return job.location.includes(app.checkedLocations);
            });

            // filterJobs: function(event) {
            //     app.jobs = app.jobs.filter( function( location ) {
            //       return !app.checkedLocations.includes( location );
            //     } );
          }
        }
    });



   };


   return { init, app };

})();

(function(){
  careers.taleo.init();
})();
#app {
  padding: 25px;
}
#app ul {
  margin-left: 0;
  padding: 0;
}
#app ul li {
  list-style: none;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.10/vue.min.js"></script>

<div id="app">

  <div class="container-fluid">
    <div class="row">
      <div class="col-md-3">
        <h3>Locations</h3>
        <ul>
          <li v-for="location in locations">
           <input type="checkbox" v-model="checkedLocations" v-on:click="filterJobs" v-bind:value="location" />  {{location}}
          </li>
        </ul>
        <span>Checked locations: {{ checkedLocations }}</span>
      </div>
      <div class="col-md-9">
         <div class="jobs">
           <div class="job" v-for="job in jobs">
             <div class="card" style="margin: 5px 0">
               <div class="card-block">
                 <h4 class="card-title">
                   {{ job.title }}
                 </h4>
                 <small class="pull-right text-muted" style="font-size: 12x">
                   {{job.date}}
                 </small>
                 <p class="card-text">
                    <!-- {{job.description}} -->
                 </p>
                 <button class="btn btn-sm btn-primary">View</button>
               </div>
             </div>
           </div>
         </div>
      </div>
    </div>
  </div>

</div>

https://codepen.io/neil/pen/WjXrxx


person Community    schedule 11.05.2017    source источник
comment
Вам не нужно переходить с jQuery — он очень хорошо работает с Vue, особенно когда вы хотите использовать Ajax.   -  person Staszek    schedule 12.05.2017
comment
Под переходом от jQuery я подразумеваю исключительно использование jQuery для создания таких интерактивных интерфейсов.   -  person    schedule 12.05.2017


Ответы (2)


Используйте вычисленное значение для отфильтрованных местоположений.

computed:{
  filteredJobs(){
    // if there are no checked locations, return everything.
    // You could remove this if you only want to return 
    // checked locations.
    if (!this.checkedLocations.length)
       return this.jobs

     return this.jobs.filter(j => this.checkedLocations.includes(j.location))
  }
}

И измените свой шаблон.

<div class="job" v-for="job in filteredJobs">

А также удалив метод filterJobs.

Пример.

По сути, вам нужно было перевернуть фильтр на

this.checkedLocations.includes(job.location). 

Кроме того, вы не хотите изменять свои данные каждый раз, когда вы фильтруете, потому что вы пропускаете данные. Однако использование вычисляемого значения более идиоматично для Vue.

person Bert    schedule 11.05.2017
comment
Как добавить дополнительные фильтры? Допустим, я добавляю отдел, могу ли я просто обновить этот вычисляемый метод, чтобы включить дополнительный фильтр? - person ; 12.05.2017
comment
@Нил Да, именно так. - person Bert; 12.05.2017
comment
@Нил, вот пример. stackoverflow.com /вопросы/43503622/ - person Bert; 12.05.2017
comment
@Нил или этот. stackoverflow.com/questions/42683926/ - person Bert; 12.05.2017
comment
привет, не могли бы вы проверить этот вопрос: stackoverflow.com/questions/54415053/ - person ; 29.01.2019

Используйте v-if в строке, где вы перечисляете вакансии:

<div class="job" v-if=filterJobs(job) v-for="job in jobs">

и используйте метод filterJobs следующим образом:

filterJobs: function(data) {
        if (this.checkedLocations.length == 0) return true;
        return this.checkedLocations.includes(data.location);
}

Отредактированный код

person Staszek    schedule 11.05.2017