Apakah mungkin untuk data-bind terlihat oleh negasi ("!") Properti ViewModel boolean?

162

Saya ingin menggunakan properti di ViewModel saya untuk beralih ikon mana yang akan ditampilkan tanpa membuat properti yang dihitung secara terpisah dari invers. Apakah ini mungkin?

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

ViewModel saya memiliki periode properti yang merupakan array bulan, seperti ini:

var month = function() {
    this.charted = ko.observable(false);
};
agradl
sumber
3
@ Niko: Ini bukan pertanyaan duplikat. OP dari pertanyaan yang Anda rujuk sudah tahu bahwa mungkin untuk mengikat data negasi yang dapat diamati, tetapi bertanya-tanya mengapa hal itu perlu disebut seperti fungsi. OP pertanyaan ini di sini tidak tahu bagaimana melakukannya sejak awal dan jelas tidak menemukan pertanyaan lain itu. Saya senang saya menemukan pertanyaan ini di sini - yang sebagian besar berkat judul deskriptifnya.
Oliver

Jawaban:

281

Saat menggunakan observable dalam ekspresi Anda perlu mengaksesnya sebagai fungsi seperti:

visible: !charted()

RP Niemeyer
sumber
33
Mungkin kita harus membuat ikatan tersembunyi :) Kami telah mengaktifkan dan menonaktifkan.
John Papa
Apakah dokumentasi tidak setuju dengan ini, atau saya benar-benar salah paham halaman ini: knockoutjs.com/documentation/css-binding.html
Pengacara Setan
Tidak pernah, saya kira "isSevere" bukan properti tua yang bisa diamati, jadi kebingungan saya.
Pengacara Setan
3
Saat menggunakan! Charted, Anda mendapatkan! [Fungsi]. [Fungsi] benar,! [Fungsi] menjadi salah dan akan selalu salah jika Anda menggunakan sintaks itu. jsfiddle.net/datashaman/E58u2/3
datashaman
1
Mereka benar-benar menambahkan hiddenbinding di v3.5.0
Grin
53

Saya setuju dengan komentar John Papa bahwa harus ada hiddenikatan bawaan. Ada dua manfaat dari hiddenpengikatan khusus :

  1. Sintaks yang lebih sederhana, yaitu. hidden: chartedbukannya visible: !charted().
  2. Lebih sedikit sumber daya, karena Knockout dapat mengamati yang dapat diamati chartedsecara langsung, daripada membuat a computeduntuk diamati !charted().

Cukup sederhana untuk membuat hiddenpenjilidan, seperti ini:

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

Anda dapat menggunakannya seperti visiblepenjilidan bawaan:

<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
sumber
9
ini tidak berhasil untuk saya tanpa kembalireturn !ko.utils.unwrapObservable(valueAccessor());
Mehmet Ataş
Terima kasih @ MehmetAtaş - Saya mengoreksi hiddenpengikatan per komentar Anda. (BTW, saya menggunakan CoffeeScript dalam proyek saya pada saat saya memposting ini awalnya. Sintaks CoffeeScript tidak membuatnya jelas ketika pengembalian disengaja.)
Dave
9

Agak membingungkan, seperti yang harus Anda lakukan

visible:!showMe()

jadi saya lakukan

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

model saya

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

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

Jhankar Mahbub
sumber
4

Anda dapat menggunakan sakelar / penjilid kasus saya , yang mencakup case.visibledan 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>

Anda juga bisa memilikinya

        <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
sumber
Saya baru menyadari bahwa ini adalah pertanyaan lama tetapi berharap ini bisa bermanfaat bagi seseorang.
Michael Best
1

Untuk membuat ikatan menyadari perubahan pada properti, saya menyalin handler pengikat yang terlihat dan membaliknya:

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

Penafian: solusi ini hanya untuk tujuan hiburan.

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

Saya memiliki masalah yang sama tentang bagaimana menggunakan kebalikan dari boolean yang dapat diamati. Saya telah menemukan solusi mudah:

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

};

Sekarang pada HTML Anda, Anda harus melakukan ini

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

Ketika program dimulai hanya "Text1" yang terlihat karena "false === false is TRUE" dan Text2 tidak terlihat.

Katakanlah kita memiliki tombol yang memanggil collectPlacesData pada acara klik. Sekarang Text1 tidak akan terlihat karena "true === false is FALSE" dan Text 2 hanya dapat terlihat.

Solusi lain yang mungkin bisa menggunakan komputasi teramati tetapi, saya pikir adalah solusi yang terlalu rumit untuk masalah yang sangat sederhana.

ccastanedag
sumber
-1

Juga dapat menggunakan disembunyikan seperti ini:

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