A naive approach with jQuery
At first, I used the same approach as always in my new job. I’ve started writing a Flask application in Python that rendered some HTML. I’ve added some jQuery magic to do stuff like forms with a dynamic number of items that could be added without reloading the whole page and it worked. At first. This time it was a little bit different. The previous projects were usually finished before the point when the pure jQuery code started to be hard to maintain. On the contrary, this project was getting bigger and bigger every day.
Our analytics app contained multiple different screens for different analyses. Those screens contained forms that were getting more and more complex. We added advanced filtering and suddenly the forms contained a dynamic number of items that contained another dynamic number of items that displayed different subforms when switching some select boxes. The jQuery code just bloated and it was hard to maintain and understand.
Moreover, since different types of analyses used same parts of the forms, I felt like the proper way to handle this would be to encapsulate those parts to components that I could reuse and compose together. Doing this in pure jQuery was pain in the ass. I had to deal with maintaining the data model, modifying the DOM when that data model changed, modifying the model when the DOM changed, handling error messages and hiding them when user focused the correct input or removed it by removing one of its parents. This caused lot of boilerplate code and slowed down the development process.
Moving towards AngularJS
I started looking for a framework that will help me solve this problem. The problem was that there were too many of them and it was hard to do an informed decision. It was too time-consuming to evaluate every single one of them.
One of my colleagues suggested AngularJS since he had a previous experience with it. I have already watched some YouTube videos from its creator and I was sure that using it will enable me to remove a lot of the boilerplate code since AngularJS does the data binding between the model and DOM auto-magically. On the other side, I didn’t like some of the concepts like embedding the logic directly into the HTML, it just felt wrong to me.
However, I gave it a try and I started rewriting one of the analyses edit screens into it. The application was not a single page app at this point. All the screens were rendered by the Flask backend. The majority of them contained the ugly jQuery code, except for one which used AngularJS. The code became much easier to understand and it was much shorter. I used directives to turn the parts of the complex forms into smaller components. HTML templates were now easier to understand since I just saw right in the markup that the funnel-editor directive consisted of a funnel-steps component and customer-filter component and how the data was mapped to each of them.
Lessons learned the hard way
So is AngularJS cure for everything? Absolutely not. After spending 3 years with it there are a lot of things I hate about it. Out of the box, it is good and easy to use on one part of an app. It is easy to use in simple single page apps, but as soon as you want to have more complex views (logged out section that looks completely differently, logged in section that uses same navigation on majority of the pages, but not on all of them) you will have to use a custom router since the default one doesn’t support inheritance of views commonly used in templating languages. This is the stuff that you as an AngularJS newbie don’t know and if you realize that after you have already written a lot of code, then I wish you a happy rewriting.
There is no built-in support for authentication and access rights in the default router, you have to build your own.
For me, the biggest drawback is the performance. For an AngularJS newbie, it is very tempting to use the two-way binding since it makes a lot of stuff easy to write. The problem is, that every time you add one two-way bound variable, you have one more expression that AngularJS have to watch and compare for changes. AngularJS do such comparisons quite often, more often that you think and the two-way bindings can be easily created dynamically for example by using several nested ng-repeats (the stuff that usually happens as soon as you write your first table with a dynamic number of columns and rows).
So yes, the Angular’s magic is cool, it can save you a lot of time, but as soon as you don’t care about it, one day you will start wondering why your application freezes for several seconds every time you have a 20 x 1000 table on your screen and you change something in a form above it that doesn’t update the table in any way.
Would I choose AngularJS if I was making the decision again right now? Yes, but it would definitely be AngularJS 2.0 and I would be more careful with the decisions I will be making to save me some time in future. With AngularJS the code is much easier to understand and maintain and there is no way I could write such a big application as Exponea is with just jQuery and remain a sane person at the same time.
Continue to part II: Joining Exponea frontend team & improving productivity
PS: we are currently in a process of upgrading to AngularJS 2.0 and we are looking for new developers to help us.