Angular ngAnimate table row detail slide down (similar to jQuery.slideDown)

Let’s start with an example of what we’re trying to achieve – click the rows to show and hide a detail row:

IndexIdCol 1Col 2
{{$index + 1}} {{row.id}} {{row.column1}} {{row.column2}}

{{rowDetail}}

I figured this would be pretty straight forward with lots of examples out there in the wild but unless google is broke I can’t find a good example of what I’m after! I don’t want a tonne of hidden table rows, I want to leverage Angulars repeater and ng-if so we don’t clutter up the DOM. Initially I tried to do it using pure CSS but I hit some rendering issues on the table row – the browser would only fully update the table on completion so weird things would happen during the animation. I’ll include that solution at the end, maybe somebody knows how to fix it.

Anyway, so here’s what I did to get it to work using some javascript and ngAnimate.

First, the html:

Main things to note here are that I’m using ng-repeat-start/end to render the data row, then the detail row. ng-if in the detail row will get angular to add/remove the row to the DOM as required. Also within the td on the row (where I’ve set the colspan to cover the all columns) I’ve had to add two divs. The first I’ve given the class ‘slide-outer’, which is the element we’ll be resizing in script, and the second div is our actual content. Doing it this way means we can grab the height of the inner divs content, so we know what size we need to use on the outer one.

OK so next, the CSS. This is simply:

Next is the script. I’m just going to dump the whole lot in, and then describe what’s going on:

So – first, I’m just generating some data that all goes into the table variable, and creating some random detail for each row. Then I’m setting up my angular app with the “slider” controller. This just has two functions, one that sets the selectedRow when a row is clicked, and one that is used to evaluate which row is selected. Pretty standard stuff so far.

Next is where the magic happens, in the app.animation section. When a row is clicked, the enter and leave functions are called by ngAnimate. These functions find my slider div then call initShrinky, telling it which direction to animate, so up for leave and down for enter. The doneFn is an internal ngAnimate function that we pass over and call when we’re finished so it knows we’re done.

initShrinky stuffs the row into the shrinkyItems array, which gives us an id that we’ll use to work out what we’re animating. We then call the shrinky function in a timeout, which simply looks at the direction we’re animating, applies the new height, then if we’ve not reached our target calls itself again. Once we hit the target height, we call the doneFn function and clear out the array position. (I think this final bit in particular could be improved!)

Then Boom! That’s all there is to it!

Leave a Reply

Your email address will not be published.