<!DOCTYPE html>
<html>

<head>
  <link data-require="fontawesome@*" data-semver="4.1.0" rel="stylesheet" href="//netdna.bootstrapcdn.com/font-awesome/4.1.0/css/font-awesome.min.css" />
  <link href="https://cdnjs.cloudflare.com/ajax/libs/ng-grid/2.0.11/ng-grid.css" type="text/css" rel="stylesheet" />
  <link href="style.css" type="text/css" rel="stylesheet" />
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.13/angular.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/ng-grid/2.0.11/ng-grid.debug.js" type="text/javascript"></script>
  <link rel="stylesheet" href="style.css" />
  <script src="script.js"></script>
</head>

<body ng-app="tableExpandCollapseApp">
  <div ng-controller="tableExpandCollapseController">

    <div class="headerPane">
      <h1 class="header"> Description</h1>
      Tables that supports expand (+) and collapse (-) rows.
      <ul>
        <li>Click 
          <span class="fa-stack fa-lg">
  <i class="fa fa-circle fa-stack-2x"></i>
  <i class="fa fa-plus fa-stack-1x fa-inverse"></i>
</span>
          (of any row parenet row) to view it's details (child rows) if present.</li>
        <li>Click <span class="fa-stack fa-lg">
  <i class="fa fa-circle fa-stack-2x"></i>
  <i class="fa fa-minus fa-stack-1x fa-inverse"></i>
</span>
          (of any row parenet row) to hide it's details (child rows)</li>
      </ul>
      <hr />
    </div>

    <div class="left">
      <h2 class="header">HTML table</h2>
      <table>
        <thead>
          <tr>
            <td></td>
            <td>Name</td>
            <td>Quantity</td>
            <td>Type</td>
            <td>Cost</td>
          </tr>
        </thead>
        <tbody>
          <tr ng-repeat="si in selItems">
            <td>
              <div ng-if="si.Summary">
                <!-- <button ng-click="toggleDisplay(si.Type)"> -->
                <div ng-if="si.Summary == '+'">
                  <a href="" ng-click="toggleDisplay(si.Type)">
                    <i class="fa fa-plus"></i>
                  </a>
                </div>
                <div ng-if="si.Summary == '-'">
                  <a href="" ng-click="toggleDisplay(si.Type)">
                    <i class="fa fa-minus"></i>
                  </a>
                </div>
                <!-- </button> -->
              </div>
            </td>
            <td>{{si.Name}}</td>
            <td>{{si.Quantity}}</td>
            <td>{{si.Type}}</td>
            <td>{{si.Cost}}</td>
          </tr>
        </tbody>
      </table>
      <hr />
    </div>

    <div class="right">
      <h2 class="header">ngGrid</h2>
      <div ng-grid="gridOptions"></div>
      <hr />
    </div>

  </div>
</body>

</html>
var app = angular.module('tableExpandCollapseApp', ['ngGrid']);

app.service('shoppingList', function($http, $q) {
  var items;

  return {
    getShoppingList: function() {
      if (angular.isUndefined(items)) {
        items = {};
        return $http.get('http://cdn.rawgit.com/abhijithda/jnaan/master/items.json').success(function(jsonData) {
          items["Items"] = jsonData["Items"];
        });
      } else {
        return $q.when(items);
      }
    }
  };
});


app.controller('tableExpandCollapseController',
  function($scope, shoppingList) {

    $scope.displayItemDetails = {};


    $scope.toggleDisplay = function(iType) {
      console.log("Toggling display of " + iType + " from " + $scope.displayItemDetails[iType]);
      $scope.displayItemDetails[iType] = $scope.displayItemDetails[iType] ? 0 : 1;
      console.log(" to " + $scope.displayItemDetails[iType]);

      console.log(" All display details value:");
      console.log($scope.displayItemDetails);

      $scope.selItems = $scope.updateTable();
      console.log("In toggleDisplay()::selItems: ");
      console.log($scope.selItems);
    };


    $scope.updateTable = function() {
      var selItems = [];
      for (var i in $scope.allItems) {
        var iType = $scope.allItems[i]["Type"];

        if (angular.isUndefined($scope.displayItemDetails[iType])) {
          $scope.displayItemDetails[iType] = 0;
        }

        if (1 == $scope.displayItemDetails[iType]) {
          $scope.allItems[i]["Summary"] = '-';
          console.log("Expanding(" + $scope.allItems[i]["Summary"] + ") details of " + iType);
        } else {
          $scope.allItems[i]["Summary"] = '+';
          console.log("Collapsing(" + $scope.allItems[i]["Summary"] + ") details of " + iType);
        }
        selItems.push($scope.allItems[i]);

        console.log("Display details of " + iType + ": " + $scope.displayItemDetails[iType]);
        if ($scope.displayItemDetails[iType]) {
          console.log("Viewing details of " + iType);
          for (var j in $scope.allItems[i]["Details"]) {
            $scope.allItems[i]["Details"][j]["Summary"] = "";
            selItems.push($scope.allItems[i]["Details"][j]);
          }
        }

      }
      console.log("In updateTable()::selItems: ");
      console.log(selItems);
      return selItems;
    };


    shoppingList.getShoppingList().then(function(result) {
      console.log("Result: ");
      console.log(result);
      $scope.allItems = result.data.Items;
      $scope.selItems = $scope.updateTable();
      console.log("In then::selItems: ");
      console.log($scope.selItems);
    });



    var summaryCellTemplate = "<div ng-if='row.getProperty(col.field)'>" +
      "<button ng-click='toggleDisplay(row.entity.Type)'> {{row.getProperty(col.field)}} </button>" +
      "</div>";

    $scope.gridOptions = {
      data: 'selItems',
      columnDefs: [{
        field: 'Summary',
        displayName: '',
        cellTemplate: summaryCellTemplate,
        width: 30
      }, {
        field: 'Name',
        displayName: 'Name',
      }, {
        field: 'Type',
        displayName: 'Type',
      }, {
        field: 'Cost',
        displayName: 'Cost',
      }, {
        field: 'Quantity',
        displayName: 'Quantity',
      }],
      enableCellSelection: false,
      enableColumnResize: true
    };

  });
* {
  padding: 10;
  margin: 10;
  border: 10;
}
.header {
  background-color: rgba(44, 163, 0, 0.4);
}
.headerPane {
  clear: none;
  float: left;
  position: relative;
  width: 100%;
  height: 20%;
}
.left {
  clear: none;
  float: left;
  position: relative;
  width: 50%;
  height: 80%;
}
.right {
  clear: none;
  float: left;
  position: relative;
  width: 50%;
  height: 80%;
}
.ngViewport.ng-scope {
  height: auto !important;
  overflow-y: hidden;
}
.ngTopPanel.ng-scope, .ngHeaderContainer {
  width: auto !important;
}
Table expand and collapse rows

# Description

Allow expand/collapse of rows of a table in order to view/hide details. When a row is expanded, new rows will show up the details of the expanded row.


# Example: 

Below table that shows the overview:

   |Name   |  Quantity |  Type  | Cost
---|-------|-----------|--------|------                                                               
[+](# expand)|Fruits |  5        | Fruit  |    10                                                               
[+](# expand)|Vegetables |  2    |  Vegetable | 5                                                               
[+](# expand)|Pulses |  2        |  Pulse |    40                                                               
[+](# expand)|Drinks |  4        |  Drink |    20


Below table that shows the details of Fruits item when '+' of the Fruits row is clicked.


   |Name   |  Quantity |  Type  | Cost
---|-------|-----------|--------|------                                                               
[-](# collapse)|Fruits |  5        | Fruit  |    10                                                               
   |Banana |  2      | Fruit  |     1
   |Apple  |  2      | Fruit  |     4
   |Pomogrande |  1    |  Fruit   |   5
[+](# expand)|Vegetables |  2    |  Vegetable | 5                                                               
[+](# expand)|Pulses |  2        |  Pulse |    40                                                               
[+](# expand)|Drinks |  4        |  Drink |    20
    {
      "Items": [{
        "Name": "Fruits",
        "Type": "Fruit",
        "Quantity": 5,
        "Cost": 10,
        "Details": [{
          "Name": "Banana",
          "Type": "Fruit",
          "Quantity": 2,
          "Cost": 1
        }, {
          "Name": "Apple",
          "Type": "Fruit",
          "Quantity": 2,
          "Cost": 4
        }, {
          "Name": "Pomogrande",
          "Type": "Fruit",
          "Quantity": 1,
          "Cost": 5
        }]
      }, {
        "Name": "Vegetables",
        "Type": "Vegetable",
        "Quantity": 2,
        "Cost": 5,
        "Details": []
      }, {
        "Name": "Pulses",
        "Type": "Pulse",
        "Quantity": 2,
        "Cost": 40,
        "Details": []
      }, {
        "Name": "Drinks",
        "Type": "Drink",
        "Quantity": 4,
        "Cost": 20,
        "Details": [{
          "Name": "Water",
          "Type": "Drink",
          "Quantity": 2,
          "Cost": 1
        }, {
          "Name": "Coconut Water",
          "Type": "Drink",
          "Quantity": 2,
          "Cost": 4
        }, {
          "Name": "Pomogrande Juice",
          "Type": "Drink",
          "Quantity": 1,
          "Cost": 5
        }]
      }]
    }