Чи можна прив'язувати дані, видимі до заперечення ("!") Булевого властивості 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>

Мій ViewModel має періоди властивостей, що є масивом місяця, наприклад:

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

3
@Niko: Це насправді не повторне запитання. ОП питання, на яке ви посилаєтесь, уже знав, що можливо пов'язати дані заперечення спостережуваного, але цікавиться, чому це потрібно викликати як функцію. Оперативна програма цього питання в першу чергу не знала, як це зробити, і, очевидно, не знайшла іншого питання. Я радий, що тут я знайшов це питання - що, в основному, завдяки його описовій назві.
Олівер

Відповіді:


281

Використовуючи спостережуваний в виразі, вам потрібно отримати доступ до нього як до функції:

visible: !charted()


33
Можливо, нам слід зробити приховану прив'язку :) У нас є включення та відключення.
Джон Папа

Чи не згодна документація з цим, чи я цілком не розумію цю сторінку: knockoutjs.com/documentation/css-binding.html
Адвокат Чорта

Я не маю на увазі, я вважаю, що "isSevere" - це не спостережувана, а звичайна стара властивість, тому моя плутанина.
Адвокат диявола

3
Використовуючи! Charted, ви отримуєте! [Функцію]. [Функція] є правдоподібною,! [Функція] стає хибною і завжди буде помилковою, якщо використовувати цей синтаксис. jsfiddle.net/datashaman/E58u2/3
datashaman

1
Вони фактично додали hiddenприв’язку в v3.5.0
Grin

53

Я погоджуюся з коментарем Джона Папи про те, що має бути вбудована hiddenприв'язка. До цільового hiddenзв’язку є дві переваги :

  1. Простіший синтаксис, тобто. hidden: chartedзамість visible: !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);    

Реєстрація у скрипці http://jsfiddle.net/khanSharp/bgdbm/


4

Ви можете використовувати мій перемикач / прив'язку корпусу , що включає case.visibleі 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>

Ви також можете мати його як

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

Я просто зрозумів, що це старе питання, але сподіваюся, що це може бути корисним для когось.
Майкл Бест

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 - ІСТИНА", а Text2 - не видно.

Скажімо, у нас є кнопка, яка викликає подію збиранняPlacesData при натисканні. Тепер Text1 не буде видно, тому що "true === false FALSE", а Text 2 - видимий.

Іншим можливим рішенням може бути використання обчислених спостережуваних, але, я думаю, це надскладне рішення для такої простої проблеми.


-1

Також можна використовувати приховане так:

 <div data-bind="hidden: isString">
                            <input type="text" class="form-control" data-bind="value: settingValue" />
                        </div>
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.