Ist es möglich, Daten zu binden, die für die Negation ("!") Einer booleschen ViewModel-Eigenschaft sichtbar sind?

162

Ich möchte eine Eigenschaft in meinem ViewModel verwenden, um das anzuzeigende Symbol umzuschalten, ohne eine separate berechnete Eigenschaft der Umkehrung zu erstellen. Ist das möglich?

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

Mein ViewModel hat eine Eigenschaftsperiode, die eine Reihe von Monaten umfasst, wie folgt:

var month = function() {
    this.charted = ko.observable(false);
};
agradl
quelle
3
@Niko: Es ist nicht wirklich eine doppelte Frage. Das OP der Frage, auf die Sie sich beziehen, wusste bereits, dass es möglich ist, die Negation eines Observablen datengebunden zu haben, fragt sich jedoch, warum es wie eine Funktion aufgerufen werden muss. Das OP dieser Frage hier wusste überhaupt nicht, wie man das macht, und hat diese andere Frage offensichtlich nicht gefunden. Ich bin froh, dass ich diese Frage hier gefunden habe - was hauptsächlich dem beschreibenden Titel zu verdanken ist.
Oliver

Antworten:

281

Wenn Sie ein Observable in einem Ausdruck verwenden, müssen Sie darauf wie folgt zugreifen:

visible: !charted()

RP Niemeyer
quelle
33
Vielleicht sollten wir eine versteckte Bindung machen :) Wir haben aktivieren und deaktivieren.
John Papa
Ist die Dokumentation damit nicht einverstanden oder verstehe ich diese Seite völlig falsch: knockoutjs.com/documentation/css-binding.html
Devil's Advocate
Egal, ich denke "isSevere" ist kein beobachtbares, sondern ein einfaches altes Eigentum, daher meine Verwirrung.
Devil's Advocate
3
Wenn Sie! Charted verwenden, erhalten Sie! [Funktion]. [Funktion] ist wahr! [Funktion] wird falsch und wird immer falsch sein, wenn Sie diese Syntax verwenden. jsfiddle.net/datashaman/E58u2/3
datashaman
1
Sie fügten tatsächlich hiddenBindung in v3.5.0
Grin
53

Ich stimme John Papas Kommentar zu, dass es eine eingebaute hiddenBindung geben sollte. Eine dedizierte hiddenBindung bietet zwei Vorteile :

  1. Einfachere Syntax, dh. hidden: chartedstatt visible: !charted().
  2. Weniger Ressourcen, da Knockout können die beobachtbaren beobachten charteddirekt, anstatt die Schaffung eines computedzu beobachten !charted().

Es ist jedoch einfach genug, eine hiddenBindung wie folgt zu erstellen :

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

Sie können es genau wie die integrierte visibleBindung verwenden:

<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>
Dave
quelle
9
Dies funktionierte nicht für mich ohne Rückkehrreturn !ko.utils.unwrapObservable(valueAccessor());
Mehmet Ataş
Danke @ MehmetAtaş - Ich habe die hiddenBindung gemäß Ihrem Kommentar korrigiert . (Übrigens habe ich CoffeeScript in meinem Projekt verwendet, als ich dies ursprünglich gepostet habe. Die Syntax von CoffeeScript macht es nicht offensichtlich, wenn eine Rückgabe beabsichtigt ist.)
Dave
9

Es ist wenig verwirrend, wie Sie tun müssen

visible:!showMe()

so tat ich

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

Mein Modell ist

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

Geige einchecken http://jsfiddle.net/khanSharp/bgdbm/

Jhankar Mahbub
quelle
4

Sie könnten meine Schalter- / Fallbindung verwenden, die case.visibleund enthält 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>

Sie könnten es auch als haben

        <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>
Michael Best
quelle
Ich habe gerade festgestellt, dass dies eine alte Frage ist, hoffe aber, dass dies für jemanden nützlich sein könnte.
Michael Best
1

Um die Bindung auf Änderungen an der Eigenschaft aufmerksam zu machen, habe ich den sichtbaren Bindungshandler kopiert und invertiert:

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 = "";
    }
};
Yogev Smila
quelle
0

Haftungsausschluss: Diese Lösung dient nur zu Unterhaltungszwecken.

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
-->
THX-1138
quelle
0

Ich hatte das gleiche Problem damit, wie man ein Gegenteil eines Booleschen Observablen verwendet. Ich habe eine einfache Lösung gefunden:

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

};

Jetzt in Ihrem HTML sollten Sie dies tun

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

Wenn das Programm startet, ist nur "Text1" sichtbar, da "false === false is TRUE" und Text2 nicht sichtbar ist.

Nehmen wir an, wir haben eine Schaltfläche, die das Ereignis "collectPlacesData on click" aufruft. Jetzt ist Text1 nicht sichtbar, da "true === false is FALSE" und Text 2 nur sichtbar ist.

Eine andere mögliche Lösung könnte die Verwendung von berechnetem Observable sein, aber ich denke, es ist eine überkomplizierte Lösung für ein so einfaches Problem.

ccastanedag
quelle
-1

Kann auch so versteckt verwenden :

 <div data-bind="hidden: isString">
                            <input type="text" class="form-control" data-bind="value: settingValue" />
                        </div>
Dev-Systematix
quelle