เป็นไปได้ไหมที่ data-bind จะปรากฏต่อการปฏิเสธ (“!”) ของคุณสมบัติ ViewModel บูลีน?


162

ฉันต้องการใช้พร็อพเพอร์ตี้ใน ViewModel ของฉันเพื่อสลับไอคอนที่จะแสดงโดยไม่ต้องสร้างคุณสมบัติที่คำนวณได้แยกจากอินเวอร์ส เป็นไปได้ไหม

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

My ViewModel มีระยะเวลาคุณสมบัติซึ่งเป็นอาร์เรย์ของเดือนเช่นนี้

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

3
@Niko: มันไม่ใช่คำถามที่ซ้ำกันจริงๆ OP ของคำถามที่คุณอ้างถึงรู้อยู่แล้วว่าเป็นไปได้ที่ data ผูกการปฏิเสธของสิ่งที่สังเกตได้ แต่สงสัยว่าทำไมมันจำเป็นต้องถูกเรียกเหมือนฟังก์ชั่น OP ของคำถามนี้ที่นี่ไม่รู้ว่าจะทำอย่างไรในตอนแรกและเห็นได้ชัดว่าไม่พบคำถามอื่น ฉันดีใจที่ฉันพบคำถามนี้ที่นี่ - ซึ่งส่วนใหญ่ต้องขอบคุณชื่อบรรยาย
Oliver

คำตอบ:


281

เมื่อใช้สิ่งที่สังเกตได้ในนิพจน์คุณต้องเข้าถึงมันเป็นฟังก์ชั่นเช่น:

visible: !charted()


33
บางทีเราควรผูกมัดที่ซ่อนไว้ :) เราได้เปิดใช้งานและปิดใช้งาน
John Papa

เอกสารไม่เห็นด้วยกับสิ่งนี้หรือฉันเข้าใจผิดหน้านี้อย่างสมบูรณ์: knockoutjs.com/documentation/css-binding.html
Devil's Advocate

ไม่เป็นไรฉันเดาว่า "isSevere" ไม่ใช่สิ่งที่สามารถสังเกตเห็นได้ แต่เป็นสมบัติเก่าแก่ธรรมดาดังนั้นความสับสนของฉัน
ผู้สนับสนุนปีศาจเมื่อ

3
เมื่อใช้! charted คุณจะได้รับ! [Function] [ฟังก์ชั่น] เป็นเรื่องจริง! [ฟังก์ชั่น] จะกลายเป็นเท็จและจะเป็นเท็จเสมอหากคุณใช้ไวยากรณ์นั้น jsfiddle.net/datashaman/E58u2/3
datashaman

1
พวกเขาเพิ่มการhiddenรวมในv3.5.0 จริง
Grin

53

ฉันเห็นด้วยกับความคิดเห็นของจอห์นปาปาว่าควรมีการhiddenผูกมัดในตัว มีประโยชน์สองประการสำหรับการhiddenโยงเฉพาะ:

  1. ไวยากรณ์ที่เรียบง่ายคือ แทนhidden: chartedvisible: !charted()
  2. ทรัพยากรน้อยตั้งแต่ที่น่าพิศวงสามารถสังเกตสังเกตchartedโดยตรงมากกว่าการสร้างที่จะสังเกตเห็นcomputed!charted()

มันง่ายพอที่จะสร้างความhiddenผูกพันได้เช่นนี้

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

คุณสามารถใช้งานได้เช่นเดียวกับการvisibleรวมในตัว:

<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
สิ่งนี้ไม่ได้ผลสำหรับฉันโดยไม่มีการกลับมาreturn !ko.utils.unwrapObservable(valueAccessor());
เมห์เม็ตอาตา

ขอบคุณ @ MehmetAtaş - ฉันแก้ไขhiddenข้อผูกพันต่อความคิดเห็นของคุณ (BTW ฉันใช้ CoffeeScript ในโครงการของฉันในขณะที่โพสต์สิ่งนี้ไว้เดิมไวยากรณ์ของ CoffeeScript ไม่ชัดเจนเมื่อมีการส่งคืนโดยเจตนา)
เดฟ

9

มันสับสนเล็กน้อยตามที่คุณต้องทำ

visible:!showMe()

ดังนั้นฉันทำ

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

แบบจำลองของฉันคือ

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

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


4

คุณสามารถใช้ของฉันสวิตช์ / กรณีที่มีผลผูกพันซึ่งรวมถึงและcase.visiblecasenot.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>

คุณสามารถมีมันเป็น

        <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

1

ในการทำให้การเชื่อมโยงตระหนักถึงการเปลี่ยนแปลงคุณสมบัติฉันได้คัดลอกตัวจัดการการเชื่อมที่มองเห็นได้และกลับด้าน:

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

คำเตือน: โซลูชั่นนี้มีวัตถุประสงค์เพื่อความบันเทิงเท่านั้น

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

ฉันมีปัญหาเดียวกันเกี่ยวกับวิธีใช้สิ่งที่ตรงกันข้ามกับบูลีนที่สังเกตได้ ฉันได้พบวิธีง่ายๆแล้ว:

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

};

ตอนนี้บน HTML ของคุณคุณควรทำเช่นนี้

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

เมื่อโปรแกรมเริ่มทำงานเฉพาะ "Text1" จะปรากฏให้เห็นเพราะ "false === false คือ TRUE" และมองไม่เห็น Text2

ช่วยบอกว่าเรามีปุ่มที่เรียกใช้ gatherPacesData เมื่อคลิกเหตุการณ์ ตอนนี้ Text1 จะไม่ปรากฏเนื่องจาก "true === false เป็น FALSE" และข้อความ 2 จะมองเห็นได้เท่านั้น

อีกวิธีที่เป็นไปได้อาจใช้การคำนวณที่สังเกตได้ แต่ฉันคิดว่าเป็นวิธีการแก้ปัญหาที่ซับซ้อนสำหรับปัญหาง่าย ๆ


-1

นอกจากนี้ยังสามารถใช้ซ่อนอยู่เช่นนี้

 <div data-bind="hidden: isString">
                            <input type="text" class="form-control" data-bind="value: settingValue" />
                        </div>
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.