Monday, December 23, 2013

Data binding in AngularJS

One of the most important things in AngularJS is the data binding. In fact I think it is so important it should be one of the first things you should get to know if you start to write Angular apps. It should be explained more and it shouldn't be just "the magic that we won't cover right now".

The real magic behind Angular's data binding is called dirty checking. Basically every time you write {{myModel}} in the background a new watch for the expression myModel is being created that on every $digest cycle will be evaluated and if the value of the model is changed, the DOM will be updated. Thanks to this dirty checking we are also able to use plain old JS object as our model. How data binding works is explained in detail in this great article - http://angular-tips.com/blog/2013/08/watch-how-the-apply-runs-a-digest/. I also recommend to read Misko's answer to this StackOverflow question on why dirty checking is not a bad thing, unless of course it is used in a bad way. This is why we should understand how data binding works.

An example of such a bad use would be to bind to a function that makes some complex computations. In this example not so complex, but lets have have an input that will represent a value for radius of a circle and we will calculate it's area and show it. We can create a function and bind to it
However if you look at the console output, you will see that on every radius change, it is called twice, once on the first loop of the $digest cycle and because the area value was changed it will called once again in the second loop. We can even bind to this function in multiple places in the view, and unlike I expected it to work, for each one of them it will add a watch in the $watch list, and the function will be called multiple times. For example if we add
<div>Area {{calculateArea()}}</div>
on 3 places, then when the value of radius is changed, calculateArea() will be called 2*3=6 times. So if this was computing something more complex it would really be an issue.

 We can optimize this by listening the radius for change, compute the area based on the new radius value and assign the result to the scope. That way the computation will be done only once.
Of course if we include
<div>Area {{area}}</div>
 again the 3 watches will cause the evaluation of the area model value, but since it is assigned to the scope it will be much faster.

The book Mastering Web Application Development with AngularJS explains really well how data binding works, how the DOM and model are synchronized, what is scope.$apply, how $watches are registered and how the $digest cycle executes. It also has a nice step by step explanation of how the 2-way data binding is achieved in Angular. A must-read book!

Tuesday, December 10, 2013

JavaScript on conferences

Recently two big conferences were held in Sofia - jQuery Bulgaria and Java2Days. Luckily I was able to attend both and I really liked both of them.

What was interesting about those events was that one was free and it was in Saturday, while the other was paid and during two workdays. One was targeting JavaScript developers, while the other Java developers. One was about JavaScript and the other ... well JavaScript was hot topic :-) At one point I even though I was on JavaScript2Days, which by the way would be awesome to have!
Although more targeted for Java developers, on Java2Days there were topics like "Automate your JavaScript development in your Web App" by Mite Mitreski, where he covered tools like Yeoman (and it's set) and Karma, that was quite nice and made some things clear to me. Another talk by Andrew Lombardi was "Real Time with Websockets", where he created a node.js server and a simple HTML client, that used Websockets to exchange data. And of-course the framework that was mentioned in nearly all JavaScript sessions on both events - AngularJS, mainly covered in "Web apps: a different angle – Web applications in Java with spring data, spring data rest and Angular.js" by Ioan Eugen Stan, "AngularJS for Spring Developers" by Sergi Almar and "AngularJS - a radically different way of building Single Page Apps" by Jivko Petiov.

Some interesting talks that I attended at the jQuery Bulgaria event include "Best Practices for Developing Modern Web UIs with JavaScript" by Angel Todorov, which if I had watched an year ago could have saved me a lot of time in filling the gap that I had from the time I had stayed away from HTML/JavaScript. "Things I learned from the jQuery source" was very interesting, where Haralan Dobrev opened up a text editor and started coding the presentation live. If I am to make a dev presentation soon, I would definitely consider doing it in a text editor!
Ivelin Andreev opened my eyes on some security issues and workarounds for the same origin policy, in his presentation "Going Beyond Cross Domain Boundaries".

So as I mentioned in a previous post and if I may quote this blog "JavaScript is the de-facto standard: if you want to create something that just about everybody on the planet can see and use, you must choose JavaScript as your programming language". Just the fact that it was so much discussed on a event like Java2Days should make you think "hey, there really is something going on with JS that I should watch closely".

Interesting times!

Tuesday, December 3, 2013

Running "grunt server" in development

Some time ago @jvassev pointed me to Yeoman, a great set of tools that really improved my productivity when developing JavaScript apps. One of the tools it wraps is Grunt, it is used to automate common tasks when developing a project, like running a preview of the project, building it and testing it.

I am working on a project, where we are running the "grunt server" task that starts a static server so we can preview and test out changes of the front end code. Together with that it can run livereload that will listen to file changes, so that when a file is changed, the browser is automatically refreshed, or also compass server that will compile all your sass files, and others.

In order to develop in an environment as close as the production environment, you should query your back-end API. This can be done with this neat grunt plugin, that, https://github.com/drewzboto/grunt-connect-proxy . So basically if you run "grunt server" locally, then it can serve you the static files, and request to the back-end API can be proxied to your web server.

You can check this post that explains more.