Requêtes de tables avec Vue3 et Element Plus : gestion des conditions, liaison de pagination et bonnes pratiques

Problèmes clés des requêtes de tables

Les requêtes de tables dans les applications web présentent trois défis principaux : la gestion des conditions de filtre, la logique de réinitialisation et la synchronisation de la pagination. Voici une approche standardisée pour les résoudre.

Gestion des conditions de requête avec un objet unifié

Utiliser un objet réactif centralisé pour les conditions de filtre évite la dispersion des données et simplifie la maintenance.

import { reactive, computed } from 'vue';

// Objet pour les conditions de filtre
const filtreRequete = reactive({
  motCle: '',
  statut: '',
  plageDates: []
});

// Pagination séparée
const etatPagination = reactive({
  pageActuelle: 1,
  elementsParPage: 10
});

// Paramètres d'interface calculés automatiquement
const parametresAPI = computed(() => ({
  motCle: filtreRequete.motCle?.trim() || undefined,
  statut: filtreRequete.statut || undefined,
  dateDebut: filtreRequete.plageDates?.[0] || undefined,
  dateFin: filtreRequete.plageDates?.[1] || undefined,
  page: etatPagination.pageActuelle,
  limite: etatPagination.elementsParPage
}));

Réinitialisation propre des conditions

La réinitialisation doit effacer les conditions de filtre tout en ramenant la pagination à la première page, sans perturber l'état réactif.

// Valeurs initiales pour la réinitialisation
const obtenirValeursInitiales = () => ({
  motCle: '',
  statut: '',
  plageDates: []
});

const handleReset = () => {
  const valeursInit = obtenirValeursInitiales();
  Object.keys(valeursInit).forEach(cle => {
    filtreRequete[cle] = valeursInit[cle];
  });
  etatPagination.pageActuelle = 1;
  chargerDonnees();
};

Liaison de la pagination avec les conditions

Lors du changement de page ou du nombre d'éléments par page, les conditions actuelles doivent être incluses dans la requête. Un changemetn du nombre d'éléments par page réinitialise la page à 1.

<el-pagination
  v-model:current-page="etatPagination.pageActuelle"
  v-model:page-size="etatPagination.elementsParPage"
  :page-sizes="[10, 20, 50]"
  :total="donneesTable.total"
  layout="total, sizes, prev, pager, next"
  @current-change="gererChangementPage"
  @size-change="gererChangementTaille"
/>

const gererChangementPage = (nouvellePage) => {
  etatPagination.pageActuelle = nouvellePage;
  chargerDonnees();
};

const gererChangementTaille = (nouvelleTaille) => {
  etatPagination.elementsParPage = nouvelleTaille;
  etatPagination.pageActuelle = 1;
  chargerDonnees();
};

Exemple complet d'une page de requête de table

<template>
  <div class="conteneur-requete">
    <el-form :model="filtreRequete" inline>
      <el-form-item label="Mot-clé">
        <el-input v-model="filtreRequete.motCle" clearable />
      </el-form-item>
      <el-form-item label="Statut">
        <el-select v-model="filtreRequete.statut" clearable>
          <el-option label="Actif" value="actif" />
          <el-option label="Inactif" value="inactif" />
        </el-select>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="effectuerRecherche">Rechercher</el-button>
        <el-button @click="handleReset">Réinitialiser</el-button>
      </el-form-item>
    </el-form>

    <el-table :data="donneesTable.elements" v-loading="enChargement" border>
      <el-table-column prop="identifiant" label="ID" width="80" />
      <el-table-column prop="nom" label="Nom" />
      <el-table-column prop="statut" label="Statut">
        <template #default="{ row }">
          {{ row.statut === 'actif' ? 'Actif' : 'Inactif' }}
        </template>
      </el-table-column>
    </el-table>

    <el-pagination
      v-model:current-page="etatPagination.pageActuelle"
      v-model:page-size="etatPagination.elementsParPage"
      :page-sizes="[10, 20, 50]"
      :total="donneesTable.total"
      layout="total, sizes, prev, pager, next"
      @current-change="gererChangementPage"
      @size-change="gererChangementTaille"
    />
  </div>
</template>

<script setup>
import { ref, reactive, computed, onMounted } from 'vue';

const obtenirValeursInitiales = () => ({
  motCle: '',
  statut: '',
  plageDates: []
});

const filtreRequete = reactive(obtenirValeursInitiales());
const etatPagination = reactive({ pageActuelle: 1, elementsParPage: 10 });

const parametresAPI = computed(() => ({
  motCle: filtreRequete.motCle?.trim() || undefined,
  statut: filtreRequete.statut || undefined,
  dateDebut: filtreRequete.plageDates?.[0] || undefined,
  dateFin: filtreRequete.plageDates?.[1] || undefined,
  page: etatPagination.pageActuelle,
  limite: etatPagination.elementsParPage
}));

const enChargement = ref(false);
const donneesTable = reactive({ elements: [], total: 0 });

const chargerDonnees = async () => {
  enChargement.value = true;
  try {
    const reponse = await fetchAPI(parametresAPI.value);
    donneesTable.elements = reponse.liste;
    donneesTable.total = reponse.total;
  } finally {
    enChargement.value = false;
  }
};

const effectuerRecherche = () => {
  etatPagination.pageActuelle = 1;
  chargerDonnees();
};

const handleReset = () => {
  const valeursInit = obtenirValeursInitiales();
  Object.keys(valeursInit).forEach(cle => {
    filtreRequete[cle] = valeursInit[cle];
  });
  etatPagination.pageActuelle = 1;
  chargerDonnees();
};

const gererChangementPage = () => chargerDonnees();
const gererChangementTaille = () => {
  etatPagination.pageActuelle = 1;
  chargerDonnees();
};

onMounted(() => chargerDonnees());
</script>

Problèmes courants et solutions

Anti-rebond pour éviter les requêtes fréquentes : Utilisez un anti-rebond lors des saisies utilisateur pour limiter les appels API.

import { useDebounceFn } from '@vueuse/core';

const chargerDonneesAntiRebond = useDebounceFn(chargerDonnees, 300);

const gererChangementMotCle = () => {
  etatPagination.pageActuelle = 1;
  chargerDonneesAntiRebond();
};

Gession des valeurs vides : Transmettez undefined pour les champs non remplis afin d'éviter les chaînes vides dans les requêtes API.

motCle: filtreRequete.motCle?.trim() || undefined

Format des dates : Assurez-vous que le format des dates correspond aux attentes du backend, par exemple YYYY-MM-DD.

Réinitialisation des validations de formulaire : Si vous utilisez la validation d'Element Plus, appelez resetFields() sur la référence du formulaire pour réinitialiser les erreurs.

const formulaireRef = ref();

const handleReset = () => {
  formulaireRef.value?.resetFields();
  etatPagination.pageActuelle = 1;
  chargerDonnees();
};

Étiquettes: Vue3 Element Plus table queries reactive state Pagination

Publié le 17 juin à 19h00