Filtering checkboxes with VueJS

This is my first VueJS project (transition from jQuery) and I am trying to filter a grid with multiple checkboxes. As you can see from JavaScript, I have a filterJobs function that filters an array with values ​​set from what is checked (v-model = "checkedLocations"). array.includes seems to be filtering a single value, and I would like to filter multiple values. I don't want to float or slice the array, because if they uncheck the checkbox, they disappear and won't regenerate

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>
      

Run codeHide result


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

+3


source to share


2 answers


Use the calculated value for the filtered locations.

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

      

And change your template.

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

      

Also by removing your filterJobs method.



An example .

Basically you need to flip the filter to

this.checkedLocations.includes(job.location). 

      

Also, you don't want to change your data every time you filter because your data is bleeding. Using a computed value is more idiomatic in Vue.

+3


source


Use v-if on the line that lists the jobs:

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

      

and use the filterJobs method:



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

      

Edited code

+2


source







All Articles