Vuetify : : Ouvrir une ligne de détail de manière programmatique

Pour la prochaine version du PiCockpit v2.0, je prépare une application GPIO.

Les entrées GPIO sont des lignes de tableau - et pour les configurer, nous voulons pouvoir accéder à la ligne de détail en cliquant sur le bouton configurer :

image

En cliquant soit sur le chevron, soit sur le bouton de configuration, la ligne de détail s'ouvre :

image

Voici le modèle Vue correspondant :

<v-data-table
   :headers="gpioInputTableHeaders"
   :items="gpioInputTableData"
   :loading="loading"
   item-key="bcm_id"
   loading-text="en attente de données ... "
   en-tête fixe
  show-expand
   :expanded.sync="gpioInputTableExpanded"

   class="elevation-1″
>
   <template v-slot:item.value=”{ item }”>
     <span v-if="”!onlineStateBinary”"><i class="”fa" fa-warning”></i> </span>
     <span v-if="”item.state" ><v-icon x-small>mdi-flèche en gras</v-icon>{{item.high}}</span>
     <span v-else-if="”item.state" ><v-icon x-small>mdi-flèche-bas-bold</v-icon>{{item.low}}</span>
     <span v-else-if="”item.state" >N/A</span>
     <span v-else-if="”item.state" >N/A</span>
     <span v-else>ERROR</span>
   </template>
   <emballage v-slot:item.action="{ item }">
     <v-btn
       class="mr-2″
       couleur="primaire"
       petit
       @click.ctrl.exact="configGpioAll('input', item)"
       @click.exact="configGpio('input', item)"

     >
       mdi-clef-marteau.
       Configurer
     </v-btn>
     <v-btn
       class="mr-2″
       color="error"
       petit
       @click="remove_gpio('input', item.bcm_id)"
     >
       mdi-trash-can-outline
       Retirer
     </v-btn>
   </template>
   <template v-slot:expanded-item=”{ headers, item }”>
     <!– v-on:pull-change=”pullChange” –>
     <td :colspan="”headers.length”">
       <gpioInputDetailRow
         :rowData="item"
         v-on:pull-change="pullChange"
         v-on:debounce-change="debounceChange"
       >
     </td>
   </template>       
</v-data-table>        

Comme vous pouvez le voir, j'ai enveloppé un autre composant pour l'emplacement expanded-item. Ce composant n'est pas pertinent pour notre discussion actuelle, donc je ne fournis pas de code pour lui.

J'ai mis en évidence les éléments importants ci-dessus.

Ce sont :

  • :items= "gpioInputTableData" - cela relie les données à la clé des éléments de la table de données Vuetify.
  • item-key="bcm_id" - - il est important de donner une clé unique pour chaque entrée de vos données (qui sont données sous forme de tableau aux éléments).
    • si vous ne configurez pas cette option, toutes vos lignes de détail s'ouvriront et se fermeront en même temps.
    • la valeur doit être unique comme nous l'avons vu ; si vos données ont potentiellement des valeurs en double sur toutes les clés, vous devez créer une clé unique supplémentaire.
  • show-expand - cela montrera les Chevrons image
  • :expanded.sync="gpioInputTableExpanded" - Notez l'utilisation du modificateur sync, pour synchroniser les changements en retour ! Ceci est une variable pour stocker les éléments actuellement développés.

alors :

  •  @click.ctrl.exact="configGpioAll('input', item)" - comme vous pouvez le voir, lorsque je fais Ctrl + Click, j'appelle une fonction utilitaire pour basculer tous les emplacements d'extension, en fonction de l'état de l'élément actuel. Je lui passe l'élément qui doit être étendu.
  • @click.exact="configGpio('input', item)" - comme vous le voyez, lors d'un clic exact, j'appelle une autre fonction utilitaire (nous y reviendrons bientôt), en passant AUSSI l'élément courant

enfin :

  • <template v-slot:expanded-item=”{ headers, item }”> - ce Slot contient l'élément développé. Il est important de transmettre les en-têtes :
  • <td :colspan="”headers.length”"> - ... car il permet de créer une cellule qui s'étend sur toutes les colonnes.

Voici à quoi ressemble mon data() (extrait) :

data () {
   retour {
     chargement : vrai,
     gpioInputTableData : [],
     gpioInputTableHeaders : [
       {texte : 'Nom', valeur : 'nom'},
       { text : 'Value', value : 'value'},
       { texte : 'Action', valeur : 'action'}
     ],
     gpioInputTableExpanded : []

  }
},

Et voici les deux fonctions d'utilité :

image

configGpioAll : function (source, item){
         var ref = null ;
         var refTable = null ;
         if (source === 'input'){
             ref = 'gpioInputTableExpanded' ;
             refTable = 'gpioInputTableData' ;
         } else if (source === 'output'){
             ref = 'gpioOutputTableExpanded' ;
             refTable = 'gpioOutputTableData' ;
         } else if (source === 'softpwm'){
             ref = 'gpioSoftPWMTableExpanded' ;
             refTable = 'gpioSoftPWMTableData' ;
         }
         // avons-nous une correspondance pour cet article (est-il ouvert ?) ?
        si (this[ref].filter(e => e.bcm_id === item.bcm_id).length > 0){
           // supprimer tous les éléments
           console.log("configGpioAll : removing") ;
           ce[réf] = [] ;
         }
         else {
           console.log("configGpioAll : adding") ;
           // ajouter tous les éléments
           this[ref] = this[refTable] ;
         }
       },

dans configGpioAll, je vérifie si j'ai la table d'entrée, de sortie ou softpwm (pour éviter de dupliquer le code), et je configure les références à la variable étendue appropriée (voir données ci-dessus), et les données de la table elle-même.

Si l'élément est contenu dans les données développées (je fais une correspondance avec ma clé unique, bcm_id), je ferme tous les éléments développés. pour cela, je mets simplement la variable étendue à un tableau vide.

Si l'élément n'est PAS contenu dans les données étendues, j'ouvre tous les éléments, en y mettant toutes les données de la table.

Note : il pourrait être intéressant d'expérimenter si un tableau d'objets contenant uniquement les clés uniques pourrait être suffisant pour que cela fonctionne également.

image

configGpio : function (source, item){
   var ref = null ;
   if (source === 'input'){
       ref = 'gpioInputTableExpanded' ;
   } else if (source === 'output'){
       ref = 'gpioOutputTableExpanded' ;
   } else if (source === 'softpwm'){
       ref = 'gpioSoftPWMTableExpanded' ;
   }
   si (this[ref].filter(e => e.bcm_id === item.bcm_id).length > 0){
     // supprimer l'élément
     this[ref] = this[ref].filter(e => e.bcm_id !== item.bcm_id) ;
   }
   else {
     // ajouter l'élément
     this[ref].push(item) ;
   }
},

dans configGpio, je fais des choses similaires - mais au lieu de supprimer tous les éléments, je filtre et supprime l'élément qui correspond au bcm_id qui m'a été transmis.

Si l'élément n'est pas présent, je le pousse dans la variable étendue.

C'est la raison pour laquelle j'ai besoin de l'élément entier, et pas seulement du bcm_id. J'ai choisi d'avoir une symétrie dans mon code, donc configGpioAll qui techniquement n'a besoin que du bcm_id obtient aussi l'élément entier.