J'ai un tableau généré avec bootstrap-vue qui montre les résultats d'une recherche système.
Le tableau des résultats montre les enregistrements à l'utilisateur, et l'utilisateur peut les trier et les filtrer.
Comment puis-je ajouter le champ de recherche sous l'en-tête du tableau <th>
généré avec le bootstrap-vue <b-table>
élément?
Vous pouvez utiliser le top-row
emplacement pour personnaliser votre première ligne. Voir ci-dessous pour un exemple à nu ...
new Vue({
el: '#app',
data: {
filters: {
id: '',
issuedBy: '',
issuedTo: ''
},
items: [{id:1234,issuedBy:'Operator',issuedTo:'abcd-efgh'},{id:5678,issuedBy:'User',issuedTo:'ijkl-mnop'}]
},
computed: {
filtered () {
const filtered = this.items.filter(item => {
return Object.keys(this.filters).every(key =>
String(item[key]).includes(this.filters[key]))
})
return filtered.length > 0 ? filtered : [{
id: '',
issuedBy: '',
issuedTo: ''
}]
}
}
})
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap/dist/css/bootstrap.min.css"/><link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.css"/><script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script><script src="//unpkg.com/babel-polyfill@latest/dist/polyfill.min.js"></script><script src="//unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.js"></script>
<div id="app">
<b-table striped show-empty :items="filtered">
<template slot="top-row" slot-scope="{ fields }">
<td v-for="field in fields" :key="field.key">
<input v-model="filters[field.key]" :placeholder="field.label">
</td>
</template>
</b-table>
</div>
Remarque: J'ai utilisé une propriété calculée pour filtrer les éléments au lieu de :filter
accessoire dans b-table
car il ne rend pas les lignes si tous les éléments sont filtrés, y compris votre première ligne personnalisée. De cette façon, je peux fournir une ligne de données fictive si le résultat est vide.
Ont voté la réponse de phil, la rendant simplement plus générique
filtered() {
const filtered = this.items.filter(item => {
return Object.keys(this.filters).every(key =>
String(item[key]).includes(this.filters[key])
);
});
return filtered.length > 0
? filtered
: [
Object.keys(this.items[0]).reduce(function(obj, value) {
obj[value] = '';
return obj;
}, {})
];
}
erreur
const filtered = this.items.filter(item => {
return Object.keys(this.filters).every(key =>
// String(item[key]).includes(this.filters[key]))
return String(item[key]).includes(this.filters[key]))
})
Merci à vous pour ces réponses utiles. Cela m'a fait gagner du temps aujourd'hui. Cependant, dans le cas où les éléments sont donnés de manière asynchrone, j'ai dû ajouter un test sur la taille des éléments comme celui-ci
filtered() {
if (this.items.length > 0) {
const filtered = this.items.filter(item => {
return Object.keys(this.filters).every(key => String(item[key]).includes(this.filters[key])
);
});
return filtered.length > 0
? filtered
: [
Object.keys(this.items[0]).reduce(function (obj, value) {
obj[value] = '';
return obj;
}, {})
];
}
},
D'un autre côté si nécessaire d'avoir une colonne sans filtre, j'ai ajouté ce test ci-dessous
Dans le modèle
<td v-for="field in fields" :key="field.key">
<input v-if="fieldIsFiltered(field)" v-model="filters[field.key]" :placeholder="field.label">
</td>
et dans les méthodes des composants
fieldIsFiltered(field) {
return Object.keys(this.filters).includes(field.key)
}