Vuetify :: Abrir linha de detalhes programática

Para o próximo lançamento do PiCockpit v2.0, estou a preparar uma aplicação GPIO.

As entradas GPIO são linhas de tabela - e para configurá-las, queremos poder acessar a linha de detalhes clicando no botão de configuração:

imagem

clicando no chevron ou no botão de configuração irá conduzir à abertura da linha de detalhes:

imagem

Aqui está o modelo Vue correspondente:

<v-tabela de dados
   cabeçalhos="gpioInputTableHeaders"
   :items="gpioInputTableData"
   :carregando="carregando"
   item-key="bcm_id"
   loading-text="à espera de dados..."
   cabeça-fixa
  mostrar-expandir
   :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.baixo}}</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>
   <modelo v-slot:item.action="{item }">
     <v-btn
       class="mr-2″
       cor="principal"
       pequeno
       @click.ctrl.exact="configGpioAll('input', item)"
       @click.exact="configGpio('input', item)"

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

Como você pode ver, eu embrulho outro componente para o slot de item expandido. Este componente é irrelevante para nossa discussão atual, portanto, não forneço código para ele.

Eu sublinhei as partes importantes acima.

Estes são:

  • :items="gpioInputTableData" - isto liga os dados à chave dos itens da tabela de dados Vuetify
  • item-key="bcm_id" - isto é importante para dar uma chave única para cada entrada dos seus dados (que é dada como uma matriz aos itens).
    • se você omitir esta configuração, todas as suas linhas de detalhes serão abertas e fechadas de uma só vez.
    • o valor deve ser único como discutido; caso seus dados tenham valores duplicados em todas as chaves, você precisa criar uma chave adicional única
  • mostrar-expandir - isto vai mostrar aos Chevrons imagem
  • :expanded.sync="gpioInputTableExpanded" - note o uso do modificador de sincronia, para sincronizar as mudanças de volta! Esta é uma variável para armazenar os itens expandidos no momento.

então:

  •  @click.ctrl.exact="configGpioAll('input', item)" - como você pode ver, em Ctrl + Click, eu estou chamando uma função utilitária para alternar todos os slots de expansão, dependendo do estado do item atual. Eu passo o item para ele, que deve ser expandido
  • @click.exact="configGpio('input', item)" - como você vê, em um clique exato, eu chamo outra função de utilidade (vamos chegar a estes em breve), passando TAMBÉM no item atual

finalmente:

  • <template v-slot:expanded-item=”{ headers, item }”> - esta ranhura segura o item expandido. Passar nos cabeçalhos é importante:
  • <td :colspan="”headers.length”"> – ... porque permite a criação de uma célula que abrange todas as colunas

Aqui está como meus dados() se parecem (trecho):

dados () {
   retornar {
     Carregamento: verdade,
     gpioInputTableData: [],
     gpioInputTableHeaders: [
       { texto: 'Nome', valor: 'nome'},
       { texto: 'Valor', valor: 'valor'},
       { texto: 'Acção', valor: 'acção'}
     ],
     gpioInputTableExpanded: []

  }
},

E aqui estão as duas funções de utilidade:

imagem

configGpioAll: função (fonte, item){
         var ref = nulo;
         var refTable = nulo;
         se (fonte ==== 'input'){
             ref = 'gpioInputTableExpanded';
             refTable = 'gpioInputTableData';
         } else if (source ==== 'output'){
             ref = 'gpioOutputTableExpanded';
             refTable = 'gpioOutputTableData';
         } else if (source ==== 'softpwm'){
             ref = 'gpioSoftPWMTableExpanded';
             refTable = 'gpioSoftPWMTableData';
         }
         // estamos à altura deste item (ele está aberto?)
        if (this[ref].filter(e => e.bcm_id === item.bcm_id).length > 0){
           // remover todos os itens
           console.log("configGpioAll: removendo");
           isto[ref] = [];
         }
         senão (
           console.log("configGpioAll: adicionando");
           // adicionar todos os itens
           this[ref] = this[refTable];
         }
       },

no configGpioAll, eu verifico se tenho a tabela de entrada, saída ou softpwm (para evitar duplicação de código), e configuro referências à variável expandida apropriada (ver dados acima), e os próprios dados da tabela.

Se o item estiver contido dentro dos dados expandidos (eu correspondo pela minha chave única, bcm_id), eu fecho todos os itens expandidos - para isso eu simplesmente defino a variável expandida para uma matriz vazia.

Se o item NÃO estiver contido nos dados expandidos, abro todos os itens, colocando todos os dados da tabela dentro dele.

Nota: pode valer a pena experimentar se um conjunto de objectos contendo apenas as chaves únicas pode ser suficiente para que isto também funcione.

imagem

configGpio: função (fonte, item){
   var ref = nulo;
   se (fonte ==== 'input'){
       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){
     // remover o item
     this[ref] = this[ref].filter(e => e.bcm_id !== item.bcm_id);
   }
   senão (
     // adicionar o item
     este[ref].push(item);
   }
},

no configGpio, eu faço coisas semelhantes - mas em vez de remover todos os itens, eu filtro e removo o item que corresponde ao bcm_id em que fui passado.

Se o item não estiver presente, eu o empurro para a variável expandida.

Esta é a razão de eu precisar do item inteiro, não apenas do bcm_id. Eu optei por ter simetria no meu código, então configGpioAll que tecnicamente só precisa do bcm_id também recebe o item inteiro.