È possibile associare i dati alla negazione ("!") Di una proprietà ViewModel booleana?


162

Vorrei utilizzare una proprietà sul mio ViewModel per attivare / disattivare quale icona visualizzare senza creare una proprietà calcolata separata dell'inverso. È possibile?

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

Il mio ViewModel ha un periodo di proprietà che è un array del mese, come questo:

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

3
@Niko: Non è davvero una domanda duplicata. L'OP della domanda a cui fai riferimento sapeva già che è possibile legare i dati alla negazione di un osservabile, ma si chiede perché debba essere chiamato come una funzione. L'OP di questa domanda qui non sapeva come farlo in primo luogo e ovviamente non trovava quell'altra domanda. Sono contento di aver trovato questa domanda qui, principalmente grazie al suo titolo descrittivo.
Oliver,

Risposte:


281

Quando si utilizza un osservabile in un'espressione è necessario accedervi come una funzione come:

visible: !charted()


33
Forse dovremmo creare un'associazione nascosta :) Abbiamo abilitato e disabilitato.
John Papa,

La documentazione non è d'accordo con questo, o sto fraintendendo completamente questa pagina: knockoutjs.com/documentation/css-binding.html
Devil's Advocate,

Non importa, suppongo che "isSevere" non sia una proprietà osservabile ma una vecchia proprietà, quindi la mia confusione.
Devil's Advocate,

3
Quando si utilizza! Grafici, si ottiene! [Funzione]. [La funzione] è vera,! [La funzione] diventa falsa e sarà sempre falsa se si utilizza quella sintassi. jsfiddle.net/datashaman/E58u2/3
datashaman

1
Hanno effettivamente aggiunto l' hiddenassociazione in v3.5.0
Grin

53

Concordo con il commento di John Papa sul fatto che dovrebbe esserci un'associazione integrata hidden. Esistono due vantaggi per un'associazione dedicata hidden:

  1. Sintassi più semplice, ad es. hidden: chartedinvece di visible: !charted().
  2. Meno risorse, poiché Knockout può osservare charteddirettamente l'osservabile , piuttosto che creare un computedda osservare !charted().

È abbastanza semplice creare un'associazione hidden, in questo modo:

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

Puoi usarlo proprio come il visiblebinding incorporato :

<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
questo non ha funzionato per me senza ritornoreturn !ko.utils.unwrapObservable(valueAccessor());
Mehmet Ataş

Grazie @ MehmetAtaş - Ho corretto l' hiddenassociazione per il tuo commento. (A proposito, stavo usando CoffeeScript nel mio progetto nel momento in cui l'ho pubblicato originariamente. La sintassi di CoffeeScript non lo rende ovvio quando un ritorno è intenzionale.)
Dave,

9

È un po 'confuso, come devi fare

visible:!showMe()

così ho fatto

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

il mio modello è

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

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


4

Puoi usare il mio switch / case binding, che include case.visiblee 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>

Potresti anche averlo come

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

Ho appena capito che questa è una vecchia domanda, ma spero che possa essere utile a qualcuno.
Michael Best,

1

Al fine di rendere l'associazione consapevole delle modifiche apportate alla proprietà, ho copiato il gestore dell'associazione visibile e l'ho invertito:

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

Disclaimer: questa soluzione è solo a scopo di intrattenimento.

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

Stavo avendo lo stesso problema su come usare l'opposto di un osservabile booleano. Ho trovato una soluzione semplice:

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

};

Ora sul tuo HTML dovresti farlo

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

All'avvio del programma è visibile solo "Text1" perché "false === false è TRUE" e Text2 non è visibile.

Diciamo che abbiamo un pulsante che richiama l'evento gatherPlacesData on click. Ora Text1 non sarà visibile perché "true === false è FALSE" e Text 2 sarà visibile solo.

Un'altra possibile soluzione potrebbe essere l'utilizzo di calcolabili osservabili ma, penso che sia una soluzione complicata per un problema così semplice.


-1

Inoltre puoi usare nascosto in questo modo:

 <div data-bind="hidden: isString">
                            <input type="text" class="form-control" data-bind="value: settingValue" />
                        </div>
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.