Why The World Needed Another Angular Grid
--
The Story of ag-Grid
Breaking for Christmas at the end of 2014, I left work frustrated. We released a new system into production with ‘usability issues’ due to our choice of grid component. Every time we started a new project the question ‘which grid should we use’ came up and each time there was debate. Each grid had its merits, no grid fit well. We were on our third project in three years to be using AngularJS 1.x, having tested 5 different grids that ‘worked’ with AngularJS 1.x.
In the beginning we were new to AngularJS 1.x, so we decided to use ng-grid. We found the basic interface into ng-grid nice and simple, an AngularJS 1.x directive that took a list of columns and a list of rows. However we also needed to have checkbox selection and grouping, and found to get these items from ng-grid required using plugins, looking at ng-grid source code and hacking around. These we could live with (ie our users don’t care about these things) but found frustrating as developers. Once our tables started to grow in size beyond 20 columns and once we introduced pinned columns, the grid gave the user experience that the application had stalled — in other words it made the application unusable.
So for our more complex tables we went with jqxGrid. jqxGrid performed much better with large data-sets, but we still found it lacking. It behaved a bit clunky, was tricky to extend and customise, and wasn’t native to AngularJS 1.x(making it not ‘natural’ for the AngularJS 1.x developer). We stuck with jqxGrid, taking it as the ‘best choice for now’.
We also considered SlickGrid. It’s widely adopted, free, and performed very well. However it didn’t support pinned columns (unless you went with a branch) and it wasn’t written with AngularJS 1.x in mind.
I realised in 2014 that ng-grid was been rewritten, that ui-grid was going to be the new ng-grid and solve the performance problems. So I kept a close eye on ui-grid and was excited in late in 2014 when I could download a release candidate of ui-grid. Finally I could say goodbye to jqxGrid and move back into the pure-AngularJS 1.x world… I really wanted ui-grid to be my answer…
Performance in ui-grid was disappointing. And it had bugs. OK so the bugs I could deal with, it was a release candidate after all and bugs are expected in initial releases of all software (note: time of writing, 4 months later, it’s still release candidate), but the performance made our application fail system test. That means the performance was so bad our test team deemed the application not suitable to be released into production. I was ready to be ui-grids number one fan!! But we took it out and put jqxGrid back in :(
So jqxGrid was again our grid of choice and I went home for Christmas to mull over it all. SlickGrid showed Javascript was capable of a great fast grid. But I liked the interface and native AngularJS 1.x feel of ui-grid. How hard would it be to match SlickGrid for performance, but keep the AngularJS 1.x interface??? Can it really be that difficult to write a grid that gave me this?
So I began my Christmas break pet project entitled “How do you build a lightning fast grid for AngularJS 1.x”.
First step was technology choice. I wrote the following prototypes, wanting to consider every possibility:
- SVG:
SVG DOM elements. I considered using D3 to interface with the DOM, but for the fastest possible grid, I thought D3 could add an unnecessary layer. So I wrote raw Javascript creating SVG. I virtualised the rows on a scrolling div. This was interesting for me to program, but I knew where this was going, out of reach of most developers not used to SVG and hence customisation was going to be a nightmare. Time for the next prototype…
- Canvas:
Canvas was of interest to me because games are programmed using the HTML canvasand games render very fast, with complicated scenes drawn at high frame rates. So I created a canvas to act as my viewport, and used sliders to act as scrollbars (ie no native browser scrolling). The position of the sliders indicated to the grid engine what part of the grid to render within the viewable area. This is how 2D scrolling platform games work, deciding what gets rendered in the visible viewport depending on the scroll position. I then used canvas 2D drawing API to render the grid cells. This prototype worked very fast but had the following drawbacks: a) looked awful as the styling could not use CSS and layout was crude b) you loose all dom interactivity on elements (ie you cannot attach native browser events to your own canvas objects) and c) like SVG this option pushed the technology out of reach of the ordinary Javascript developer (unless like me you like programming games).
- Pure AngularJS 1.x:
ui-grid did, use Angular JS for everything — almost using the project to showcase AngularJS 1.x. So I created a grid using about eight directives, one for a cell, one for a row, one for a column header e.t.c. and create my own ‘ng-repeat’ to virtualise the rows (I did not virtualise the columns, I do not believe this should be done as it is not normal to have a table with hundreds of columns). This created a lot of Angular scopes and some extra levels of div’s than I wanted (unnecessary baggage). The result was very AngularJS 1.x-esque, performed fine (better than ui-grid, but unfair to make a comparison at this point as I didn’t have any complex features in) but didn’t perform as well as SlickGrid. You see, Angular JS is great for form based applications, where you don’t have hundreds of bound values laid out in a grid and scrolling. I still use Angular JS as my primary building tool for web applications. However the ‘free stuff’ you get costs CPU processing and redraw lags (waiting for the digest cycle), and grids require fast redraw when been scrolled and virtualised, so the extra logic that AngularJS 1.x puts in behind the scenes doesn’t work in your favour when building something like a complex grid. So my journey continued, how can a grid be an AngularJS 1.x component but yet not use AngularJS 1.x???
- Hybrid AngularJS 1.x:
AngularJS 1.x to present the grid (so has an AngularJS 1.x interface like ui-grid) but doesn’t use AngularJS 1.x itself to draw the grid. This incidentally became the evolutionary prototype of what is now ag-Grid. When drawing the grid, not using AngularJS 1.x means you don’t get two-way-binding. However in my experience, the vast majority of grids don’t require this, so supporting it is slowing down everything to cater for the few. The performance, to my surprise, was up to SlickGrid. I say ‘to my surprise’ as I was expecting it to be harder to come up with a fast grid (if I’d had an inkling I wouldn’t of bothered with my SVG and canvas experiments, but they were fun, if you consider alone on your laptop writing code that will never be used ‘fun’). But what about AngularJS 1.x, what if someone did want two-way-binding, or use AngularJS 1.x to customise a cell? Easy — we can add that as an option! If you want to use AngularJS 1.x you can, just turn it on and have your rows compiled AngularJS 1.xstyle!!!
The Hybrid AngularJS 1.x was the clear winner. The SVG and canvas experiments were fun but ended up in my ‘home office software graveyard’. With the prototype under my belt, I felt I had the workings of a grid worthy of investing more time in, so I came up with a list of all the things I wanted in a grid. My list was as follows (otherwise known as requirements):
- AngularJS 1.x Interface
- Customisable Cell Editors and Renderers
- Themable via CSS
- Pinned columns & Checkbox Selection
- ‘Excel like’ filtering
- Customisable Filters
- Aggregations and Grouping
- Zero Dependencies
- Other stuff
So I coded up the new grid in time for getting back to work in 2015. I introduced ag-Grid to the ‘troubled’ application. What a breath of fresh air! For the first time we had a grid that performed as well as SlickGrid and had a programming interface native to AngularJS 1.x. The styling and customizing worked a treat. The grid made our application more responsive than any of the grids that we had used. For the first time I felt our grid choice was without compromise.
ag-Grid has been released as open source for anyone who finds it helpful. We are continuing to use it in my work, so you can expect it to be maintained for the foreseeable future.
And that is the story of ag-Grid. I hope my contribution back to the community can help out if you are suffering the same frustration I used to with the grid choices for AngularJS 1.x. I intend continuing with ag-Grid, making it a great choice for AngularJS 1.x, or even non-AngularJS 1.x web development. So please spread the word, the more people who use it, the better it will become.
Niall Crosby, March 2015.
UPDATE: 6 years later ag-Grid is going as strong as ever thanks to your support.
Learn more about AG Grid — high performance JavaScript Data Grid. We write the code to visualise data in interactive tables so you can concentrate on writing the application code. We support multiple frameworks: Angular, Vue, React so you can pick the best framework for your needs.