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!
This wouldn’t work since is outside of the repeater in the above
Not only was my formatting wrong, but I completely overlooked the
-start
and-end
, the point of this article… Sorry but thank you!Hi how are you ? That was a really helpful example exactly what I need for clickable exandable row. Sweet thanks.
Hi John,
in the WPF days I put a IsExpanded property on the ViewModel. Then you do not need the 2 buttons.
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
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
Works like a charm! Thanks!
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
Thanks! Really helpful!
Is there a way to expand / collapse ALL of the rows in a parent table?
This happened to me by accident, but it’ll work for you.
In this example, change each occurrence of “person.expanded” to “people.expanded”
How to implement ‘close others’ functionality in this example.
Is there a way to expan specific while collapse all others?
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 .
How can I select collapsible row. Like If I select all the collapsible rows under it should get selected?
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.
You made my day. I was building angular version of Jtable and want to give hierarchical support for data.Your solution worked perfectly.
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?
Hey Nice solution. Thank you very much!!