0

I have a set of Checkboxes and a Select All checkbox implemented in the following way using Knockout. I need the "Select All" checkbox to be checked by default on page load.

$(document).ready(function(){
    viewModel=new model(ko,$);
    ko.applyBindings(viewModel);
});

function model(ko,$){
     var jsonResponse= $.parseJSON(response);

     this.factors=ko.observableArray(jsonResponse["factors"]);
    this.selectedFactors=ko.observableArray();

     this.selectAll = ko.dependentObservable({
        read: function() {
            return this.selectedFactors().length === this.factors().length;
        },
        write: function(newValue) {
            this.selectedFactors(this.selectedFactors().length === this.factors().length ? [] : this.factors().slice(0));
        },
        owner: this 
    });

}

HTML:

<table>
    <tr>
        <td><input type="checkbox" id="selectAll" data-bind="checked: selectAll" />Select All</td>
   </tr>
</table>
<table data-bind="foreach: factorsSplitJsonArray">
    <tr data-bind="foreach: $data">
        <td>
            <!-- ko if: $data.hasOwnProperty("factorCode") -->
            <input type="checkbox" class="jqFactors" id="jqFactors" data-bind="checkedValue: $data, checked: $root.selectedFactors" /> 
            <span data-bind="text: factorDescription"></span> 
            <!-- /ko -->
        </td>
    </tr>
</table>

When I select or deselect any checkbox or the SelectAll checkbox the observableArray ie selectedFactors get changed. Now I need the "Select All" checkbox to be selected by default on page load and the selectedFactors should also have all the selected factors in it.

I am new to Knockout and unable to find out how to implement this using Knockout. What if we somehow call the function selectAll explicitly, will it do the job? How do I call a ko.dependentObservable function. Can some one please help me.

Arunabh
  • 167
  • 1
  • 7
  • 18

1 Answers1

0

Here's a somewhat different approach to get to the same thing:

var jsonData = {
  allFactors: [
    { code: "A1", desc: "Alpha one" },
    { code: "A2", desc: "Alpha two" },
    { code: "B1", desc: "Beta one" },
  ],
  
  // Simulate that no selection was ever made
  selectedFactors: null // or "undefined"
  
  // Unomment this version instead if you want to simulate loading
  // data that was previously selected:
  //selectedFactors: ["A1", "B1"]
};

function ViewModel(data){
  var self = this;
  
  self.factors = ko.observableArray(data.allFactors);
    
  function getAllCodes() {
    return data.allFactors.map(function(f) { return f.code; });
  }
  
  self.selectedFactors = ko.observableArray(
    data.selectedFactors || getAllCodes()
  );
  
  self.selectAll = ko.computed({
    read: function() {
      return self.selectedFactors().length === self.factors().length;
    },
    write: function(newVal) {
      if (newVal === self.selectAll()) return;     
      if (!!newVal) self.selectedFactors(getAllCodes());
      if (!newVal) self.selectedFactors([]);
    }
  });
}

ko.applyBindings(new ViewModel(jsonData));
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>

<label><input type="checkbox" data-bind="checked: selectAll"> Select All</label>
<hr>
<ul data-bind="foreach: factors">
  <li>
    <label>
      <input type="checkbox" data-bind="checkedValue: code, checked: $root.selectedFactors">
      <span data-bind="text: desc"></span>
    </label>
  </li>
</ul>
Jeroen
  • 60,696
  • 40
  • 206
  • 339
  • Thanks for your help but I havent been able to really understand this and implement. Does it keep the "Select All" checkbox checked on page load? – Arunabh Nov 25 '16 at 09:05
  • Whether "Select All" should be selected on page load probably depends on whatever data is being loaded, assuming your page can keep some state server side. If the user previously selected everything, then `jsonData.selectedFactors` will contain all codes and the "Select All" box will also become checked. – Jeroen Nov 25 '16 at 09:22
  • What I understand from your comment is that assign all of the factors from the JSON to "selectedFactors" so that it will check "Select All" on page load. I had already tried it and it does check "select all" and all other factors but its behaviour is not exactly correct. If I uncheck a checkbox, it still keeps Select All checked ideally it should uncheck "Select All" and clicking it again should select the earlier unchecked one. – Arunabh Nov 25 '16 at 10:20
  • Have you tried *my* example? It *does* have the behavior you expect. If you want help with the issue specific to your scenario try putting it as a [mcve] in the question, otherwise it's hard for us to tell what's wrong. – Jeroen Nov 25 '16 at 10:35
  • http://fiddle.jshell.net/likhi1/qFE2C/ This is the Js fiddle from where I tried implementing the "Select All" checkbox. Unfortunately, the example you have given didnt work for me. Could you please suggest a solution modifying the code given in the js fiddle. – Arunabh Nov 28 '16 at 06:57
  • I don't think I understand your question, because fixing your fiddle to select all on load is [trivial](http://fiddle.jshell.net/n68jxrLv/), but probably not what you want? PS. Try to update and edit your question itself to clarify it, and make sure the code is in there too. If you edit substantially it'll get bumped and others can view it too. – Jeroen Nov 28 '16 at 07:15
  • The solution which you have given terming "trivial" is what I want and I had tried doing the same in my original code earlier but it didnt work for some reason. I'll try editing the question again. Thanks. – Arunabh Nov 28 '16 at 07:33