Creare una tabella con ordine, ricerca e paginazione in Alpine.js

Mattepuffo's logo
Creare una tabella con ordine, ricerca e paginazione in Alpine.js

Creare una tabella con ordine, ricerca e paginazione in Alpine.js

In questo articolo vediamo come creare una tabella tipo DataTable con Alpine.js.

Per la parte dello stile ho usato Bootstrap, ma ovviamente non è obbligatorio.

I dati li prendiamo da uno dei miei url; siete liberi di usarlo per i vostri test.

Cominciamo dal codice Javascript:

document.addEventListener('alpine:init', () => {
  Alpine.data('getItems', () => ({
        items: null,
        sortCol: null,
        sortAsc: false,
        pageSize: 10,
        curPage: 1,
        search: "",
        async init() {
          let resp = await fetch('https://www.mattepuffo.com/api/book/get.php');
          let data = await resp.json();
          data.books.forEach((d, i) => d.id = i);
          this.items = data.books;
        },
        nextPage() {
          if ((this.curPage * this.pageSize) < this.items.length) this.curPage++;
        },
        previousPage() {
          if (this.curPage > 1) this.curPage--;
        },
        sort(col) {
          if (this.sortCol === col) this.sortAsc = !this.sortAsc;
          this.sortCol = col;
          this.items.sort((a, b) => {
            if (a[this.sortCol] < b[this.sortCol]) return this.sortAsc ? 1 : -1;
            if (a[this.sortCol] > b[this.sortCol]) return this.sortAsc ? -1 : 1;
            return 0;
          });
        },
        get pagedItems() {
          if (this.items) {
            if (this.search === '') {
              return this.items.filter((row, index) => {
                let start = (this.curPage - 1) * this.pageSize;
                let end = this.curPage * this.pageSize;
                if (index >= start && index < end) return true;
              });
            } else {
              return this.items.filter((item) => {
                return item.title
                        .toLowerCase()
                        .includes(this.search.toLowerCase())
                    ||
                    item.author
                        .toLowerCase()
                        .includes(this.search.toLowerCase());
              });
            }
          } else {
            return [];
          }
        },
      })
  );
});

Il codice è abbastanza flessibile; per applicarlo ad un fonte dati diversa dovete cambiare solo la url e i campi in cui cercare.

Questo l'HTML:

<div class="row">
    <div class="col-12 mb-3">
      <section class="card">
        <div class="card-body">

          <div x-data="getItems()">
            <input type="search"
                   class="form-control mb-3"
                   placeholder="Cerca..."
                   x-ref="searchField"
                   x-model="search"
                   x-on:keydown.window.prevent.slash="$refs.searchField.focus()">

            <table class="table table-no-more table-bordered table-striped mb-3">
              <thead>
                <tr>
                  <th @click="sort('title')">Title</th>
                  <th @click="sort('author')">Author</th>
                </tr>
              </thead>
              <tbody>
                <template x-if="!items">
                  <tr>
                    <td colspan="4"><i>Loading...</i></td>
                  </tr>
                </template>
                <template x-for="item in pagedItems" :key="item.id">
                  <tr>
                    <td x-text="item.title"></td>
                    <td x-text="item.author"></td>
                  </tr>
                </template>
              </tbody>
            </table>

            <button class="btn btn-primary" @click="previousPage">Previous</button>
            <button class="btn btn-primary" @click="nextPage">Next</button>
          </div>

        </div>
      </section>
    </div>
  </div>
  
  <script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
  <script src="./js/script.js"></script>

Dvoreste anche aggiungere le icone sui nomi delle colonne per indicare meglio che la tabella è ordinabile.

Enjoy!


Condividi

Commentami!