¿Cómo modelar estructuras If-Else en vistas vinculadas a datos?

95

Constantemente me encuentro usando este idioma en plantillas HTML basadas en 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 una forma mejor / más limpia de hacer condicionales en KO, o hay un enfoque mejor que simplemente usar las construcciones tradicionales if-else?

Además, me gustaría señalar que algunas versiones de Internet Explorer (IE 8/9) no analizan correctamente el ejemplo anterior. Consulte esta pregunta SO para obtener más información. El resumen rápido es que no use comentarios (enlaces virtuales) dentro de las etiquetas de la tabla para admitir IE. Utilice en su tbodylugar:

<tbody data-bind="if: display"><tr><td>hello</td></tr></tbody>
Jensen Ching
fuente
Cualquiera que vea
Brian M. Hunt

Respuestas:

64

Hay un par de formas diferentes de manejar este tipo de código.

  • con una combinación si / si no como lo es ahora. Esto funciona bien y no es muy detallado.

  • El enlace de interruptor / caso de Michael Best ( https://github.com/mbest/knockout-switch-case ) es bastante flexible y puede permitirle manejar fácilmente esto y otros más complicados (más estados que verdadero / falso).

  • Otra opción es utilizar plantillas dinámicas. Uniría un área a una o más plantillas con el nombre de la plantilla que se usa según un observable. Aquí hay una publicación que escribí sobre este tema hace un tiempo: http://www.knockmeout.net/2011/03/quick-tip-dynamically-changing.html . En su escenario, podría verse así:

<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>

La getCellTemplatefunción podría vivir en cualquier lugar, pero se le daría el elemento ($ data) como primer argumento y devolvería el nombre de la plantilla a usar.

RP Niemeyer
fuente
extraño, mi HTML no aparecerá. También me di cuenta de que Michael dio prácticamente la misma respuesta.
RP Niemeyer
Gracias por una lista completa de opciones. Supongo que mi estilo de código original funciona para casos simples. Verificaré las otras opciones cuando surja la necesidad.
Jensen Ching
¿Hay alguna manera de personalizar la plantilla aún más, como "template: data, proppertyName: 'email'" y en la plantilla data-bind = "text: $ data [propertyName]"?
Onur Topal
@OnurTOPAL: sí, siempre que tenga una variable propertyName, puede determinar dinámicamente el nombre de la plantilla.
RP Niemeyer
44

Un enfoque es utilizar plantillas con nombre (que pueden admitir el paso 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>

Otra opción es usar mi complemento switch / case , que funcionaría así:

<!-- 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 -->
Michael mejor
fuente
Gracias. Tendré en cuenta el complemento switch / case para cuando surja la necesidad.
Jensen Ching
2
¡Buen plugin que llegaste! Usaré este seguro.
Kukks
Las plantillas con nombre funcionan muy bien y admiten escenarios de tipo if elseif elseif else anidando el operador ternario.
4

Para evitar que se vuelva a calcular el enlace de nocaut cuando se usa una combinación de if: / ifnot: puede usarlos junto con la construcción 'with:'

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

Ahora también existe el knockout-elseenlace / complemento (que escribí para abordar este problema).

Brian M. Hunt
fuente