Vuetify :: Detailzeile programmatisch öffnen

Für das kommende PiCockpit v2.0 Release bereite ich eine GPIO Anwendung vor.

Die GPIO-Einträge sind Tabellenzeilen - und um sie zu konfigurieren, wollen wir in der Lage sein, auf die Detailzeile zuzugreifen, indem wir auf die Schaltfläche configure klicken:

Bild

Wenn Sie entweder auf den Chevron oder auf die Schaltfläche "Konfigurieren" klicken, wird die Detailzeile geöffnet:

Bild

Hier ist die entsprechende Vue-Vorlage:

<v-data-table
   :headers="gpioInputTableHeaders"
   :items="gpioInputTableData"
   :loading="loading"
   item-key="bcm_id"
   loading-text="Warten auf Daten ..."
   feste Überschrift
  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-arrow-up-bold</v-icon>{{item.high}}</span>
     <span v-else-if="”item.state" ><v-icon x-small>mdi-arrow-down-bold</v-icon>{{item.low}}</span>
     <span v-else-if="”item.state" >K.A.</span>
     <span v-else-if="”item.state" >K.A.</span>
     <span v-else>ERROR</span>
   </template>
   <template v-slot:item.action="{ item }">
     <v-btn
       class="mr-2″
       color="primary"
       klein
       @click.ctrl.exact="configGpioAll('input', item)"
       @click.exact="configGpio('input', item)"

     >
       mdi-hammer-wrench
       Konfigurieren Sie
     </v-btn>
     <v-btn
       class="mr-2″
       color="error"
       klein
       @click="remove_gpio('input', item.bcm_id)"
     >
       mdi-trash-can-outline
       entfernen
     </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>        

Wie Sie sehen können, habe ich eine weitere Komponente für den Slot "Expanded-Item" eingefügt. Diese Komponente ist für unsere aktuelle Diskussion irrelevant, daher stelle ich keinen Code für sie bereit.

Ich habe die wichtigen Teile oben hervorgehoben.

Diese sind:

  • :items="gpioInputTableData" - dies verknüpft die Daten mit dem Schlüssel "items" der Vuetify-Datentabelle
  • item-key="bcm_id" - Dies ist wichtig, um einen eindeutigen Schlüssel für jeden Eintrag Ihrer Daten (die als Array an Items übergeben werden) zu erhalten.
    • Wenn Sie diese Einstellung nicht vornehmen, werden alle Detailzeilen auf einmal geöffnet und auf einmal geschlossen.
    • der Wert sollte wie besprochen eindeutig sein; falls Ihre Daten möglicherweise doppelte Werte in allen Schlüsseln haben, müssen Sie einen zusätzlichen eindeutigen Schlüssel erstellen
  • show-expand - Hier werden die Chevrons angezeigt Bild
  • :expanded.sync="gpioInputTableExpanded" - Beachten Sie die Verwendung des Modifikators sync, um Änderungen zurück zu synchronisieren! Dies ist eine Variable, in der die aktuell erweiterten Elemente gespeichert werden.

dann:

  •  @click.ctrl.exact="configGpioAll('input', item)" - Wie Sie sehen können, rufe ich bei Strg+Klick eine Utility-Funktion auf, die alle Erweiterungs-Slots umschaltet, je nach dem Status des aktuellen Elements. Ich übergebe das Element, das erweitert werden soll, an die Funktion
  • @click.exact="configGpio('input', item)" - wie Sie sehen, rufe ich bei einem exakten Klick eine andere Dienstfunktion auf (wir werden gleich dazu kommen), wobei ALSO das aktuelle Element übergeben wird

endlich:

  • <template v-slot:expanded-item=”{ headers, item }”> - dieser Slot enthält das erweiterte Element. Die Übergabe der Kopfzeilen ist wichtig:
  • <td :colspan="”headers.length”"> - ... weil Sie damit eine Zelle erstellen können, die sich über alle Spalten erstreckt

So sieht mein data() aus (Auszug):

Daten () {
   zurück {
     Laden: wahr,
     gpioInputTableData: [],
     gpioInputTableHeaders: [
       { Text: 'Name', Wert: 'Name'},
       { Text: 'Wert', Wert: 'Wert'},
       { Text: 'Aktion', Wert: 'Aktion'}
     ],
     gpioInputTableExpanded: []

  }
},

Und hier sind die beiden Nutzenfunktionen:

Bild

configGpioAll: function (source, item){
         var ref = null;
         var refTable = null;
         wenn (Quelle === 'Eingabe'){
             ref = 'gpioInputTableExpanded';
             refTable = 'gpioInputTableData';
         } else if (source === 'output'){
             ref = 'gpioOutputTableExpanded';
             refTable = 'gpioOutputTableData';
         } else if (source === 'softpwm'){
             ref = 'gpioSoftPWMTableExpanded';
             refTable = 'gpioSoftPWMTableData';
         }
         // stimmen wir für diesen Artikel überein (ist er geöffnet?)
        if (this[ref].filter(e => e.bcm_id === item.bcm_id).length > 0){
           // alle Elemente entfernen
           console.log("configGpioAll: Entfernen");
           this[ref] = [];
         }
         sonst {
           console.log("configGpioAll: Hinzufügen");
           // alle Elemente hinzufügen
           this[ref] = this[refTable];
         }
       },

in configGpioAll prüfe ich, ob ich die input-, output- oder softpwm-Tabelle habe (um doppelten Code zu vermeiden), und richte Verweise auf die entsprechende erweiterte Variable (siehe Daten oben) und die Tabellendaten selbst ein.

Wenn das Element in den erweiterten Daten enthalten ist (ich stimme mit meinem eindeutigen Schlüssel bcm_id überein), schließe ich alle erweiterten Elemente - Dazu setze ich die erweiterte Variable einfach auf ein leeres Array.

Wenn das Element NICHT in den erweiterten Daten enthalten ist, öffne ich alle Elemente, indem ich alle Tabellendaten in das Element einfüge.

Hinweis: Es könnte sich lohnen zu experimentieren, ob ein Array von Objekten, das nur die eindeutigen Schlüssel enthält, ausreicht, um dies ebenfalls zu tun.

Bild

configGpio: function (source, item){
   var ref = null;
   wenn (Quelle === 'Eingabe'){
       ref = 'gpioInputTableExpanded';
   } else if (source === 'output'){
       ref = 'gpioOutputTableExpanded';
   } else if (source === 'softpwm'){
       ref = 'gpioSoftPWMTableExpanded';
   }
   if (this[ref].filter(e => e.bcm_id === item.bcm_id).length > 0){
     // Entfernen Sie das Element
     this[ref] = this[ref].filter(e => e.bcm_id !== item.bcm_id);
   }
   sonst {
     // Hinzufügen der Position
     this[ref].push(item);
   }
},

in configGpio mache ich ähnliche Dinge - aber anstatt alle Elemente zu entfernen, filtere ich und entferne das Element, das mit der bcm_id übereinstimmt, die ich übergeben bekam.

Wenn das Element nicht vorhanden ist, schiebe ich es in die erweiterte Variable.

Dies ist der Grund, warum ich das gesamte Element benötige, nicht nur die bcm_id. Ich habe mich für Symmetrie in meinem Code entschieden, so dass configGpioAll, das technisch nur die bcm_id benötigt, auch das gesamte Element erhält.