Steve
Steve

Reputation: 14922

Select All checkbox to select nested angular ng-repeat checkboxes?

I have a series of nested ng-repeat checkboxes, where it's a structure like:

The "select all" in each group should select all "country" checkboxes in that group.

You can see it in action here: http://plnkr.co/edit/rBIv9lfOr5MASPia7ORS?p=preview

The inner checkboxes are generated by an array in the main json:

  $scope.carriers = 
  [{
    "name": "UPS",
    "selected": false,
    "hasPaymentOptions": false,
    "isSelectable": true,
    "value": "",
    "countries": [
        "USA","UK","Canada","Germany","Australia"
     ]
   },etc

And are in a nested ng-repeat:

<!-- main list of carrier checkboxes -->
    <div ng-repeat="c in partnerent.carriers.carriers" class="spacer-top-md spacer-bottom-md">
      <div class="carrier spacer-bottom-sm">
        <div class="checkbox-inline">
          <label>
            <input type="checkbox" name="{{c.name | slug}}" ng-model="c.selected"> {{c.name}}
          </label>
        </div>
        <!-- inner checkboxes for countries -->
        <ul class="entitlement-countries list-inline">
          <li ng-repeat="ec in c.countries">
            <div class="checkbox-inline">
              <label>
                <input type="checkbox" name="{{ec | slug}}"> {{ec}}
              </label>
            </div>
            </li>
            <li ng-if="c.countries.length > 0">
              <div class="checkbox-inline">
                <label>
                  <input type="checkbox" name="{{ec | slug}}_selectall"> Select all
                </label>
              </div>
            </li>
        </ul>

It all works, but my question is how to have those "select all" checkboxes select their group of countries? Most of the solutions and directives I've found involve the model and are generally for one group of checkboxes, where I have several inside a ng-repeat.

Upvotes: 0

Views: 2742

Answers (2)

gonzofish
gonzofish

Reputation: 1417

Plunker of my answer: http://plnkr.co/edit/d4cV1VP5iPj58ePGvZNR

Note: I didn't change all of the carriers, just the first one in the Plunker

How I would approach this would be to have some sort of ng-change method on the selectAll & the child checkboxes:

<ul class="entitlement-countries list-inline">
    <li ng-repeat="ec in c.countries">
        <div class="checkbox-inline">
            <label>
                <input type="checkbox" name="{{ec.name | slug}}" ng-model="ec.selected" ng-change="checkAllCountriesSelected(c)"> {{ec}}
            </label>
        </div>
    </li>
    <li ng-if="c.countries.length > 0">
        <div class="checkbox-inline">
            <label>
                <input type="checkbox" name="{{c.name | slug}}_selectall" ng-model="c.selectAll" ng-change="checkAllCountriesSelected(c)"> Select all
            </label>
        </div>
    </li>
</ul>

And the data model would change slightly to:

$scope.carriers = 
  [{
    "name": "UPS",
    "selected": false,
    "selectAll": false,
    "hasPaymentOptions": false,
    "isSelectable": true,
    "value": "",
    "countries": [
        { name: "USA", selected: false },
        { name: "UK", selected: false },
        { name: "Canada", selected: false },
        { name: "Germany", selected: false },
        { name: "Australia", selected: false }
     ]
   },etc

And I'd add the change methods:

$scope.checkCountryToggled = function checkCountryToggled (carrier) {
    var carrierCountriesSelected = getSelectedCountries(carrier);

    if (carrierCountriesSelected.length === carrier.countries.length) {
        carrier.selectAll = true;
    } else {
        carrier.selectAll = false;
    }
};

function getSelectedCountries (carrier) {
    var selectedCountries = filterFilter(carrier.countries, function (country) {
        return country.selected;
    });

    return selectedCountries || [];
}

$scope.checkSelectAllToggled = function (carrier) {
    if (carrier.selectAll) {
         selectAllCountries(carrier);
    }
};

function selectAllCountries (carrier) {
    angular.forEach(carrier.countries, function (country) {
        country.selected = true;
    });
}        

Upvotes: 0

Vinay K
Vinay K

Reputation: 5572

Use ng-checked directive to select all the checkboxes.

<ul class="entitlement-countries list-inline">
  <li ng-repeat="ec in c.countries">
    <div class="checkbox-inline">
      <label>
        <input type="checkbox" name="{{ec | slug}}" ng-checked="c.countries.selectAll"> {{ec}}
      </label>
    </div>
    </li>
    <li ng-if="c.countries.length > 0">
      <div class="checkbox-inline">
        <label>
          <input type="checkbox" name="{{ec | slug}}_selectall" ng-model="c.countries.selectAll"> Select all
        </label>
      </div>
    </li>
</ul>

Here is the updated plnkr: http://plnkr.co/edit/o2NOBmFYZMtfkBu4lTrs?p=preview

Upvotes: 0

Related Questions