Expandable / collapsable table detail rows with Angular.js

Here is how to create expandable and collapsible tables with Angular.js. I couldn’t find any examples of this online and Angular.js only recently added official support for this in v1.2.0 with ng-repeat using ng-repeat-start/ng-repeat-end.

Don’t get me wrong here, I’m not really a fan of how this looks (I prefer Knockout.js’ “virtual element” approach in this situation) but it seems to be the official/best way to do it with Angular. Luckily I’ve been using Angular for many months now and this is the first time I needed it so it’s pretty uncommon.

What I’m talking about

Collapsed:

Name    Gender
+ Bob    Male
+ Jane  Female
+ Bill     Male

Expanded:

Name    Gender
– Bob     Male
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque quis nisi quis mi tincidunt luctus ut quis nunc. Nam non risus tincidunt risus sodales condimentum. Morbi sed gravida elit. Nunc a turpis vestibulum elit posuere blandit. Phasellus luctus lectus non porta auctor. Etiam pellentesque imperdiet posuere. Nullam adipiscing congue nisl, in vulputate odio ornare ac.
+ Jane  Female
+ Bill     Male

 

JavaScript

function repeatTest($scope) {
  $scope.people = [
    {name: "Bob", gender: "Male", details: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque quis nisi quis mi tincidunt luctus ut quis nunc. Nam non risus tincidunt risus sodales condimentum. Morbi sed gravida elit. Nunc a turpis vestibulum elit posuere blandit. Phasellus luctus lectus non porta auctor. Etiam pellentesque imperdiet posuere. Nullam adipiscing congue nisl, in vulputate odio ornare ac."},
    {name: "Jane", gender: "Female", details: "Maecenas quis sodales lectus, vitae convallis ipsum. Ut ac viverra tellus. Quisque vulputate, orci placerat eleifend scelerisque, eros nunc rutrum odio, pharetra mattis leo neque vel eros. Cras id purus nec lorem vehicula rutrum a vel arcu. Quisque eget euismod augue. Integer volutpat auctor lorem, quis lacinia nisl tempus nec. Nunc fringilla, odio eget molestie varius, tortor turpis dignissim lacus, sed varius nunc velit eu turpis. Etiam sed congue diam. In ornare elit nec dolor faucibus ornare. Ut eget erat vel elit tristique iaculis. Maecenas et semper lorem. Nam mollis ante et ipsum vestibulum posuere. Ut non purus non risus tempor vulputate et vitae ipsum. Mauris et sem sit amet quam pulvinar fringilla."},
    {name: "Bill", gender: "Male", details: "Quisque rhoncus scelerisque sapien, tempor vestibulum dui tincidunt eu. Maecenas scelerisque, dolor sed vehicula pulvinar, ligula erat ornare arcu, in dictum ipsum libero vel est. Donec porttitor venenatis lacus, a laoreet orci. Proin quam mi, ultrices in ullamcorper vel, malesuada suscipit lectus. Nam faucibus commodo quam, auctor vehicula felis condimentum quis. Phasellus tempor molestie enim, at vehicula justo auctor eu. Pellentesque venenatis elit eu malesuada fringilla."}
  ];
}

 HTML

<!DOCTYPE html>
<html>

  <head>
    <script src="http://code.angularjs.org/1.2.0-rc.2/angular.js"></script>
    <link rel="stylesheet" href="style.css" />
    <script src="script.js"></script>
    <style>
      .button
    </style>
  </head>

  <body ng-app="">
    <h1>People and Details</h1>
    <div ng-controller="repeatTest">
      <table>
        <thead style="background-color: lightgray;">
          <tr>
            <td style="width: 30px;"></td>
            <td>Name</td>
            <td>Gender</td>
          </tr>
        </thead>
        <tbody>
          <tr ng-repeat-start="person in people">
            <td>
              <button ng-if="person.expanded" ng-click="person.expanded = false">-</button>
              <button ng-if="!person.expanded" ng-click="person.expanded = true">+</button>
            </td>
            <td>{{person.name}}</td>
            <td>{{person.gender}}</td>
          </tr>
          <tr ng-if="person.expanded" ng-repeat-end="">
            <td colspan="3">{{person.details}}</td>
          </tr>
        </tbody>
      </table>
    </div>
  </body>

</html>

 

Here is an example Plunker with it running. Enjoy and let me know if you’ve found a better way!

19 thoughts on “Expandable / collapsable table detail rows with Angular.js

    1. Not only was my formatting wrong, but I completely overlooked the -start and -end, the point of this article… Sorry but thank you!

  1. Hi John

    Excellent example, and so simple. Works with smart-tables without interfering with their code as well. **Ensure you have the ng-repeat-start** and not just ng-repeat, I tested to the see the difference and sure enough, the expansion only occurs with the start added.

    By the way, John, is there a post on Stack you have answered with this, I wouldn’t mind popping an up-vote on it.

    Kind regards

  2. Hi john,

    I have to use nested ng-repeat using table in angular js. So that on expand i can open other. Can you help me out for this situation.

    Thanks

  3. Can I have an index based check box as part of the main row before expanding, so that I can carry on with my index based functionality. I tried implementing it but I can see only one check box.

    Regards,
    AngelaM

    1. This happened to me by accident, but it’ll work for you.
      In this example, change each occurrence of “person.expanded” to “people.expanded”

  4. Great article; the -start and -end are awesome and the colspan=”3″ is also a great addition since it allows us to put anything into the table row without being restricted by the number .

  5. How to do if one row is expanded and remaining all rows should be collapsed(scenario: if i expand one row, again if i expand one more row. previously expanded should be collapsed.

  6. You made my day. I was building angular version of Jtable and want to give hierarchical support for data.Your solution worked perfectly.

  7. Great solution! Thank you!
    I am looking to add animation to this and tried everything. Strangely the angularjs animate and css transitions are not working well with the tr ng-if elements.
    Any suggestions on how I could go about it?

Leave a Reply

Your email address will not be published. Required fields are marked *

Proudly powered by WordPress | Theme: Cute Blog by Crimson Themes.