Sharing Top Content from the Angular-sphere.

Transition from jQuery to AngularJS

0

Prerequisite knowledge

jQuery and CSS

You need to familiar with jQuery to take full advantage of this article. For example, the following line of code should be intuitive to you:

Furthermore, you should be able to explain:

  • The difference between .filter() and .find()
  • ‘this’ in $.each() function, and in jQuery event handler
  • $.fn

Angularjs

You should be able to understand basic angular example below. Note: <html>, <head> are not included in below example

Try this code here.

1. Overall Picture

jQuery knowledge tree

jQuery, at the beginning, was designed to unify DOM manipulation across all browsers. Its motto is “Select something, and then do something with it”. Here is a knowledge map to index key concepts of jQuery.

jquery flow chart

Philosophically, you can say all tasks in browser is “doing something” with selected DOM, and all the computer code is manipulating the data, but the difference is level of difficulty and maintainability.

Angularjs knowledge tree

Angularjs on the other hand is quite different animal. They both use javascript, but the purpose are different. jQuery is for DOM manipulation, though it can be a bit complex, whereas Angularjs is for structuring a whole single page web application. The purpose is different, therefore it introduces many more dimensions of concepts, just as society and economy grows bigger, more laws are introduced to govern the intellectual property, Internet, and how individuals contract with another. Here is the concept dimensions of Angularjs (1.x).

angularjs flow chart

Given many new concepts and APIs introduced by Angularjs, how you use it is quite different from how you use jQuery. To successfully transition from jQuery world to Angularjs world, you need to 1) get crystal clear of the concepts tree above, and 2) make clear distinction between the overlapping areas between jQuery and Angularjs.

2. Declarative way of binding event and encapsulating logic

jQuery event binding

In jQuery and pure Javascript world, one good practice is to separate Javascript, HTML, and CSS in different files.

<!-- bad code for binding event handler -->

<button onclick="alert()">a button</button>

Above code is bad because it put javascript in the HTML tag, resulting poor maintenance. In jQuery, you should bind event like this:

Angularjs event binding

In Angularjs, you are required to wire event and its handler inside HTML tag as attribute declaration. That’s why they call it declarative way to binding event.

You can try it here.

I personally find it very not acceptable since it is violating previous best practice. After many struggles, I realized I had to let go of old way and don’t get too attached to it. As JFK always likes to say “Those who only focused past or present, will sure to miss the future”.

In real project, you are very likely to see even 10 attributes put into one HTML tag, e.g.:

<button

popover-placement="{{placement.selected}}"

uib-popover="On the {{placement.selected}}"

type="button"

class="btn btn-default" >

    Popover {{placement.selected}}

</button>

You can find above code explanation here.

There is nothing wrong with it. The key reason is event binding and other behaviors in general is dependent on DOM structure (aka: HTML template), you can link HTML to event handler either in javascript code by jquery selector way, or use Angular declarative way by putting the linkage in HTML tag in template, and then focus only on the logic in Angular code. This is the No.1 difference between Anguary and jQuery.

Angular directive – code encapsulation and reuse

The declarative way is not only limited to event binding, but also expanded to logic abstraction.

You can see it working here.

The above code use a build-in angular directive “ng-if”, which shows the element if scope variable “switch1” is true, and hide the element if “switch1” is false.  Then $interval is used to toggle the variable every one second. Since ng-if is bound to scope variable switch1, if the switch1 changes, ng-if will update accordingly. How it works involves the concepts of data binding, and digest cycle, which will cover later.

Now, imagine if you use jQuery to implement the above flashing green light logic.

You can see working here.

Wow, it looks much simpler. However, if you want to find out the current status of the light in jQuery code, there is no variable to tell you and you have to query the DOM to find out. In a large web application, leaving every status of the app at DOM is very not good, because it leaves your data dependent on the representation of the HTML. Avoid this at all cost if you working on real application.

ng-if directive encapsulates the whole set of activities of updating DOM based on variable value in a declarative html attribute. You can develop any directive like this one based on your need. This is the angular way.

3. Built in Angularjs directives make mundane work easy

Right now it is the time to understand built-in Angularjs directives. Please read this article to learn what is Angular directive. In programming field or any other fields, figuring out what it is the most important thing. There are about 60 of built-in directives. If you are serious about learning Angularjs, you should write one example for each directives and it will take you about 3 to 7 days.

You can delay that work, but it is still important to understand several of them before moving forward. What are these directives have in common is that they update DOM based on the variable in controller (controller will be covered in later in MVC). Change the DOM according to a variable value. That’s the concept.

Here are the list of directives that you should master:

ngRepeat, ngSwitch, ngClass , ngIf, ngInclude, ngModel, ngShow

Understanding the above built-in directives is not negotiable. Please don’t move forward if you have trouble understanding them. Software development skills are built on layers upon layers of knowledge. If you miss one layer, then the layer on top of it will look like alien language for you.


4. MVC doesn’t exist in jQuery

MVC means (Model View Controller) and is the de facto pattern for framework designed for complex single page web application. MVC concept doesn’t exist in jQuery. From all my experience, if jQuery plugin becomes complex, it will develop some kind of MVC structure to manage the complexity, for example this jQuery atWho plugin.

Here is an example of MVC:

transactions example

Views is organized in tree structure

In Angularjs, you can largely say view is HTML template. From the above picture, you can see there are high degree of similarities among view1, view2, view3 and view4. The similarities are 1) all represent a financial account, 2) all display title and sub-categories below main title with an indent, 3) main title (account name) can be clicked to toggle the display of sub-categories.

view5 contains view1 to view4. It is a tree structure.

---------------------

|  view5            |

|     ----> view1 |

|     ----> view2 |

|     ----> view3 |

|     ----> view4 |

--------------------

DOM is also a tree and so is Angular View. How do you implement this feature in Angularjs MVC structure? Let’s take baby step.

<view5>

 <view1></view1>

 <view2></view2>

 <view3></view3>

 <view4></view4>

</view5>

Well, all complex things start have small origin. The above code will not work yet, but it is a very good starting point. Because we need to be semantic (giving meaningful name for variable), let’s give views meaning names. Here is version 2:

<account-summary>

 <account name="Assets"></account>

 <account name="Receivables"></account>

 <account name="Debts"></account>

 <account name="Equity"></account>

</account-summary>

Since view1 to view4 has the same behavior, we can abstract them into one angular directive and pass the account name as variable. We need to define <account-summary> and <account> in Angularjs code before above code can work.

MVC in <account> directive

If at this moment, you don’t understand what is Angular directive, which is quite normal, please take some time to review directive concept from official document.

Here is the account directive looks like, version 3:


Here is the code for account directive:

The Model (M) of account directive is the variable ‘subAccountsOpen’ attached on $scope. There will be more model on $scope later. The View (V) of account directive is the whole html template. The Controller the account directive is controller function in returned the directive definition object.

Only handle event in directive controller, never in controller definition

angular.module('myApp', []).controller('ctrl1', function ($scope) {
  // 1. never bind event handler here,
  // 2. never alter DOM structure here
});

Above is a controller definition, don’t alter DOM or attach event handler there because if you do, you will violate the principle of MVC, making code not maintainable. The things you are allowed to do in controller definition function are:

  1. define/update models
  2. Define event handling function, but not attaching handler.

Attaching handler should only be done in the view template or in directive.

Here is template(View) after attaching event handler, version 4:

Account directive definition:

You can see the working code here.

Thinking about the data (Model) for account directive

Data include user data, such as account name and balance, and controlling data, such as subAccountsOpen to tell if sub accounts area is visible. Generally speaking, Model can be an object which includes some behaviors for the data, e.g. saving, retrieving, validating, and basic calculation, etc.

<account> directive should be able to show any account info, therefore the account data (model) should be passed in as parameter. How do you achieve that? One way to do it is putting model at parent scope(scope is also a tree structure, will cover it later), and pass it in as parameter to account directive.

Template file after adding model to parent scope, version 5:

js file after adding model data:

Scope is also an important concept to transition from jQuery to Angularjs. It’s a organized in a tree structure. Later chapter will explain it thoroughly.

scope: {account: ‘=name’} This line of code is used to take attribute name ‘name’, and pass the value assetAccount from outer scope to variable ‘account’ inside directive scope. Please refer this official document for detail explanation.

You can see a working version here.

Organize all modal data in parent scope

Right now everything works now, but all account directive display the same account data, because we pass the same account model data to the account directive. Let’s make it more real by providing more account data and give it some CSS to make look like final product.

Template file, version 6:

Javascript file:

You can find the working version here.

DRY (Don’t Repeat Yourself)

The way we provide model data is by manually assign it on parent scope, and then manually add an account directive in the template for the its account model. If one more account needed, we have to update the template file by adding one more account directive. It is one problem, because we are unnecessarily repeating ourselves. There is an opportunity for higher level of abstraction.

The other problem is, in reality, we are more likely to get an array of accounts from REST API. So the account data model is an array of JSON, not one account JSON object.

To address the above two problem, we can use ng-repeat to initialize the account model, which is an array on parent scope.

We only need to change <body> tag in template to the following, version 7:

Then update data model to be an array on parent scope:

Here is how it looks like now:

better transaction example

You can see a working version here.

jQuery doesn’t have MVC concept. In the above step-by-step example, you can see data array in parent scope is the Model, the account directive template is the View, and the controller in directive is Controller. All complex things have simple origin. This is the way you use Angularjs to start small and gradually evolve into a full blown web application.

Transition from jQuery to Angularjs (part 2)

There are many more concepts that need to be understood to transition to Angular world. Here are the topics that will be covered in Part 2.

  1. Dependency Injection
  2. Understand $scope which doesn’t exist in jquery
  3. Understand 2-way data binding
  4. Digestion cycle
  5. There is a compiler in Angularjs
  6. Modularity in jQuery and Angular (Plugins vs. Directives)
  7. Angular coding best practice

Leave A Reply

Your email address will not be published.