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>
source to share
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.
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.
source to share