Como modelar estruturas If-Else em visualizações vinculadas a dados?


95

Eu constantemente me pego usando este idioma em modelos HTML baseados em KO:

<!-- ko if: isEdit -->
<td><input type="text" name="email" data-bind="value: email" /></td>
<!-- /ko -->
<!-- ko ifnot: isEdit -->
<td data-bind="text: email"></td>
<!-- /ko -->

Existe uma maneira melhor / mais limpa de fazer condicionais em KO, ou há uma abordagem melhor do que apenas usar construções if-else tradicionais?

Além disso, gostaria apenas de salientar que algumas versões do Internet Explorer (IE 8/9) não analisam o exemplo acima corretamente. Por favor, veja esta pergunta do SO para mais informações. O resumo rápido é: não use comentários (ligações virtuais) dentro de tags de tabela para oferecer suporte ao IE. Em tbodyvez disso, use :

<tbody data-bind="if: display"><tr><td>hello</td></tr></tbody>

Respostas:


64

Existem algumas maneiras diferentes de lidar com esse tipo de código.

  • com uma combinação if / ifnot como você está agora. Isso funciona bem e não é muito prolixo.

  • A vinculação de switch / case de Michael Best ( https://github.com/mbest/knockout-switch-case ) é bastante flexível e pode permitir que você lide facilmente com isso e com outros mais complicados (mais estados do que verdadeiro / falso).

  • Outra opção é usar modelos dinâmicos. Você vincularia uma área a um ou mais modelos com o nome do modelo sendo usado com base em um observável. Aqui está um post que escrevi sobre esse tópico há algum tempo: http://www.knockmeout.net/2011/03/quick-tip-dynamically-changing.html . Em seu cenário, pode ser assim:

<td data-bind="template: $root.getCellTemplate"></td>

<script id="cellEditTmpl" type="text/html">
    <input type="text" name="email" data-bind="value: email" />
</script>

<script id="cellTmpl" type="text/html">
    <span data-bind="text: email"></span>
</script>

A getCellTemplatefunção poderia residir em qualquer lugar, mas receberia o item ($ data) como o primeiro argumento e retornaria o nome do modelo a ser usado.


estranho, meu HTML não vai aparecer. Também acabei de notar que Michael deu praticamente a mesma resposta.
RP Niemeyer

Obrigado por uma lista abrangente de opções. Acho que meu estilo de código original funciona para casos simples. Vou verificar as outras opções quando for necessário.
Jensen Ching

existe uma maneira de personalizar o template ainda mais, como "template: data, proppertyName: 'email'" e no template data-bind = "text: $ data [propertyName]".
Onur Topal

@OnurTOPAL - sim, contanto que você tenha uma variável propertyName, você pode determinar dinamicamente o nome do modelo.
RP Niemeyer

44

Uma abordagem é usar modelos nomeados (que podem suportar a passagem de argumentos):

<!-- ko template: isEdit() ? 'emailEdit' : 'emailDisplay' --><!-- /ko -->
<script id="emailEdit" type="text/html">
    <td><input type="text" name="email" data-bind="value: email" /></td>
</script>
<script id="emailDisplay" type="text/html">
    <td data-bind="text: email"></td>
</script>

Outra opção é usar meu plug-in switch / case , que funcionaria assim:

<!-- ko switch -->
    <!-- ko case: isEdit -->
        <td><input type="text" name="email" data-bind="value: email" /></td>
    <!-- /ko -->
    <!-- ko case: $else -->
        <td data-bind="text: email"></td>
    <!-- /ko -->
<!-- /ko -->

Obrigado. Vou manter o plug-in switch / case em mente para quando for necessário.
Jensen Ching

2
Belo plugin você tem aí! Vou usar este com certeza.
Kukks de

Os modelos nomeados funcionam muito bem e oferecem suporte a cenários de tipo if elseif elseif aninhando o operador terniário.

4

Para evitar o recálculo da ligação knockout ao usar a combinação de if: / ifnot: você pode usá-los em conjunto com a construção 'with:'

    <!-- ko with: $data.DoSomePerformanceCriticalWork($data.SomeParameter()) -->
        <!-- ko if: $data.Condition() -->
           ... some markup ...
        <!-- /ko -->
        <!-- ko ifnot: $data.Condition() -->
           ... some markup ...
        <!-- /ko -->
    <!-- /ko -->

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.