Markus
Markus

Reputation: 297

AngularJS display array based off checkbox selection

I have 4 check boxes, and depending on which one/pair is selected I want a specific array to be displayed on the page. I'm relatively new to angularjs so I'm not sure how to get this to work. So how do I a) check which check box is selected through angular, b) print out the specific array, and c) if "Do Nothing" is selected a message will appear instead of the array. The content should be dynamic so if i choose a different check box the content will change as well. http://codepen.io/MarkBond/pen/gpJWKe?editors=101 the "Simple Form Object" is just to show what that current boolean value is not the array of names that are supposed to appear.

HTML

<html ng-app="myApp">
 .....
 <body ng-controller="FormController">
 <form>
  <div class="checkbox">
    <label>
      <input type="checkbox" name="displayOption" ng-model="formData.displayOption.fiftyMill"/>50 million
    </label>
  </div>
  <div class="checkbox">
    <label>
      <input type="checkbox" name="displayOption" ng-model="formData.displayOption.hundredMill" />100 million
    </label>
  </div>
  <div class="checkbox">
    <label>
      <input type="checkbox" name="displayOption" ng-model="formData.displayOption.statusQuo"/>Status Quo
    </label>
  </div>
  <div class="checkbox">
    <label>
      <input type="checkbox" name="displayOption" ng-model="formData.displayOption.doNothing"/>Do Nothing
    </label>
  </div>
  <div ng-repeat="ActionController as actionCtrl">
    <a>{{ page.name }}</a>
    {{ message }}
  </div>
</form>
</body>
</html>

AngularJS

angular.module('myApp', [])

.controller('FormController', ['$scope' ,function($scope) {

  // Just for outputting data
  $scope.formData = {};

    // Trying to place the boolean value of each checkbox into a variable
    var value1 = '$scope.fiftyMill';
    var value2 = '$scope.hundredMill';
    var value3 = '$scope.statusQuo';
    var value4 = '$scope.doNothing';

    // Checks to see which checkbox is selected then outputting array 
    // associated with selection 
    if (value1 === true || value2 === true) {
        this.page = groupOne
    } else if (value3 === true) {
        this.page = groupTwo
    } else if (value1 === true || value2 === true && value3 === true) {
        this.page = groupThree + groupOne + groupTwo
    }else{
        this.message = 'No Options'
    }

    // Array gtoups
    var groupOne = [
      { name: 'BudgetCharts'},
      { name: 'BudgetComparison'},
      { name: 'EDITBudgetAmounts'}
    ]

    var groupTwo = [
      { name: 'Optimize'},
      { name: 'ReviewAndAdjust'}
    ]

    var groupThree = [
        { name: 'Export'},
        { name: 'Import'},
        { name: 'Construction Program'},
        { name: 'ExportStrategies'}
    ]
}]);

Updated question with how my current code works also with a workable codepen

Upvotes: 2

Views: 2621

Answers (3)

Maxim Zhukov
Maxim Zhukov

Reputation: 10140

I'm not sure what would you like to achieve, but i could code your example like this: http://codepen.io/anon/pen/xGNLJe?editors=101

Explanations:

(function(angular) {
  "use strict";

  angular
    .module('formApp', [])
    .controller('FormController', ['$scope', function($scope) {
      var groupOne = [
        { name: 'BudgetCharts'},
        { name: 'BudgetComparison'},
        { name: 'EDITBudgetAmounts'}
      ];

      var groupTwo = [
        { name: 'Optimize'},
        { name: 'ReviewAndAdjust'}
      ];

      var groupThree = [
        { name: 'Export'},
        { name: 'Import'},
        { name: 'Construction Program'},
        { name: 'ExportStrategies'}
      ];

      $scope.formData = {};

      $scope.$watch("formData.displayOption", function(displayOption) {
        if(displayOption) {
          var value1 = displayOption.fiftyMill,
              value2 = displayOption.hundredMill,
              value3 = displayOption.statusQuo,
              value4 = displayOption.doNothing;

          $scope.pages = null;
          $scope.message = null;

          if (value1 === true || value2 === true) {
            $scope.pages = groupOne;
          } else if (value3 === true) {
            $scope.pages = groupTwo;
          } else if (value1 === true || value2 === true && value3 === true) {
            $scope.pages = groupThree + groupOne + groupTwo;
          } else {
            $scope.message = 'No Options';
          }
        }
      }, true);
    }]);
})(angular);

So, step by step:

  1. Remove ng-click:

As you could see, your checkbox's markup now looks like this:

<input type="checkbox" name="displayOption" ng-model="formData.displayOption.fiftyMill"/>

I removed your ng-click handler and process ng-model updating with $scope.$watch (https://docs.angularjs.org/api/ng/type/$rootScope.Scope) like this:

$scope.$watch("formData.displayOption", function(displayOption) { ... }, true);

  1. Add $scope.pages and $scope.message variables, interact with it in code and display in view. This is body of your $watch function:

This fires every time, when "watching" variable (formData.displayOption in your case) changes.

$scope.pages = null;
$scope.message = null;

if (value1 === true || value2 === true) {
    $scope.pages = groupOne;
} else if (value3 === true) {
    $scope.pages = groupTwo;
} else if (value1 === true || value2 === true && value3 === true) {
    //
    // Algorithm never goes here, because:
    // value1 === true || value2 === true, always goes to first if block
    // value3 === true, it goes to second if block
    // there aren't any other options to go here 
    //
    $scope.pages = groupThree + groupOne + groupTwo;
    //
    // groupThree, groupOne, groupTwo are arrays. If you plus
    // arrays in javascript like this: 
    // [1,2] + [3,4,5] you will get string = "1,23,4,5"
    //
    // if you want to have [1,2,3,4,5] array as result of adding arrays,
    // you have to use concatenation like this:[1,2].concat([3,4,5])
    //
    // In your case:
    // $scope.pages = groupThree.concat(groupOne.concat(groupTwo));
} else {
    $scope.message = 'No Options';
}

and then display in view (as you can see, you assign into $scope.pages an array, so you could iterate over it with ng-repeat):

<h3>Pages</h3>
<div ng-repeat="page in pages">
  {{ page.name }}
</div>  

<div>{{ message }}</div>

P.S. Look at comments in my code, you could have mistakes in places i've commented.

Upvotes: 2

jyrkim
jyrkim

Reputation: 2869

I tried to apply ng-if in the above context, and it seemed quite useful. You can use ng-if to show and hide DOM elements, which in this case display group data. So if third checkbox is checked, then show Group 2 array:

   <h4>Group2</h4>
   <div ng-repeat="g2 in groupTwo" ng-if="value3">
      {{g2.name}} 
   </div>

If you have multiple models on which the appearance is dependent on, then you can apply Boolean conditions in your ng-if expression like below:

   <h4>Group 1</h4>
   <div ng-repeat="g1 in groupOne" ng-if="value1 && value2">
      {{g1.name}} 
   </div>

I discovered the above in older answer: angular-ng-if-with-multiple-arguments

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<body ng-app="checkBoxExample">
  <script>
  angular.module('checkBoxExample', [])
    .controller('ActionController', ['$scope', function($scope) {

      $scope.groupOne = [{name:'BudgetCharts'},{name:'BudgetComparison'},{name:'EDITBudgetAmounts'}];
      
      $scope.groupTwo  = [{name:'Optimize'},{name:'ReviewAndAdjust'}];
      
      $scope.groupThree = [{ name: 'Export'},{ name: 'Import'},{ name: 'Construction Program'}, { name: 'ExportStrategies'}];     
    }]);
</script>
<form name="selectionForm" ng-controller="ActionController">
    <table class="table table-striped">
        <thead>
           ...nothing important in here
        </thead> 
        <tbody>
           <tr>
              <td>
                 <div class="checkbox">
                     <label>
                         <input type="checkbox" id="selectionCondition" ng-model="value1" ng-checked="value1"/>50 million
                         <button rel="popover" type="button" class="close hoverMessage" data-dismiss="modal" data-toggle="popover" data-content="And here's some amazing content. It's very engaging. right?">
                              <span class="fa fa-info-circle">Button 1</span>
                         </button>
                     </label>
                  </div>
                </td>
       
             </tr>
             <tr>
                <td>
                   <div class="checkbox">
                       <label>
                           <input type="checkbox" id="selectionDistribution" ng-model="value2" ng-checked="value2"/>100 million
                              <button rel="popover" type="button" class="close hoverMessage" data-dismiss="modal" data-toggle="popover" data-content="And here's some amazing content. It's very engaging. right?">
                                  <span class="fa fa-info-circle">Button 2</span>
                              </button>
                       </label>
                   </div>
                </td>
             </tr>
             <tr>
                <td>
                   <div class="checkbox">
                        <label>
                            <input type="checkbox" value="status" id="selectionProgram" ng-model="value3" ng-checked="value3"/>Status Quo
                            <button rel="popover" type="button" class="close hoverMessage" data-dismiss="modal" data-toggle="popover" data-content="And here's some amazing content. It's very engaging. right?">
                               <span class="fa fa-info-circle">Button 3</span>
                            </button>
                        </label>
                    </div>
                 </td>
              </tr>
              <tr>
                 <td>
                     <div class="checkbox">
                          <label>
                             <input type="checkbox" value="nothing" id="selectionTreatment" ng-model="value4" ng-checked="value4"/>Do Nothing
                             <button rel="popover" type="button" class="close hoverMessage" data-dismiss="modal" data-toggle="popover" data-content="And here's some amazing content. It's very engaging. right?">
                                 <span class="fa fa-info-circle">Button 4</span>
                             </button>
                        </label>
                     </div>
                 </td>
              </tr>
          </tbody>
       </table>
       <h4>Group 1</h4>
       <div ng-repeat="g1 in groupOne" ng-if="value1 && value2">
          {{g1.name}} 
       </div>
       
       <br>
       <h4>Group 2</h4>
       <div ng-repeat="g2 in groupTwo" ng-if="value3">
          {{g2.name}} 
       </div>
       
       <br>
       
       <h4>Group 3</h4>
       <div ng-repeat="g3 in groupThree" ng-if="value1 && value2 && value3">
          {{g3.name}} 
       </div>
       
        <br>

       <div ng-if="value4">
          <b>Do Nothing selected</b>
       </div>
    </form>
</body>

Upvotes: 2

Zoltan Rakottyai
Zoltan Rakottyai

Reputation: 1662

Don't really understand, but I think you're missing the know-how for "two-way data binding"!

Twoway databinding makes your angular app really dynamic by refreshing the controller (js code) if the model changes (inputs in html using ng-model).

Check this example on codepen: http://codepen.io/ngocminh1112/pen/EjPapL Take a look on the Sample Form Object below in the pen, how angular updates the formData variable by interacting with the inputs.

So, there is one variable called formData binded to the scope:

$scope.formData = {};

and all the inputs gets that one variable with custom property.

Angular updates the scope.formData object when you interact with the inputs.

Upvotes: 1

Related Questions