Comment modéliser des structures If-Else dans des vues liées aux données?

95

Je me retrouve constamment à utiliser cet idiome dans des modèles HTML basés sur 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-t-il un moyen meilleur / plus propre de faire des conditions dans KO, ou y a-t-il une meilleure approche que d'utiliser simplement des constructions if-else traditionnelles?

De plus, je voudrais juste souligner que certaines versions d'Internet Explorer (IE 8/9) n'analysent pas correctement l'exemple ci-dessus. Veuillez consulter cette question SO pour plus d'informations. Le résumé rapide est de ne pas utiliser de commentaires (liaisons virtuelles) à l'intérieur des balises de table pour prendre en charge IE. Utilisez tbodyplutôt le:

<tbody data-bind="if: display"><tr><td>hello</td></tr></tbody>
Jensen Ching
la source
Quiconque regarde cela peut souhaiter suivre github.com/knockout/knockout/issues/962
Brian M. Hunt

Réponses:

64

Il existe plusieurs manières de gérer ce type de code.

  • avec une combinaison if / ifnot comme vous l'êtes maintenant. Cela fonctionne très bien et n'est pas terriblement verbeux.

  • La liaison switch / case de Michael Best ( https://github.com/mbest/knockout-switch-case ) est assez flexible et peut vous permettre de gérer facilement cela et les plus compliqués (plus d'états que true / false).

  • Une autre option consiste à utiliser des modèles dynamiques. Vous lieriez une zone à un ou plusieurs modèles avec le nom du modèle utilisé en fonction d'un observable. Voici un article que j'ai écrit sur ce sujet il y a quelque temps: http://www.knockmeout.net/2011/03/quick-tip-dynamically-changing.html . Dans votre scénario, cela pourrait ressembler à:

<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 getCellTemplatefonction pourrait vivre n'importe où, mais recevrait l'élément ($ data) comme premier argument et renverrait le nom du modèle à utiliser.

RP Niemeyer
la source
étrange, mon HTML n'apparaîtra pas. Je viens également de remarquer que Michael a donné à peu près la même réponse.
RP Niemeyer
Merci pour une liste complète d'options. Je suppose que mon style de code original fonctionne pour des cas simples. Je vérifierai les autres options lorsque le besoin se fera sentir.
Jensen Ching
existe-t-il un moyen de personnaliser encore plus le modèle, comme "template: data, proppertyName: 'email'" et dans le template data-bind = "text: $ data [propertyName]".
Onur Topal
@OnurTOPAL - oui tant que vous avez une variable propertyName, vous pouvez déterminer dynamiquement le nom du modèle.
RP Niemeyer
44

Une approche consiste à utiliser des modèles nommés (qui peuvent prendre en charge le passage d'arguments):

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

Une autre option est d'utiliser mon plugin switch / case , qui fonctionnerait comme ceci:

<!-- 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 Best
la source
Merci. Je garderai à l'esprit le plugin switch / case en cas de besoin.
Jensen Ching
2
Beau plugin vous y êtes! J'utilisera celui-ci à coup sûr.
Kukks
Les modèles nommés fonctionnent très bien et prennent en charge les scénarios de type if elseif elseif else en imbriquant l'opérateur terniaire.
4

Pour éviter de recalculer la liaison knockout lors de l'utilisation de la combinaison de if: / ifnot: vous pouvez les utiliser en conjonction avec la construction 'with:'

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

Il y a maintenant aussi la knockout-elseliaison / plugin (que j'ai écrit pour résoudre ce problème).

Brian M. Hunt
la source