Czy możliwe jest wiązanie danych widoczne z negacją („!”) Wartości logicznej właściwości ViewModel?


162

Chciałbym użyć właściwości w moim ViewModel, aby przełączyć, która ikona ma być wyświetlana bez tworzenia oddzielnej obliczonej właściwości odwrotności. czy to możliwe?

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

Mój ViewModel ma właściwości okresów, które są tablicą miesięcy, na przykład:

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

3
@Niko: To nie jest tak naprawdę powtórzone pytanie. OP pytania, do którego się odnosisz, już wiedział , że jest możliwe powiązanie z danymi negacji obserwowalnego, ale zastanawia się, dlaczego należy to nazywać funkcją. Ten OP pytania nie wiedział, jak to zrobić w pierwszej kolejności i oczywiście nie znalazł tego drugiego pytania. Cieszę się, że znalazłem tutaj to pytanie - głównie dzięki opisowemu tytułowi.
Oliver

Odpowiedzi:


281

Używając obserwowalnego w wyrażeniu, musisz uzyskać do niego dostęp jako funkcję, taką jak:

visible: !charted()


33
Może powinniśmy zrobić ukryte powiązanie :) Mamy włączone i wyłączone.
John Papa,

Czy dokumentacja się z tym nie zgadza, czy też całkowicie nie rozumiem tej strony: knockoutjs.com/documentation/css-binding.html
Devil's Advocate

Nieważne, myślę, że „isSevere” nie jest obserwowalną, ale zwykłą starą właściwością, stąd moje zamieszanie.
Devil's Advocate

3
Używając! Charted, otrzymujesz! [Funkcja]. [Funkcja] jest prawdziwa,! [Funkcja] staje się fałszem i zawsze będzie fałszywa, jeśli użyjesz tej składni. jsfiddle.net/datashaman/E58u2/3
datashaman

1
W rzeczywistości dodali hiddenwiążące w wersji 3.5.0
Grin

53

Zgadzam się z komentarzem Johna Papy, że powinno być wbudowane hiddenwiązanie. Dedykowane hiddenwiązanie ma dwie zalety :

  1. Prostsza składnia, tj. hidden: chartedzamiast visible: !charted().
  2. Mniej zasobów, ponieważ Knockout może chartedbezpośrednio obserwować to, co obserwowalne , zamiast tworzyć computedobserwację !charted().

hiddenJednak utworzenie wiązania jest dość proste, na przykład:

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

Możesz go używać tak samo jak wbudowanego visiblewiązania:

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

9
to nie zadziałało bez powrotureturn !ko.utils.unwrapObservable(valueAccessor());
Mehmet Ataş

Dzięki @ MehmetAtaş - poprawiłem hiddenwiązanie zgodnie z twoim komentarzem. (Swoją drogą, korzystałem z CoffeeScript w moim projekcie w momencie, gdy to pierwotnie publikowałem. Składnia CoffeeScript nie wskazuje na to, kiedy zwrot jest zamierzony.)
Dave

9

To trochę zagmatwane, ponieważ musisz to zrobić

visible:!showMe()

więc zrobiłem

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

mój model to

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

Sprawdź skrzypce http://jsfiddle.net/khanSharp/bgdbm/


4

Możesz użyć mojego powiązania przełącznika / wielkości liter , które obejmuje case.visiblei 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>

Możesz też mieć to jako

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

Właśnie zdałem sobie sprawę, że to stare pytanie, ale mam nadzieję, że może się to komuś przydać.
Michael Best

1

Aby powiązanie było świadome zmian we właściwości, skopiowałem widoczną procedurę obsługi powiązania i odwróciłem ją:

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 = "";
    }
};

0

Zastrzeżenie: to rozwiązanie służy wyłącznie do celów rozrywkowych.

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

Miałem ten sam problem, jak używać przeciwieństwa do obserwowalnych wartości logicznych. Znalazłem proste rozwiązanie:

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

};

Teraz w swoim HTML powinieneś to zrobić

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

Podczas uruchamiania programu widoczny jest tylko tekst „Text1”, ponieważ „false === false is TRUE”, a Text2 nie jest widoczny.

Powiedzmy, że mamy przycisk, który po kliknięciu wywołuje zdarzenie collectPlacesData. Teraz Text1 nie będzie widoczny, ponieważ „true === false to FALSE”, a tekst 2 będzie widoczny tylko.

Innym możliwym rozwiązaniem może być użycie obserwowalnych obliczeń, ale myślę, że jest to zbyt skomplikowane rozwiązanie tak prostego problemu.


-1

Można również użyć ukrytego w ten sposób:

 <div data-bind="hidden: isString">
                            <input type="text" class="form-control" data-bind="value: settingValue" />
                        </div>
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.