Voltar para o blog
Desenvolvimento Fluig4 min de leitura

Tabela pai e filho no Fluig: guia e erros comuns

Como criar uma tabela pai e filho no Fluig, adicionar linhas, ler os dados em eventos e datasets e evitar os erros que apagam a linha-modelo.

A tabela pai e filho é o recurso do Fluig para formulários com linhas repetidas, como itens de um pedido, rateios ou um checklist. É simples de começar, mas tem detalhes que causam horas de depuração. O principal deles: a linha que você vê não é a linha que está no HTML.

A estrutura mínima

<table id="itens" tablename="itens" noaddbutton="true" nodeletebutton="true">
    <thead>
        <tr>
            <th>Produto</th>
            <th>Quantidade</th>
            <th></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td><input type="text" name="produto" class="form-control" /></td>
            <td><input type="text" name="quantidade" class="form-control" /></td>
            <td><button type="button" onclick="fnWdkRemoveChild(this)">Remover</button></td>
        </tr>
    </tbody>
</table>
<button type="button" onclick="wdkAddChild('itens')">Adicionar</button>

O atributo tablename é obrigatório. Sem ele, o Fluig não injeta os recursos da tabela. O sintoma é wdkAddChild is not defined no console e um botão Adicionar que parece morto. Um id não substitui esse atributo.

noaddbutton e nodeletebutton escondem os botões padrão, o que é útil quando você quer controlar a aparência.

Linha-modelo e linhas de dados

A linha do tbody não guarda dados. Ela é a linha-modelo, e o Fluig a mantém escondida para copiá-la a cada wdkAddChild. As linhas de dados são clones, com o nome do campo seguido de ___ e um índice:

produto         linha-modelo, escondida
produto___1     primeira linha de dados
produto___2     segunda linha de dados

Aqui está a armadilha: a linha-modelo e os clones têm os mesmos atributos detail e detailname. Se o seu código usar esses atributos para limpar ou esconder linhas, ele atinge os dois.

Em processos que acompanhamos, isso causou três problemas parecidos:

  • Uma rotina que apagava tr[detail="true"] removeu também a linha-modelo. Depois disso, wdkAddChild não tinha mais o que copiar.
  • Um filtro que ignorava tr[detailname] deixou de contar as linhas reais, e o resumo ficou zerado.
  • Um CSS que escondia tr[detailname] com !important sumiu com todas as linhas.

A regra é separar modelo e dado pelo sufixo:

// Linhas de dados, sem pegar a linha-modelo
$('input[name^="produto___"]').each(function () {
    var indice = this.name.split("___")[1];
    console.log(indice, this.value);
});

Adicionar uma linha com valores

wdkAddChild retorna o índice da nova linha, o que permite preencher os campos em seguida:

var indice = wdkAddChild("itens");
$("#produto___" + indice).val("Parafuso");
$("#quantidade___" + indice).val("10");

Para carregar a tabela ao abrir o formulário, faça isso dentro de $(function () { ... }), depois que a página estiver pronta.

Ler e gravar no servidor

Em um evento de processo:

var indices = hAPI.getChildrenIndexes("itens");

for (var i = 0; i < indices.length; i++) {
    var produto = hAPI.getCardValue("produto___" + indices[i]);
    log.info("[COMPRAS] item: " + produto);
}

A documentação lembra que esses dados só existem depois de salvos, portanto use eventos After.

Para adicionar uma linha pelo servidor, use hAPI.addCardChild:

var linha = new java.util.HashMap();
linha.put("produto", "Parafuso");
linha.put("quantidade", "10");
hAPI.addCardChild("itens", linha);

Ao remover várias linhas, percorra de trás para frente. A remoção pode reorganizar os índices, e um laço normal acaba pulando linhas.

Consultar a tabela por dataset

O dataset do formulário traz a tabela filha quando você informa o tablename, junto com os identificadores da ficha:

var c1 = DatasetFactory.createConstraint("tablename", "itens", "itens", ConstraintType.MUST);
var c2 = DatasetFactory.createConstraint("metadata#id", idFicha, idFicha, ConstraintType.MUST);
var c3 = DatasetFactory.createConstraint("metadata#version", versao, versao, ConstraintType.MUST);

var filhos = DatasetFactory.getDataset("ds_meu_formulario", null, new Array(c1, c2, c3), null);

O guia de dataset explica os demais filtros. Em volumes grandes, consultar a tabela de muitas fichas pelo dataset fica lento, e isso costuma pedir outra abordagem.

Bloquear campos da tabela

Evite form.setEnabled em campos pai e filho. Em nossos projetos, o Fluig alterou o nome do campo com um prefixo, e isso quebrou o JavaScript que o manipulava. Para travar uma coluna, use readonly por JavaScript ao carregar a tabela.

Lembre-se também de que disabled não é enviado no formulário. Esse e outros casos estão em erros silenciosos no Fluig.

Checklist de problemas

  • wdkAddChild is not defined: falta tablename na <table>.
  • Adicionar não faz nada: a linha-modelo foi removida do DOM.
  • Linhas somem na tela: algum CSS ou script esconde tr[detailname].
  • Valor não chega no evento: o evento roda antes de salvar. Use um evento After.
  • Campo novo some: a definição do formulário precisa ser publicada de novo.

Perguntas frequentes

O que é tabela pai e filho no Fluig?

É uma tabela de formulário com linhas repetidas ligadas a uma mesma ficha, como os itens de um pedido.

Como adicionar uma linha por JavaScript?

Chame wdkAddChild("nomeDaTabela"). A função devolve o índice, que você usa para preencher os campos campo___indice.

Como ler os dados no servidor?

Use hAPI.getChildrenIndexes("tabela") para obter os índices e hAPI.getCardValue("campo___" + indice) para ler cada campo.

Formulários com muitas tabelas e regras costumam ser o ponto mais frágil de um processo. Se esse é o seu caso, a consultoria Fluig da MyQube pode ajudar. Vamos conversar.

Sua operação ainda depende de planilhas e retrabalho?

Agende uma conversa gratuita e receba um diagnóstico inicial dos seus gargalos operacionais.

Falar com a MyQube

Ou conheça nosso serviço de Consultoria Fluig