1

I have many check boxes in a loop and I need to restrict those using some condition using Angular.js. Let me share my code in Plunkr first.

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.

3
  • Bind the value of each checkbox to a model (using the ng-model directive) and use $scope.$watch function to monitor the count of the number of checkboxes selected and, based on that count, enable or disable the desired elements. Commented May 26, 2016 at 5:51
  • Can you edit your answer there .In plunkr. Commented May 26, 2016 at 5:54
  • This question is not self-contained, so should be closed. Commented Nov 26, 2022 at 10:46

1 Answer 1

1

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="[email protected]" 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>

Sign up to request clarification or add additional context in comments.

8 Comments

I checked your answer,i need to disable only check box not other field and also retrieve the checked value with respective row all value.
All you had to do to disable only the checkboxes was to remove the ng-disabled attribute from all the other inputs/selects, but I went back in and edited them out accordingly. And when you click Store, the pre displays the selected values for each of the selected answer rows. Does this not answer your question?
yes,i need only disable the check box after 2 checked.After editing please give the comment.
I'm sorry guys, but this is turning from "question" to "do my homework for free", deleting my answer and voting for close this right now.
@BennettAdams : Your code is working properly and so flexible.Thanks.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.