web-dev-qa-db-fra.com

Table b Bootstrap-vue avec filtre dans l'en-tête

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?

Capture d'écran de la table actuelle : enter image description here

Maquette de la table souhaitée : Mockup of the wanted table

5
Adriano

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.

5
Phil

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;
            }, {})
          ];
    }
1
Abhishek

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]))
      })
0
Eugene Oleynikov

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