satya satya - 6 months ago 152
AngularJS Question

How to limit check box clicked using Angular.js/Javascript

I need one help.I have many check boxes in a loop and i need to restrict those using some condition using Angular.js.Let me to explain my code first.Here in plunkr my code is present.I can check there each day has one check box and if user is clicking on

+
button the check box is increasing ,Here i need when user has checked on max
2
check box from any day the other will get disabled.Only 2 checkbox can checked from that whole table from the
7
days.I also need after clicking on
store
button the two check box value with respective row drop down data should fetch into controller side function.Please check my code here and help me.

Answer

So, the other answer gets you on the right track, and this one should get you all the way there. You basically want to take advantage of angular's ng-disabled attribute, and when the expression you give it evaluates to true, the form field it's attached to will be disabled.

In your html, you can put the following on any form field you would like disabled when your criteria are met:

  ng-disabled="isDisabled($parent.$index, $index)"

The parent index will refer to the day of the current outer loop, and the index refers to the current answer in the inner loop.

The main controller logic I used to implement this solution is the following:

  // initialize an array of selections
  $scope.selectedAnswers = [];

  // check if answer is selected...
  // have to keep track of both the index of the answer and its parent day
  $scope.answerIsSelected = function(dayIdx, answerIdx) {
    var thisAnswer = $scope.days[dayIdx].answers[answerIdx];
    return $scope.selectedAnswers.indexOf(thisAnswer) > -1;
  };

  // depending on whether answer is already selected, 
  // adds it to or splices it from the selectedAnswers array
  $scope.toggleAnswerSelected = function(dayIdx, answerIdx) {
    var thisAnswer = $scope.days[dayIdx].answers[answerIdx];
    if ($scope.answerIsSelected(dayIdx, answerIdx)) {
      $scope.selectedAnswers.splice($scope.selectedAnswers.indexOf(thisAnswer), 1);
    } else {
      $scope.selectedAnswers.push(thisAnswer);
    }
  };

  // the check on each form element to see if should be disabled
  // returns true if the answer is not an element in the selected array
  // and if there are already two answers in the array
  $scope.isDisabled = function(dayIdx, answerIdx) {
    return !$scope.answerIsSelected(dayIdx, answerIdx) && $scope.selectedAnswers.length === 2;
  }; 

And finally, the attributes you want on your checkbox at the end of the row:

  <input type="checkbox" 
         name="chk" 
         value="true" 
         ng-checked="answerIsSelected($parent.$index, $index)"
         ng-click="toggleAnswerSelected($parent.$index, $index)"
         ng-disabled="isDisabled($parent.$index, $index)"> 

Full snippet below...

var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope,$q, $filter) {

  $scope.submitted = false;
  $scope.init = function() {
    $scope.days = [];

    $scope.listOfCategory = [{
      id:1,
      name: 'Category 1',
      value: 1
    }, {
      id:2,
      name: 'Category 2',
      value: 2
    },{
		id:3,
		name: 'Category 3',
        value: 3
	}];

     $scope.listOfSubCategory=[];

    //emulating ajax response: this should be removed, days reponse
    var response = {
      data: [{
        day_name: "Monday"
      }, {
        day_name: "Tuesday"
      }, {
        day_name: "Wednesday"
      }, {
        day_name: "Thursday"
      }, {
        day_name: "Friday"
      }, {
        day_name: "Saturday",
      }, {
        day_name: "Sunday"
      }]
    };
    //end response

    //success
    angular.forEach(response.data, function(obj) {
      obj.answers = [];
      $scope.addNewRow(obj.answers);
      $scope.days.push(obj);
    });
  };
  
  $scope.renderWithMode = function(index,catvalue,parent,isEditMode){
    if(isEditMode){
      $scope.removeBorder(index,catvalue,parent);
    }
  };
  
  $scope.removeBorder = function(index,catvalue,parent){
    //make $http call here
    //below code should be removed, its emulated response
    var subcategories = [{
        id:1,
        name: 'SubCategory 1',
        value: 1
      }, {
        id:2,
        name: 'SubCategory 2',
        value: 2
      }, {
        id:3,
        name: 'SubCategory 3',
        value: 3
      }, {
        id:4,
        name: 'SubCategory 4',
        value: 4
      }];
     
    //after reponse from server as subcaegory  
    if(!$scope.listOfSubCategory[parent]){
      $scope.listOfSubCategory[parent] = [];  
    }
	//console.log('value',catvalue);
	 var subcategories1=[];
   // $scope.listOfSubCategory[parent][index] = angular.copy(subcategories);
   var result = $filter('filter')(subcategories, {id:catvalue})[0];
  // console.log('result',result);
   subcategories1.push(result)
   $scope.listOfSubCategory[parent][index] = subcategories1;
  };

  $scope.addNewRow = function(answers) {
    answers.push({
      category: null,
      subcategory: null,
      comment: null
    });
  };
  
  $scope.submitAnswers = function(){
    // console.log($scope.selectedAnswers);
    $scope.submitted = true;
    $scope.sendToServer = $scope.selectedAnswers;
  };
  
  $scope.getResponse = function(){
    //emulating reponse: this should come from server,
    var response = {
      data: [{
        day_name: "Monday",
        answers:[{
          category:2,
          subcategory:1,
          comment:'This is answer 1'
        },{
          category:1,
          subcategory:2,
          comment:'This is answer 2'
        }]
      }, {
        day_name: "Tuesday",
        answers:[{
          category:1,
          subcategory:2,
          comment:'This is answer 1'
        }]
      }, {
        day_name: "Wednesday"
      }, {
        day_name: "Thursday"
      }, {
        day_name: "Friday"
      }, {
        day_name: "Saturday",
      }, {
        day_name: "Sunday"
      }]
    };
    
    $scope.days = [];
    angular.forEach(response.data, function(obj) {
      if(!obj.answers){
        obj.answers = [{
          category:null,
          subcategory:null,
          comment:null
        }];
      }
      $scope.days.push(obj);
    });
    
    $scope.isEditMode = true;
  };
  
  $scope.selectedAnswers = [];
  
  $scope.answerIsSelected = function(dayIdx, answerIdx) {
    var thisAnswer = $scope.days[dayIdx].answers[answerIdx];
    return $scope.selectedAnswers.indexOf(thisAnswer) > -1;
  };
  
  $scope.toggleAnswerSelected = function(dayIdx, answerIdx) {
    var thisAnswer = $scope.days[dayIdx].answers[answerIdx];
    if ($scope.answerIsSelected(dayIdx, answerIdx)) {
      $scope.selectedAnswers.splice($scope.selectedAnswers.indexOf(thisAnswer), 1);
    } else {
      $scope.selectedAnswers.push(thisAnswer);
    }
  };
  
  $scope.isDisabled = function(dayIdx, answerIdx) {
    return !$scope.answerIsSelected(dayIdx, answerIdx) && $scope.selectedAnswers.length === 2;
  };
  
  $scope.removeRow = function(answers,index,parent){
	   answers.splice(index, 1);
	   $scope.listOfSubCategory[parent].splice(index,1);
   // answers.splice(answers.length-1,1);
  };
  
});
<!DOCTYPE html>
<html ng-app="plunker">

<head>
  <meta charset="utf-8" />
  <title>AngularJS Plunker</title>
  <script>
    document.write('<base href="' + document.location + '" />');
  </script>
  <link rel="stylesheet" href="style.css" />
  <script data-require="angular.js@1.4.x" src="https://code.angularjs.org/1.4.9/angular.js" data-semver="1.4.9"></script>
  <script src="script.js"></script>

<body ng-controller="MainCtrl">
  Plunker
  <table ng-init="init()" class="table table-bordered table-striped table-hover" id="dataTable">
    <thead>
      <tr>
        <th>Day</th>
        <th>Category</th>
        <th>Sub Subcategory</th>
        <th>Comments Or special promotion</th>
        <th>Add More</th>
      </tr>
    </thead>

    <tbody id="detailsstockid">
      <tr ng-repeat="d in days track by $index">
        <td>{{d.day_name}}</td>
        <td>
          <table>
            <tbody>
              <tr ng-repeat="answer in d.answers track by $index">
                <td>
                  <select class="form-control" 
                          id="answer_{{$index}}_category" 
                          name="answer_{{$index}}_category"
                          ng-model="answer.category"
                          ng-options="cat.name for cat in listOfCategory track by cat.value"
                          ng-init="renderWithMode($index,answer.category.value,$parent.$index,isEditMode)" 
                          ng-change="removeBorder($index,answer.category.value,$parent.$index)">
                    <option value="">Select Category</option>
                  </select>
                </td>
              </tr>
            </tbody>
          </table>
        </td>
        <td>
          <table>
            <tbody>
              <tr ng-repeat="answer in d.answers track by $index">
                <td>
                  <select class="form-control" 
                          id="answer_{{$index}}_subcategory" 
                          name="answer_{{$index}}_subcategory" 
                          ng-model="answer.subcategory" 
                          ng-options="sub.name for sub in listOfSubCategory[$parent.$index][$index]">
                    <option value="">Select Subcategory</option>
                  </select>
                </td>
              </tr>
            </tbody>
          </table>
        </td>
        <td>
          <table>
            <tbody>
              <tr ng-repeat="answer in d.answers">
                <td>
                  <input type="text" 
                         id="answer_{{$index}}_comment" 
                         name="answer_{{$index}}_comment" 
                         placeholder="Add Comment" 
                         ng-model="answer.comment" />
                </td>
              </tr>
            </tbody>
          </table>
        </td>
        <td>
          <table>
            <tbody>
              <tr ng-repeat="answer in d.answers track by $index">
                <td style="width:20px">
                  <input ng-show="d.answers.length>1" 
                         class="btn btn-red"   
                         type="button" 
                         name="minus" 
                         id="minus" 
                         value="-" 
                         style="width:20px; text-align:center;" 
                         ng-click="removeRow(d.answers, $index,$parent.$index)" /> 
                </td>
                <td ng-show="$last">
                  <input type="button" 
                         class="btn btn-success"
                         name="plus" 
                         id="plus" 
                         value="+"
                         style="width:20px; text-align:center;" 
                         ng-click="addNewRow(d.answers)" />
                </td>
                <td>
                <input type="checkbox" 
                       name="chk" 
                       value="true" 
                       ng-checked="answerIsSelected($parent.$index, $index)"
                       ng-click="toggleAnswerSelected($parent.$index, $index)"
                       ng-disabled="isDisabled($parent.$index, $index)" /> 
                </td>
              </tr>
            </tbody>
          </table>
        </td>
      </tr>
    </tbody>
  </table>
  <input type="submit" 
         ng-click="submitAnswers()" 
         value="Store">
  <pre ng-if="submitted"> {{ sendToServer | json }} </pre>
 <!-- <input type="button" value="Edit" ng-click="getResponse()">-->
</body>

</html>

Comments