jai ganesh
jai ganesh

Reputation: 97

Manually check or uncheck in knockout

I am trying to manually check or uncheck a checkbox based on the result of the sub-function result. However it is not working. Below is the sample code. I have customer table which I am displaying using knockout foreach loop. Inside I need a checkbox for 'Approve' field. When the Approve field is checked I need to call a function 'CheckApprove'. Inside this function I first check if the checkbox is checked or unchecked. If it is checked I need to call a subfunction and then based on the result of the function I need to manually check the checkbox. I am trying the same thing for uncheck also. I am not able to manually check or uncheck . Please help

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm5.aspx.cs" Inherits="WebApplication2.WebForm5" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
      <link rel="stylesheet" href="Content/bootstrap.css" /> 
    <script type="text/javascript" src="Scripts/jquery-3.1.1.js"></script>
    <script type="text/javascript" src="Scripts/knockout-3.4.2.js"></script>
  <script type="text/javascript" src="Scripts/synonym.js"></script>
</head>
<body>
    <form id="form1" runat="server">
    <div class="container">
        <table>
          <thead>
            <tr>
              <th>Id</th>
              <th>Name</th>
              <th>Approve</th>
            </tr>
          </thead>
          <tbody  data-bind="foreach:Customers">
            <tr>
              <td><span data-bind="text : CustomerId"></span> </td>
              <td><span data-bind="text : CustomerName"></span></td>
              <td><input type="checkbox" data-bind="checked: Approve, event: { click: $root.CheckApprove.bind(Approve) }" /></span></td>
            </tr>
          </tbody>
        </table>
    </div>
    </form>
</body>
</html>

    function customerViewModel() {
      self = this;
      self.Customers = ko.observableArray([]);


      function addCustomer(customerId, customerName, approve) {
        return {
          CustomerId: ko.observable(customerId),
          CustomerName: ko.observable(customerName),
          Approve: ko.observable(approve)
        }
      }


      self.Customers.push(new addCustomer(1, 'Cust1', false));
      self.Customers.push(new addCustomer(2, 'Cust2', false));
      self.Customers.push(new addCustomer(3, 'Cust3', false));


      self.CheckApprove = function (data) {
        var result = data.Approve();
        var id = data.CustomerId()

        if (result == true) {
          var customerCheck = Method1() // result of process1
          if (customerCheck == true) {
            for (var i = 0; i < self.Customers().length; i++) {
              var innerid = self.Customers()[i].CustomerId();
              if (id === innerid) {
                self.Customers()[i].Approve('true');
                return;
              }
            }
          }      
        }

        if (result == false) {
          var customerCheck = Method2() // result of process1
          if (customerCheck == false)
          for (var i = 0; i < self.Customers().length; i++) {
            var innerid = self.Customers()[i].CustomerId();
            if (id === innerid) {
              self.Customers()[i].Approve('false');
              return;
            }
          }
        }
      }

      function Method1() {
        return true;
      }

      function Method2() {
        return false;
      }
    }


    $(document).ready(function () {
      var cs = new customerViewModel();
      ko.applyBindings(cs);

    });

Upvotes: 0

Views: 849

Answers (1)

Ja9ad335h
Ja9ad335h

Reputation: 5075

when you use click binding along with other events (like checked), click function should return true to propagate the next event.

below is the working example. (1 is not checkable, 3 is not un-checkable and 2 works both ways)

function customerViewModel() {
  self = this;
  self.Customers = ko.observableArray([]);

  function addCustomer(customerId, customerName, approve) {
    return {
      CustomerId: ko.observable(customerId),
      CustomerName: ko.observable(customerName),
      Approve: ko.observable(approve)
    }
  }

  self.Customers.push(new addCustomer(1, 'Cust1', false));
  self.Customers.push(new addCustomer(2, 'Cust2', false));
  self.Customers.push(new addCustomer(3, 'Cust3', true));

  self.CheckApprove = function(data) {
    
    var result = data.Approve();
    var id = data.CustomerId()
    var customerCheck = null;

    if (result == true) {      
      customerCheck = Method1(id) // result of process1
    }

    if (result == false) {
      customerCheck = Method2(id) // result of process1
    }
    
    data.Approve(customerCheck); // assuminng "customerCheck" be true/false
    return true; // needed to propagate the next event (which is checked)
  }

  function Method1(id) { // check eligibility
    return id == 2;
  }

  function Method2(id) { // uncheck eligibility
    return id == 3;
  }
}


$(document).ready(function() {
  var cs = new customerViewModel();
  ko.applyBindings(cs);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<form id="form1" runat="server" style="display: inline-block; margin: 100px 20px;">
  <div class="container">
    <table>
      <thead>
        <tr>
          <th>Id</th>
          <th>Name</th>
          <th>Approve</th>
        </tr>
      </thead>
      <tbody data-bind="foreach:Customers">
        <tr>
          <td><span data-bind="text : CustomerId"></span></td>
          <td><span data-bind="text : CustomerName"></span></td>
          <td><input type="checkbox" data-bind="checked: Approve, click: $root.CheckApprove"></td>
        </tr>
      </tbody>
    </table>
  </div>
</form>
<pre style="display: inline-block;" data-bind="text: ko.toJSON($data, null, 2)"></pre>

Upvotes: 1

Related Questions