简体   繁体   中英

Need to get custom checkbox columns to work in KoGrid

I am trying to display a KoGrid that contains some basic show data. The grid has an embedded checkbox that tells whether or not the show is a movie, and another embedded checkbox that tells whether or not the show is a cartoon. The Javascript for this grid, in a file called testgrid.js, is provided below:

var theList = [
               { isMovie: false, isCartoon: true, name: "Johnny Quest" },
               { isMovie: true, isCartoon: true, name: "Heavy Metal" },
               { isMovie: true, isCartoon: false, name: "Star Wars Rogue One" },
               { isMovie: false, isCartoon: false, name: "The Invaders" },
               { isMovie: true, isCartoon: false, name: "Star Trek: The Voyage Home" },
               { isMovie: false, isCartoon: true, name: "Space Ghost" },
               { isMovie: false, isCartoon: false, name: "Star Trek Classic" },
               { isMovie: false, isCartoon: false, name: "Lost In Space" },
               { isMovie: false, isCartoon: true, name: "Bugs Bunny/Road Runner Hour" },
           ];

var showTitles = [
              {field: 'isMovie',displayName: 'Movie',width: '10%',cellTemplate: "<input type='checkbox' class='grpcheck' data-bind='checked: theData.isMovie' />"},
              {field: 'isCartoon',displayName: 'Cartoon',width: '10%',cellTemplate: "<input type='checkbox' class='grpcheck' data-bind='checked: theData.isCartoon' />"},
              {field: 'name',displayName: 'Show Name',width: '78%'},
          ];

var TestModel = function() {
  var self = this;

  self.theData = ko.observableArray(theList);
  self.selectShow = ko.observableArray([]);

  self.instantiateSelf = function() {
       ko.applyBindings(theModel);
   }

  self.listOptions = {
      afterSelectionChange: function () { alert("Show Selected: "+selectShow()[0]); },
      data: self.theData,
      selectedItems: self.selectShow,
      displaySelectionCheckbox: false,
      multiSelect: false,
      columnDefs: showTitles
  }
}
var theModel = new TestModel();

The HTML that I am using is provided below:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
  <head>
    <meta content="text/html; charset=ISO-8859-1" http-equiv="content-type">
   <title>Grid Test</title>
   <link href="lstyles.css" rel="stylesheet" type="text/css">
   <link href="KoGrid.css" rel="stylesheet" type="text/css">
   <script src="knockout-3.4.2.js" type="text/javascript"></script>
   <script src="jquery-3.2.0.js" type="text/javascript"></script>
   <script src="koGrid-2.1.1.js" type="text/javascript"></script>
   <script src="jquery-ui.min.js" type="text/javascript"></script>
   <script type="text/javascript">
      $(document).ready(function() {
         jQuery.support.cors = true;
         theModel.instantiateSelf();
      });
   </script>
 </head>
<body>
  <div id="body">
     <div id="data">
        <div id="display">
          <div id="lstStyle" data-bind="koGrid: listOptions"></div>
        </div>
        <div id="footer">
        </div>
    </div>
  </div>
 <script>
 </script>
</div>  
   <script src="testgrid.js" type="text/javascript"></script>
</body>
</html>

The grid does not display. What displays looks like a part of a grid display but nothing appears.

I did some troubleshooting. I have discovered that the problem is n the "data-bind" statements in the cellTemplate definition that I provide for the checkboxes in the showTitles object in testgrid.js. If I remove these statements, the grid displays, but I cannot check or uncheck the checkboxes, and I cannot get the state of the checkboxes.

Is there some way to get these checkboxes to work properly in a kogrid? How do I get one to bind to the boolean that they are assigned to?

Someone please advise.

For completeness, below is the stylesheet, called lstyles.css:

#lstStyle {
   border: 4px solid #0055AA;
   width: 100%; 
   height: 400px;
   float: left;
}

.grpcheck {
   position:relative;
   top: 10px;
   left: 10px;
}

Checkbox problems, continued

Thanks to donMateo, I made some changes that allowed me to display the grid. Once I was able to get it displayed, I began clicking on the checkboxes to see if they would work. They do not -- or, rather, they do not work the way I was hoping they would.

Problem 1: The first thing I noticed was that the checkbox states do not reflect the data they are bound to. Regardless of the value of isMovie and isCartoon, the checkboxes for each show appear unchecked. For example: Johnny Quest has isCartoon set to "true". The list shows that box as unchecked. Star Wars Rogue One has isMovie set to true. Its isMovie box is unchecked. Figure 1 shows what I am seeing.

NOTE: The image embedding on this site is not working. Even linking the images seems to be broken. I am providing straight HTTP links to my site hoping they will be sufficient to illustrate.

I changed my selection code so that it calls a function that displays an alert box showing the values of the show name, the isMovie value, and the isCartoon value. Selecting Johnny Quest, I see that the isMovie and isCartoon values are correct. So my first problem is: why aren't the checkboxes reflecting the values of their data?

Problem 2: Another problem I found was that when I click on a checkbox, it doesn't appear to retain the change I make. Figure 2 shows what happens when I click on Johnny Quest's isMovie checkbox. Note that the checkbox is checked, but the alert box still shows the isMovie value as false. Note please that the alert is shown after the checkbox changes state.

When I click on the Alert Box's "OK" button, note in Figure 3 how the checkbox goes back to an "unchecked" state. In fact, the only reason we see the checked box in Figure 2 is because of the delay caused by the alert box! I know this because as an experiment I temporarily removed the alert box, refreshed the browser, and clicked on the Movie checkbox for Johnny Quest. There was a brief indication of the checkbox being pressed, then the checkbox went back to being unchecked. So my second problem is: why doesn't the checkbox display the appropriate change when checked or unchecked?

Problem 3: The third and most disturbing thing I discovered is that there apparently is a change of state for the checkboxes -- but it doesn't show that change and (worse) it doesn't cause the changes one would expect. This can be demonstrated by causing a redisplay of the data in the grid, in my case by sorting the data.

When I start up the grid, the order in which the shows are displayed is the order shown in Figure 1 . If I click on the "Show Name" column, the sorted list looks like Figure 4 .

I then click on the Johnny Quest movie checkbox, get the alert box, click Ok. Figure 5 shows how the checkbox is still unchanged.

Now when I hit the "Show Name" column again, in order to do a reverse sort, note what happens to all the movie checkboxes in Figure 6 !

The same thing happens to the cartoon checkboxes. Click on one, click Ok on the alert box, then do a resort. All cartoon checkboxes will be checked.

To uncheck them, just click on a checked box, note the incorrect status shown in the alert box, click on Ok, then resort. All the boxes will be unchecked.

So my third problem is: what is the link between the checkboxes in the different rows? More important: how do I sever this link???

Summary: The KoGrod is really screwed up when it comes to putting controls in custom columns. For checkboxes: the data shown by a checkbox is not in sync with the individual data setting that is is supposedly bound to. Attempting to change the checked status of the chekbox does not work, and changing one checkbox cuses all of them to change -- but you do not see that change until you redraw the grid (using sorting or, possibly, scrolling or paging).

This leads to a question: is the cell template intended to just be a display template for a grid? Is the koGrid even capable of properly handling custom columns that contain controls? If so, how? Of not, then where can I find a grid control that can?

Someone please advise.

The current testgrid.js is provided below. No other files have been changed.

var theList = [
               { isMovie: false, isCartoon: true, name: "Johnny Quest" },
               { isMovie: true, isCartoon: true, name: "Heavy Metal" },
               { isMovie: true, isCartoon: false, name: "Star Wars Rogue One" },
               { isMovie: false, isCartoon: false, name: "The Invaders" },
               { isMovie: true, isCartoon: false, name: "Star Trek: The Voyage Home" },
               { isMovie: false, isCartoon: true, name: "Space Ghost" },
               { isMovie: false, isCartoon: false, name: "Star Trek Classic" },
               { isMovie: false, isCartoon: false, name: "Lost In Space" },
               { isMovie: false, isCartoon: true, name: "Bugs Bunny/Road Runner Hour" },
           ];

var showTitles = [
              {field: 'isMovie',displayName: 'Movie',width: '10%',cellTemplate: "<input type='checkbox' class='grpcheck' data-bind='checked: $data.isMovie' />"},
              {field: 'isCartoon',displayName: 'Cartoon',width: '10%',cellTemplate: "<input type='checkbox' class='grpcheck' data-bind='checked: $data.isCartoon' />"},
              {field: 'name',displayName: 'Show Name',width: '78%'},
          ];

var TestModel = function() {
   var self = this;

   self.theData = ko.observableArray(theList);
   self.selectShow = ko.observableArray([]);

   self.instantiateSelf = function() {
        ko.applyBindings(theModel);
   }

   self.displaySelect = function() {
      alert("Show Selected: "+self.selectShow()[0].name+" Movie: "+self.selectShow()[0].isMovie+" Cartoon: "+self.selectShow()[0].isCartoon);
   }

   self.listOptions = {
        afterSelectionChange: function () { self.displaySelect(); },
        data: self.theData,
        selectedItems: self.selectShow,
        displaySelectionCheckbox: false,
        multiSelect: false,
        columnDefs: showTitles
   }
}
var theModel = new TestModel();

here is your "repaired" code:

var theList = [
           { isMovie: false, isCartoon: true, name: "Johnny Quest" },
           { isMovie: true, isCartoon: true, name: "Heavy Metal" },
           { isMovie: true, isCartoon: false, name: "Star Wars Rogue One" },
           { isMovie: false, isCartoon: false, name: "The Invaders" },
           { isMovie: true, isCartoon: false, name: "Star Trek: The Voyage Home" },
           { isMovie: false, isCartoon: true, name: "Space Ghost" },
           { isMovie: false, isCartoon: false, name: "Star Trek Classic" },
           { isMovie: false, isCartoon: false, name: "Lost In Space" },
           { isMovie: false, isCartoon: true, name: "Bugs Bunny/Road Runner Hour" },
       ];
var showTitles = [
          {field: 'isMovie',displayName: 'Movie',width: '10%',cellTemplate: "<input type='checkbox' class='grpcheck' data-bind='checked: $data.isMovie' />"},
          {field: 'isCartoon',displayName: 'Cartoon',width: '10%',cellTemplate: "<input type='checkbox' class='grpcheck' data-bind='checked: $data.isCartoon' />"},
          {field: 'name',displayName: 'Show Name',width: '78%'},
      ];
var showTitles = [
          {field: 'isMovie',displayName: 'Movie',width: '10%',cellTemplate: "<input type='checkbox' class='grpcheck' data-bind='checked: $data.isMovie' />"},
          {field: 'isCartoon',displayName: 'Cartoon',width: '10%',cellTemplate: "<input type='checkbox' class='grpcheck' data-bind='checked: $data.isCartoon' />"},
          {field: 'name',displayName: 'Show Name',width: '78%'},
      ];
var TestModel = function() {
var self = this;

self.theData = ko.observableArray(theList);
self.selectShow = ko.observableArray([]);

self.instantiateSelf = function() {
   ko.applyBindings(theModel);
}

self.listOptions = {
  afterSelectionChange: function () { alert("Show Selected: "+self.selectShow()[0].name); },
  data: self.theData,
  selectedItems: self.selectShow,
  displaySelectionCheckbox: false,
  multiSelect: false,
  columnDefs: showTitles
}
}

The problem was "theData" which was undefined property of record. Had to change it to $data. And in select handler add self. in alert.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM