2

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

Markus
  • 297
  • 4
  • 19

3 Answers3

2

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>
Community
  • 1
  • 1
jyrkim
  • 2,849
  • 1
  • 24
  • 33
  • Thank you for your answer as it helped me understand ng-if but I it wont be able to help me in this situation because this is only a small sample of the hundreds of page names and dozens of groups. So it would be very DRY to have a an individual div for each group. If there is a way to have just one div that can dynamically hold all of the groups together (depending on which checkbox is selected) then maybe this can work. – Markus Aug 17 '15 at 17:56
  • @Markus thanks for the info :-) i think in the controller's function some kind of array/object manipulation could be done. I'm thinking about putting selected groups in one array. In the view then print the same array that has the groups that represent the selected checkboxes. – jyrkim Aug 18 '15 at 07:05
2

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.

Maxim Zhukov
  • 10,060
  • 5
  • 44
  • 88
  • Really awesome work! Only issue I'm having is the .concat() for the three groups isn't working for me (groupThree.concat(groupOne.concat(groupTwo))) – Markus Aug 17 '15 at 20:38
  • i also tried groupOne.concat(groupTwo,groupThree); which works in w3schools but not with my code :/ – Markus Aug 17 '15 at 20:55
1

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.

ZR87
  • 1,463
  • 16
  • 27
  • Seems like the approach I want to take, but i cant for the life of me get it to work properly. I'm essentially using the checkbox code and using it in my code but it doesnt work – Markus Aug 17 '15 at 14:47
  • I also updated my code and added a codepen that is very similar to what you had but with some of my code to work with. – Markus Aug 17 '15 at 16:07