There are couple of links explaining AngularJS to jQuery developers and my effort also goes to do the same. This post is dedicated to all the jQuery developers who wish to know AngularJS before they dive in. I myself worked on jQuery since a very long time and literally its hard to switch to something which is radically different and way cooler than jQuery (sorry, darling!).
Document is Ready?
We all know about $(document).ready()
or $(window).load()
methods to setup a safe wrapper around the code to make sure that everything runs after the DOM is loaded.
Also, you might have used literal styled javascript with jQuery:
var App = {
run: function() {
var bootstrapper = 'You have successfully bootstrapped jQuery';
$('div.alert').html(bootstrapper);
}
};
// Finally I'll call the main method
$(document).ready(function() {
App.run();
});
Do not panick! Angular itself provides the manual bootstrapping the same way. Angular advocates modularity so that every piece of an application should have its own module and there is a main module that holds rest of the modules together. The subsequent code defines the main module (similar to jQuery example above) and run() block is the built-in (sort of) main method in Angular which runs once the application is bootstrapped.
// Define a module, App
var App = angular.module('App', []);
// Built-in run method
App.run(function($rootScope) {
$rootScope.bootstrapper = 'You have successfully bootstrapped AngularJS';
});
// Finally bootstrap angular manually
angular.element(document).ready(function() {
angular.bootstrap(document, ['App']);
// Target an element instead
// angular.bootstrap(jQuery('body'), ['App']);
});
The one thing to notice here is $rootScope
– which is a global variable you can bind properties to that can be injected in other modules for further use.
Finally we’ll use angular’s templating syntax {{ }}
to declaratively place data into the markup instead of grabbing the element explicitly like jQuery. Can you see?
<div class="alert alert-success">{{bootstrapper}}</div>
In case you are not a fan (like me) of manual bootstrapping, you can make it automatic as well by setting ng-app directive on any element such as html, body etc. Angular looks for an element having ng-app
on it and uses it as a target during bootstrapping. Now you do not need angular.element(document).ready()
block as defined above.
<html ng-app="App">
XHR
AJAX is the second most important thing people use jQuery for. jQuery provides different methods to fire up an XHR call.
In angular, there is $http
service which is a wrapper around the browser’s XMLHttpRequest object that returns promises .then()
, .success()
, and .error()
based on the request was successful or failed.
The only difference is that you have to manually inject it into the module definition. Suppose I want it inside the run() block we’d seen before:
App.run(function($rootScope, $http) {
$http.get('foobar.php').success(function(data, status) {
// I succedded
}).error(function(data, status) {
// I failed
});
});
Do not touch the DOM
jQuery was made to do so, Angular is not!
In AngularJS, try to avoid touching DOM implicitly as much as possible so that you can fully leverage the 2-way data binding between your data and the DOM. We are going on journey to build a process order page using following directives.
In jQuery, .val()
is a setter/getter method to interact with form controls which was quite amazing but it gets worst when you want to show the value elsewhere instantly, means we had to bind keypress events on the input control that will update the DOM as expected. But its too much effort as well as code for such a small task.
Angular provides a neat directive to rule them all. Always use ng-model
in order to read values out of form controls. You do not have to manually select an element to set/get its value – Just play with plain old javascript object/array.
<input type="text" ng-model="name">
App.run(function($rootScope) {
// setting the default value for the input
$rootScope.name = 'AngularJS';
// this will return the existing value of the input
// console.log($rootScope.name);
});
Use to lay out options based on model for select element. Know more about it.
App.run(function($rootScope) {
$rootScope.cities = [
{id: 'NM', name: 'Navi Mumbai'},
{id: 'PN', name: 'Pune'}
];
});
<select ng-model="city" ng-options="c.name for c in cities"></select>
Toggle CSS classes based on expression. This is a very common thing in jQuery:
if (same) {
$('small').removeClass('strike');
} else {
$('small').addClass('strike');
}
In angular, you can use ng-class directive to apply CSS classes conditionally. If same
is boolean true then apply strike
class. Otherwise remove it.
<small ng-class="{'strike': !same}">same as billing</small>
Similar to ng-class, you can disable/enable form controls using ng-disabled directive.
In jQuery,
$('[ng-model="shipping_name"]').prop('disabled', same);
In angular,
<input ng-disabled="same"
type="text"
ng-model="shipping_name"
placeholder="Full Name">
You may want to reflect your billing address as shipping address instantly.
In jQuery,
<input onkeypress="$('[ng-model="shipping_name"]').val($('[ng-model="billing_name"]').val());"
type="text"
ng-model="billing_name">
In Angular,
<input ng-change="reflect()" type="text" ng-model="billing_name">
$rootScope.reflect = function() {
$rootScope.shipping_name = $rootScope.billing_name;
$rootScope.shipping_address = $rootScope.billing_address;
$rootScope.shipping_city = $rootScope.billing_city;
};
In jQuery,
$('div.btn-primary').click(function() {
processed = true;
});
In Angular,
<button class='btn btn-primary' ng-click="processed = true">Process Order</button>
This is again very common thing in jQuery to show/hide elements based on conditions.
In jQuery,
if (processed) {
$('div.alert').show();
} else {
$('div.alert').hide();
}
In Angular,
<div class="alert alert-success" ng-hide='!processed'>
<b>Well done!</b> We've successfully processed the order.
</div>
Here is the Final Demo of our Process Order form using all above directives.
Loading partials
Many of us often create a separate header and footer partials to be injected into many pages instead of repeating all over again.
In jQuery,
<body>
<div id='header'></div>
<script type="text/javascript">
$('#header').load('header.html');
</script>
<!-- Body -->
<div id='footer'></div>
<script type="text/javascript">
$('#footer').load('footer.html');
</script>
</body>
In Angular, ng-include works similar to jquery.load but also allows to compile and include an external HTML fragment. Do not forget to wrap your html fragment in single quotes as I’ve already wasted an hour to figure that out 😦
<body>
<div ng-include="'header.html'"></div>
<!-- Body -->
<div ng-include="'footer.html'"></div>
</body>
History – page navigation
Take an example of a simple addressbook application that contains 3 links shown below and div.abPanel
is the place where you would wish to load the appropriate template.
<div class='cell abLinks'>
<a href='javascript:void(0);' id='addNewContact'>Add New Contact</a><br />
<a href='javascript:void(0);' id='listContacts'>List all Contact</a><br />
<a href='javascript:void(0);' id='searchContacts'>Search any Contact</a><br />
</div>
<div class='cell abPanel'>Loading... Please Wait.</div>
In jQuery, you would probably do this.
$('#addNewContact').click(function () {
$('div.abPanel').load('add_new_contact.html', function () {
// do all DOM manipulations or event bindings here
});
});
In Angular, we’ll use awesome $routeProvider
service without writing much boilerplate code. This simply loads a template based on hash.
App.config(function ($routeProvider) {
$routeProvider
.when('/add', { templateUrl: 'partials/add.html' })
.when('/list', { templateUrl: 'partials/list.html' })
.when('/search', { templateUrl: 'partials/search.html' })
.otherwise({
redirectTo: '/add'
});
});
And finally change above links a little bit to:
<div class='cell abLinks'>
<a href='#/add'>Add New Contact</a><br />
<a href='#/list'>List all Contact</a><br />
<a href='#/search'>Search any Contact</a><br />
</div>
<div ng-view>Loading... Please Wait.</div>
The one thing to notice here is ng-view directive that lets your render the template of the current route automagically.
Animation
The .animate()
method allows us to create animation effects in jQuery. In order to fade out the process order page while hiding, we can write something like this:
$('div.row').animate({opacity: 0}, 1000);
In angular(version 1.1.4+), ng-animate allows us to control the animation either using CSS or JS. This directive can gel up with other directives like ng-show/ng-hide, ng-view, ng-include, ng-switch, etc.
We’ll simply add it to our div.alert
which takes processed
CSS class as an option.
<div class="alert alert-success" ng-show='processed' ng-animate="'processed'">
<b>Well done!</b> We've successfully processed the order.
</div>
Then we’ll define necessary CSS classes. What happens here is when div.alert
is about to be shown (means processed becomes boolean true), both processed-show and processed-show-active classes will be applied which will help fade in the element for 0.5 seconds and later be removed. And display property sets to block.
.processed-show {
-webkit-transition:all linear 0.5s;
-moz-transition:all linear 0.5s;
-ms-transition:all linear 0.5s;
-o-transition:all linear 0.5s;
transition:all linear 0.5s;
opacity:0;
}
.processed-show-active {
opacity:1;
}
We can use similar css while hiding the element but opacity will change from 100% to 0%.
.processed-hide {
-webkit-transition:all linear 0.5s;
-moz-transition:all linear 0.5s;
-ms-transition:all linear 0.5s;
-o-transition:all linear 0.5s;
transition:all linear 0.5s;
opacity:1;
}
.processed-hide-active {
opacity:0;
}
Check out the demo. There are more in-depth articles on yearofmoo.com and nganimate.org.
jQuery plugins
We can not live without it. A few weeks ago, I’d written an article on how to use jQuery plugin the angular way.
Custom Directives
AngularJS really shines where it lets you write custom directives also. There are hell lot of articles to get you started.
Wrap ups
I’d seen many of my colleagues struggled to get going with AngularJS and hence I’d decided to write this post. Time has come to expand the horizon. All the best.
If you found this article useful in anyway, feel free to
donate me and receive my dilettante painting as a token of appreciation for your donation.
19.030000
73.010000
Like this:
Like Loading...