Saturday, September 14, 2013

Fast & Furious

I was impressed, my initial Angular words were "I think I love it".
I went over Angular's home page watching the videos and going over the features, coding some samples and I thought to my self, OK, it's about time that someone will come up with such framework. Routing, templates, data binding, the great directives, testing. You get everything you need for building your HTML5 application.
My first, not so complected application, was created in no time.

And then I got hit...

I was coding my directive using a simple template file and then I got an error:
Error: Syntax error, unrecognized expression: <div class="wrapper" style="height: {{dheight}}px; width: {{dwidth}}px;">
at Function.Sizzle.error (http://localhost:8089/lib/jquery.js:4421:19)
    at tokenize (http://localhost:8089/lib/jquery.js:5076:28)
    at select (http://localhost:8089/lib/jquery.js:5460:25)
    at Function.Sizzle (http://localhost:8089/lib/jquery.js:3998:20)
    at jQuery.fn.extend.find (http://localhost:8089/lib/jquery.js:5576:24)
    at jQuery.fn.jQuery.init (http://localhost:8089/lib/jquery.js:196:54)
    at jQuery (http://localhost:8089/lib/jquery.js:62:20)
    at compile (http://localhost:8089/lib/angular-1.0.5.js:3831:25)
    at link (http://localhost:8089/directive/WrapperWidget.js:89:45)
    at nodeLinkFn (http://localhost:8089/lib/angular-1.0.5.js:4344:13) <wrapper class="ng-isolate-scope ng-scope" label="Dynamic Template Content" refobject="wrapperdemo" style="float: left;"> angular-1.0.5.js:5687
</wrapper></div>
Oh well, probably nothing much. After a half hour of trying to figure out what I did wrong. I got to a point that I said (again) to myself. Maybe the template file I'm using has unwanted empty first line. That was the problem? Oh boy, someone forgot to trim.

And then I got another hit...

While creating my application I needed to add an event listener to the DOM elements programmatically, that should be an easy task.
But how can I do that if I have no way to tell when the DOM was rendered. you can read about it in here.

As a workaround to that hole in the lifecycle, someone suggested to use evalAsync method, but by doing that no guarantees as to when the expression will be executed.

I worked that out using MutationObserver. Not the ultimate solution but it works.

It's looks simple from a distance

The above hits were just some examples out of some others that I bumped while using Angular.

AngularJs is a good framework overall, but I already experienced working with similar projects that it was very simple at first, but as you went dipper you needed to hit your head against the wall a few times. And in my opinion this is Angular case.


Sharing my stuff

While coding my application I created couple of interesting directives that I wanted to share with you.
I created a sample code application just for demonstrating the below stuff. You can find the code @github

RequireJS

When I just started to code with Angular I didn't feel a need for RequireJs integration in my project since coding with Angular your project get pretty much modularized. But after a while I guess that my project got bigger and I hate to import so many JavaScript files.

RequireJS integration was almost straight forward, except the angular handler itself. When require an angular module use other variable name, such as 'ang'. In my sample project you can see requirejs in action.


First, create an requirejs configuration
require.config({
    baseUrl:".",

    paths:{
...

Then, call the require stuff
require([
    "jquery",
    "jqueryui",
    "angular",
    "app"

], function ($, $ui, ang, app) {
    app.initialize();
});

From that point, just define your modules and use them wherever you need
define(["jquery"], function ($) {

    return {
        init: function (app) {

            app.controllers.Main = function ($scope, $routeParams) {

...

Template Loader Directive

Using the ng-view with routing was very useful, but if you need to load inner dynamic content? At least one of the ways could be, to create a directive for dynamic template loading.

All you need to do is using the directive, like so:

<dtemplate  src="{{navigateTo}}" />

Change the scope property's 'navigateTo' value to other exiting template and you are good to go.

One of the cons of using that kind of directive is that you have to reflect any property you need to pass to your template thru the directive's attributes.


WrapperWidget Directive

There were a lot of cases where I found myself repeating the same pieces of code that decorates different pieces of content.

For example, you have a person entity details that changes from one to another but the person decoration stays the same. For that I used the Wrapper Widget directive like so:

<wrapper refobject="person" style="float:left" >
  <div style= "padding: 10px;" >
    <strong> {{person.name}} </strong>
    <div style="padding: 5px"> {{person.description}} </div>
  </div>
</wrapper>

The wrapper decoration template will stay the same with minor modification that can be externalized. But the person details will be set dynamically.