2012-02-10 14 views
6

Ho un gruppo di caselleCome implementare dipendenze casella di controllo knockoutjs

  • casella A
  • casella B
  • casella C

generata con l'associazione dati foreach:

<input type="checkbox" data-bind="value: id, checked: $root.chkboxSelected" /> 

Quali prendono il loro stato controllato da un array osservabile. Quindi controllando una casella si aggiungerà il valore corrispondente all'array, knockoutjs standard che funziona bene. Poi ho voluto aggiungere una semplice regola:

se C è selezionato, quindi anche A e B devono essere controllati.

Qual è il modo più pulito per aggiungere questo tipo di logica in knockoutjs? Ho provato con uno scrivibile calcolabile osservabile:

var viewModel = { 
     foo: observableArray(), 
     .. 
    }; 

viewModel.chkboxSelected = ko.computed({ 
     read: function() { 
     return this.foo(); 
     }, 
     write: function(value){ 
      //add it if not added already 
     if($.inArray(value, this.foo()) < 0) { 
      this.foo.push(value); 
     } 

      // if C is present then A,B must be as well   
     if($.inArray("C", this.foo()) >= 0) { 
      if($.inArray("B", this.foo()) < 0) { 
      this.foo().push("B"); 
      } 

      if($.inArray("A", this.foo()) < 0) { 
       this.foo().push("A"); 
      } 

     } 
     }, 
     owner: viewModel 
    }); 

Mettere un punto di interruzione sulla lettura e funzioni di scrittura: leggo viene chiamato e la pagina viene caricata bene. Tuttavia, quando ho quindi fare clic su qualsiasi casella di controllo ottengo il seguente errore (il punto di interruzione di scrittura non viene colpito):

knockout-2.0.0.debug.js:2297 

Uncaught TypeError: Object function dependentObservable() { 
     if (arguments.length > 0) { 
      if (typeof options["write"] === "function") { 
       // Writing a value 
       var valueForThis = options["owner"] || evaluatorFunctionTarget; // If undefined, it will default to "window" by convention. This might change in the future. 
       options["write"].apply(valueForThis, arguments); 
      } else { 
       throw "Cannot write a value to a dependentObservable unless you specify a 'write' option. If you wish to read the current value, don't pass any parameters."; 
      } 
     } else { 
      // Reading the value 
      if (!_hasBeenEvaluated) 
       evaluateImmediate(); 
      ko.dependencyDetection.registerDependency(dependentObservable); 
      return _latestValue; 
     } 
    } has no method 'push' 

risposta

9

Quando il checked legame è tenuto contro una matrice, quindi ha bisogno di essere in grado di eseguire operazioni di matrice contro esso. Quindi, utilizzando un osservabile calcolato scrivibile in quel caso causerà un problema.

Tuttavia, è possibile scegliere di utilizzare un abbonamento manuale per mantenere i tuoi articoli sincronizzati.

Qui è una vista modello di esempio:

var ViewModel = function() { 
    var self = this; 
    this.items = ko.observableArray([ 
     { id: "A" }, 
     { id: "B" }, 
     { id: "C" }, 
     { id: "D" } 
     ]); 
    this.checked = ko.observableArray(); 
    this.checked.subscribe(function(newValue) { 
     if (self.checked.indexOf("C") > -1) { 
      if (self.checked.indexOf("A") < 0) { 
       self.checked.push("A"); 
      } 
      if (self.checked.indexOf("B") < 0) { 
       self.checked.push("B"); 
      } 
     } 
    }); 

    this.shouldBeDisabled = function(item) { 
     return (item.id === "B" || item.id ==="A") && self.checked.indexOf("C") > -1;  
    }; 
}; 

Qui è la vista:

<ul data-bind="foreach: items"> 
    <li> 
     <span data-bind="text: id"></span> 
     <input type="checkbox" data-bind="attr: { value: id }, checked: $root.checked, disable: $root.shouldBeDisabled($data)" /> 
    </li> 
</ul> 

ho usato attr: { value: id } anziché value per evitare il gestore di eventi che verrebbe fissato dal valore vincolante, poiché il valore vincolante è progettato per gestire le modifiche a un campo. In questo caso, vogliamo solo impostare l'attributo value.

Esempio: http://jsfiddle.net/rniemeyer/tQJMg/

+0

Funziona perfettamente, grazie! (il violino dà un 404 però) – dgorissen

+0

Dovrebbe anche aggiungere a questo che per ottenere un tag

+1

Perché viene chiamato 'shouldBeDisabled' per ogni elemento nell'array degli articoli? Capisco perché viene chiamato quando cambia "self.checked", ma perché esegue iterate sull'intero array 'items'? – arb

Problemi correlati