Ao trabalhar com estruturas de permissões de usuários utilizando o componente el-tree do Element UI, é comum enfrentar desfaios na sincronização de dados entre o backend e o front end. Um problema recorrente ocorre quando a API retorna uma lista de IDs que inclui nós pais. Por padrão, se o componente recebe o ID de um nó pai, ele marca automaticamente todos os seus descendentes como selecionados, o que nem sempre reflete a realidade das permissões parciais.
Embora a propriedade check-strictly resolva a independência dos nós, ela remove a funcionalidade de cascata desejada durante a interação do usuário (marcar um pai e selecionar todos os filhos manualmente). A solução ideal é tratar os dados antes de passá-los para o componente, garantindo que apenas os "nós folha" (nós sem filhos) sejam explicitamente marcados.
Transformação de Dados Planos para Estrutura de Árvore
Muitas vezes, os dados retornados pelo servidor estão em um formato plano (array simples). O primeiro passo é converter essa lista em uma estrutura hierárquica recursiva. O exemplo abaixo demonstra como organizar esses dados utilizando um mapeamento por ID.
function organizarEstruturaHierarquica(listaOriginal) {
const mapaNodos = {};
const estruturaFinal = [];
// Mapeia todos os itens pelo ID para acesso rápido
listaOriginal.forEach(item => {
mapaNodos[item.idRef] = { ...item, subMenus: [] };
});
// Organiza a hierarquia baseada no ID do pai
Object.values(mapaNodos).forEach(nodo => {
const paiId = nodo.idSuperior;
if (paiId && mapaNodos[paiId]) {
mapaNodos[paiId].subMenus.push(nodo);
} else {
estruturaFinal.push(nodo);
}
});
return estruturaFinal;
}
// Exemplo de uso:
this.dadosArvore = organizarEstruturaHierarquica(respostaApi.listaMenu);
Filtragem de Nós Folha para Seleção Precisa
Para evitar que o el-tree marque indevidamente todos os filhos de um nó pai selecionado, devemos identificar quais IDs na lista de permissões do usuário realmente correspondem a nós que não possuem descendentes. Ao definir apenas os IDs das folhas no método setCheckedKeys, o Element UI gerenciará automaticamente o estado de "check parcial" (indeterminado) dos nós superiores.
/**
* Percorre a árvore recursivamente para encontrar IDs de nós que não possuem filhos.
*/
function identificarNosFolha(arvore, listaDestino = []) {
arvore.forEach(nodo => {
if (!nodo.subMenus || nodo.subMenus.length === 0) {
listaDestino.push(nodo.idRef);
} else {
identificarNosFolha(nodo.subMenus, listaDestino);
}
});
return listaDestino;
}
// Lógica de aplicação no componente:
const todasAsFolhasDaArvore = identificarNosFolha(this.dadosArvore);
const idsRecebidosDoBackend = respostaApi.permissoesUsuario.map(p => p.idRef);
// Interseção: Mantemos apenas os IDs que o usuário possui e que são folhas
const chavesParaMarcar = idsRecebidosDoBackend.filter(id =>
todasAsFolhasDaArvore.includes(id)
);
// Aplica a seleção ao componente de árvore
this.$refs.componenteArvore.setCheckedKeys(chavesParaMarcar);
Esta abordagem garante que a interface reflita exatamente o que foi salvo no banco de dados. Se um usuário tiver permissão em apenas dois de cinco subitens, o nó pai aparecerá corretamente com o estado indeterminado, mantendo a funcionalidade de marcar/desmarcar todos os filhos de forma reativa quando o usuário interagir diretamnete com o checkbox do pai.