web-dev-qa-db-fra.com

Est-il possible de lier des données à la négation ("!") D'une propriété ViewModel booléenne?

J'aimerais utiliser une propriété sur mon ViewModel pour changer l'icône à afficher sans créer une propriété calculée séparée de l'inverse. Est-ce possible?

<tbody data-bind="foreach: periods">
  <tr>
    <td>
      <i class="icon-search" data-bind="visible: !charted, click: $parent.pie_it"></i>
      <i class="icon-remove" data-bind="visible: charted, click: $parent.pie_it"></i>
    </td>
  </tr>
</tbody>

Mon ViewModel a une propriété périodes qui est un tableau de mois, comme ceci:

var month = function() {
    this.charted = ko.observable(false);
};
154
agradl

Lorsque vous utilisez un observable dans une expression, vous devez y accéder en tant que fonction telle que:

visible: !charted()

273
RP Niemeyer

Je suis d'accord avec le commentaire de John Papa selon lequel il devrait exister une liaison hidden intégrée. Une liaison hidden dédiée présente deux avantages:

  1. Syntaxe plus simple, ie. hidden: charted au lieu de visible: !charted().
  2. Moins de ressources, étant donné que Knockout peut observer l'observable charted plutôt que de créer un computed pour observer !charted().

C'est assez simple pour créer une liaison hidden, cependant, comme ceci:

ko.bindingHandlers.hidden = {
  update: function(element, valueAccessor) {
    ko.bindingHandlers.visible.update(element, function() {
      return !ko.utils.unwrapObservable(valueAccessor());
    });
  }
};

Vous pouvez l'utiliser comme la liaison visible intégrée:

<i class="icon-search" data-bind="hidden: charted, click: $parent.pie_it"></i>
<i class="icon-remove" data-bind="visible: charted, click: $parent.pie_it"></i>
53
Dave

C'est peu déroutant, comme vous devez le faire

visible:!showMe()

alors je l'ai fait

<span data-bind="visible:showMe">Show</span>
<span data-bind="visible:!showMe()">Hide</span>
<label><input type="checkbox" data-bind="checked:showMe"/>toggle</label>​

mon modèle est

var myModel={
    showMe:ko.observable(true)
}
ko.applyBindings(myModel);    

Check in fiddle http://jsfiddle.net/khanSharp/bgdbm/

9
KhanSharp

Vous pouvez utiliser ma liaison switch/case , qui inclut case.visible et casenot.visible.

<tbody data-bind="foreach: periods">
    <tr>
        <td data-bind="switch: true">
        <i class="icon-search" data-bind="case.visible: $else, click: $parent.pie_it"></i>
        <i class="icon-remove" data-bind="case.visible: charted, click: $parent.pie_it"></i>
        </td>
    </tr>
</tbody>

Vous pourriez aussi l'avoir comme

        <i class="icon-search" data-bind="casenot.visible: charted, click: $parent.pie_it"></i>
        <i class="icon-remove" data-bind="case.visible: $else, click: $parent.pie_it"></i>
3
Michael Best

Afin de rendre la liaison consciente des modifications apportées à la propriété, j'ai copié le gestionnaire de liaison visible et l'inversé:

ko.bindingHandlers.hidden = {
    update: function (element, valueAccessor) {
        var value = ko.utils.unwrapObservable(valueAccessor());
        var isCurrentlyHidden = !(element.style.display == "");
        if (value && !isCurrentlyHidden)
            element.style.display = "none";
        else if ((!value) && isCurrentlyHidden)
            element.style.display = "";
    }
};
1
Yogev Smila

Avertissement: cette solution est uniquement à des fins de divertissement.

ko.extenders.not = function (target) {
    target.not = ko.computed(function () {
        return !target();
    });
};

self.foo = ko.observable(true).extend({ not: null });

<div data-bind="text: foo"></div>     <!-- true -->
<div data-bind="text: foo.not"></div> <!-- false -->

<!-- unfortunately I can't think of a way to be able to use:
    text: foo...not
-->
0
THX-1138

J'avais le même problème sur la façon d'utiliser un opposé à un observable booléen. J'ai trouvé une solution facile:

var ViewModel = function () {
var self = this;

// When program start, this is set to FALSE
self.isSearchContentValid = ko.observable(false);


self.gatherPlacesData = function () {

   // When user click a button, the value become TRUE
   self.isSearchContentValid(true);

};

Maintenant, sur votre HTML, vous devriez le faire

<p data-bind = "visible:isSearchContentValid() === false"> Text 1</p>
<p data-bind = "visible:isSearchContentValid"> Text 2</p>

Lorsque le programme démarre, seul "Text1" est visible car "false === false est TRUE" et Text2 n'est pas visible.

Disons que nous avons un bouton qui appelle l'événement de rassemblementPlacesData sur click. Désormais, Text1 ne sera pas visible car "true === false est FALSE" et Text 2 uniquement.

Une autre solution possible pourrait être d'utiliser l'observable calculé, mais je pense que c'est une solution trop compliquée pour un problème aussi simple.

0
ccastanedag