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:
clicando no chevron ou no botão de configuração irá conduzir à abertura da linha de detalhes:
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
- :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:
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.
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.