jQuery Templates e combos preenchidas

Estou usando o plugin de template do jQuery em uma tela de um sistema que estou construindo, e encontrei o seuginte problema, que mostro no exemplo abaixo.

Vamos supor que temos uma página que contém uma tabela usada para edição de informações. Lista de cidades e estados, por exemplo.

image

Nesta listagem, conforme vamos precisando de novas linhas, vamos incluindo informando o nome da cidade e selecionando o estado na combo. Abaixo está o código que faz essa inclusão:

<!DOCTYPE html>
<html>
<head>
    <script src="http://code.jquery.com/jquery-latest.min.js"></script>
    <script src="http://ajax.microsoft.com/ajax/jquery.templates/beta1/jquery.tmpl.min.js"></script>
</head>
<body>
    <script id="templateLinha" type="text/x-jquery-tmpl">
    <tr>
        <td>
            <input type="text" value="${Cidade}" />
        </td>
        <td>
            <select>
                <option value="GO">GO</option>
                <option value="SP">SP</option>
                <option value="PR">PR</option>
                <option value="RJ">RJ</option>
            </select>
        </td>
    </tr>
    </script>
    <script language="javascript">
        $(document).ready(function () {
            $("#btnAdd").click(function () {
                var cidades = [{ Cidade: $("#txtCidade").val(), Estado: $("#ddlEstado").val()}];
                $("#templateLinha").tmpl(cidades).appendTo("#listaCidades").find("select").val(function (index, value) {
                    return cidades[index].Estado;
                });
            });
        });
    </script>
    <input id="txtCidade" type="text" />
    <select id="ddlEstado">
        <option value="GO">GO</option>
        <option value="SP">SP</option>
        <option value="PR">PR</option>
        <option value="RJ">RJ</option>
    </select>
    <button id="btnAdd">
        Adicionar cidade</button>
    <br /><br />
    <table border="1">
        <thead>
            <tr>
                <td>
                    Cidade
                </td>
                <td>
                    Estado
                </td>
            </tr>
        </thead>
        <tbody id="listaCidades">
            <tr>
                <td>
                    <input type="text" value="Santo André" />
                </td>
                <td>
                    <select>
                        <option value="GO">GO</option>
                        <option value="SP" selected>SP</option>
                        <option value="PR">PR</option>
                        <option value="RJ">RJ</option>
                    </select>
                </td>
            </tr>
        </tbody>
    </table>
</body>
</html>



Perceba que no código estou utilizando a funcionalidade de template para a inclusão da nova linha. Dentro da tag <script> chamada “templateLinha”, tenho todo o modelo que será utilizado para esta inclusão. Note que trata-se apenas de uma nova linha na tabela, contendo uma caixa de texto e uma combo. Veja que no lugar do valor da caixa de texto, eu coloquei ${Cidade}. É a partir da substituição desse campo que o modelo da linha será preenchido automaticamente (e veja também que, pela característica de um objeto do tipo <select>, não conseguimos fazer essa substituição, e este será nosso problema.



No código que é executado no clique do botão, eu obtenho os valores que serão passados ao template, transformados em um array de objetos, e chamo a função abaixo, que faz com que os dados sejam aplicados no template “templateLinha”, e anexados no objeto “listaCidades”.



$("#templateLinha").tmpl(cidades).appendTo("#listaCidades");

No entanto, ao executar, vemos que a combo não é preenchida com o valor que queremos (ela fica com o valor padrão, que é o primeiro da lista, “GO”). Isto ocorre pois não temos como substituir um valor dentro da tag <select> para que seja ajustado o valor da combo (diferentemente de um objeto do tipo <input>, que é apenas substituir o conteúdo da propriedade “value”).



image



Neste caso específico, a resolução não pode ser feita apenas com o template do jQuery (minto, até consegue usando a funcionalidade de “if” do plugin de Template do jQuery, mas se usar desta maneira terá que construir o código da combo na mão, e não poderá, por exemplo, utilizar um helper de geração de HTML como o método Html.DropDownList() do ASP.NET MVC).



Bom, para resolver este problema de uma forma elegante, temos que contar com a função .val(xxx) do jQuery, só que não passando um valor mas sim uma função que retorne este valor. Com isso, podemos fazer uma iteração nos valores do array, obtendo o dado correto. Veja o trecho do código alterado abaixo (destacado em azul).



<script language="javascript"> 
    $(document).ready(function () {
        $("#btnAdd").click(function () {
            var cidades = [{ Cidade: $("#txtCidade").val(), Estado: $("#ddlEstado").val()}];
           $("#templateLinha").tmpl(cidades).appendTo("#listaCidades").find("select").val(function (index, value) {
                return cidades[index].Estado;
            });
        });
    });
</script>

image


Desta maneira, logo após a inclusão da linha na tabela, já fazemos a correção dos valores da combo.


[]’s e até a próxima!

Comentários

Postagens mais visitadas deste blog

Trocando configurações padrão do Live TIM

Uma proposta de Clean Architecure com Modelo de Atores

Testes automatizados em sistemas autenticados com certificados digitais, usando Selenium e PhantomJS