- Vue.js 2.x by Example
- Mike Street
- 275字
- 2021-07-02 20:00:28
Filtering and custom classes
We now have a fully fledged user list/register that has filtering on selected fields and custom CSS classes depending on the criteria. To recap, this is what our view looks like now we have the filter in place:
<p id="app">
<form>
<label for="fiterField">
Field:
<select id="filterField" v-model="filterField">
<option value="">Disable filters</option>
<option value="isActive">Active user</option>
<option value="name">Name</option>
<option value="email">Email</option>
<option value="balance">Balance</option>
<option value="registered">Date registered</option>
</select>
</label>
<label for="filterQuery" v-show="this.filterField &&
!isActiveFilterSelected()">
Query:
<input type="text" id="filterQuery" v-model="filterQuery">
</label>
<span v-show="isActiveFilterSelected()">
Active:
<label for="userStateActive">
Yes:
<input type="radio" v-bind:value="true" id="userStateActive" v-
model="filterUserState">
</label>
<label for="userStateInactive">
No:
<input type="radio" v-bind:value="false" id="userStateInactive"
v-model="filterUserState">
</label>
</span>
</form>
<table>
<tr v-for="person in people" v-show="filterRow(person)">
<td>{{ person.name }}</td>
<td>
<a v-bind:href="'mailto:' + person.email">{{ person.email }}
</a>
</td>
<td v-bind:class="balanceClass(person)">
{{ formatBalance(person.balance) }}
</td>
<td>{{ formatDate(person.registered) }}</td>
<td v-bind:class="activeClass(person)">
{{ activeStatus(person) }}
</td>
</tr>
</table>
</p>
And the JavaScript for our Vue app should look something like this:
const app = new Vue({
el: '#app',
data: {
people: [...],
currency: '$',
filterField: '',
filterQuery: '',
filterUserState: ''
},
methods: {
activeStatus(person) {
return (person.isActive) ? 'Active' : 'Inactive';
},
activeClass(person) {
return person.isActive ? 'active' : 'inactive';
},
balanceClass(person) {
let balanceLevel = 'success';
if(person.balance < 2000) {
balanceLevel = 'error';
} else if (person.balance < 3000) {
balanceLevel = 'warning';
}
let increasing = false,
balance = person.balance / 1000;
if(Math.round(balance) == Math.ceil(balance)) {
increasing = 'increasing';
}
return [balanceLevel, increasing];
},
formatBalance(balance) {
return this.currency + balance.toFixed(2);
},
formatDate(date) {
let registered = new Date(date);
return registered.toLocaleString('en-US');
},
filterRow(person) {
let result = true;
if(this.filterField) {
if(this.filterField === 'isActive') {
result = (typeof this.filterUserState === 'boolean') ?
(this.filterUserState === person.isActive) : true;
} else {
let query = this.filterQuery,
field = person[this.filterField];
if(typeof field === 'number') {
query.replace(this.currency, '');
try {
result = eval(field + query);
} catch(e) {}
} else {
field = field.toLowerCase();
result = field.includes(query.toLowerCase());
}
}
}
return result;
},
isActiveFilterSelected() {
return (this.filterField === 'isActive');
}
}
});
With a small amount of CSS, our people filtering app now looks like the following:
