I’ve seen some developers quite shy about AngularJS when confronted to all the magical powers; don’t be afraid, AngularJS indeed introduces several new concepts but you can get them in just a few weeks of practice… The Google team is working hard to lower the Angular entry barrier and to make everything as simple as possible for developers.
AngularJS is a new disruptive innovation in the Javascript frameworks world and it prefigures the future of web browsers : templates, data-binding, web components…
In this post i’ll give some advices for the AngularJS newbies and share with you the best pointers to learn and understand the core concepts quickly.
First, to understand AngularJS you of course need to know a bit of Javascript. If you’re not comfortable enough yet, pick a free book on JSbooks and practice.
If you have a jQuery background, you absolutely need to read this in-depth Stack Overflow answer : How to think in AngularJS if i have a jQuery background. Just imagine the productivity boost you’ll get when you won’t need to maintain the DOM anymore :)
To sum up key features of AngularJS :
Templates : Your templates lives right in the DOM. Forget mustache, handlebars, hogan…
Two-way data-binding : Your javascript data automagically updates your DOM and vice-versa.
Routing : Define routes, associate templates and controller in just a few lines.
Forms : Many helpers to help dealing with forms, one of the worst webdevs nightmare.
Directives : Encapsulates templates and code in reusable components easily.
Testability : AngularJS was designed in a way your web app can be fully testable.
Animation : Easily animate elements and views.
Here are 5 steps to boost your AngularJS skills right now :
So today was the opening of the 2013 GoogleIO developer conference in San Francisco and the Googlers announced a insanely crazy amount of new projects/services/features in just the first few hours, which is very exciting for every web/android developer. The next three days will be very busy, with a lot of focus on Chrome, Android and Google+.
Though, we don’t have new Nexus devices, no Android 4.3, and no Javascript AppEngine runtime. So huge fail on my previous predictions.
The keynote started with a big fail demo effect happened in the very first demo about Android multiplayer gaming when demoing a new Google Cloud Messaging feature, quite embarassing, but then everything ran smoothly.
Here’s a little recap of the most important things announced just during the 3 hours keynote :
Google cloud messaging : can now be used in a bidirectionnal way, and apps can now also store data in the cloud and sync it across devices (scores, leaderboards…).
Google Game Services platform to help game developers with new APIs
Samsung Galaxy S4 will be available in June on Google Play with standard Android build and unlocked bootloader ! 649$ though but without that ugly, messy, shitty Samsung overlay.
Android studio to replace Eclipse nightmare, finally ! good move !
WebP and VP9 royalty-free compression standards for images and videos to increase speed specially on mobile devices.
Google provides a free (deactivable) proxy for Android to improve speed based on this codecs.
New payment autocomplete API will help process payments quickly on websites, specially useful on mobile (2 clicks payments)
Google will finally release a rock solid UI framework based on web components standards : polymer-project.org . I wonder how it will fit with AngularJS.
V8 will integrate asm.js to improve Javascript performance.
Our first real life experiment with AngularJS is a mobile and touch-friendly carousel directive.
As this project shed some lights on various AngularJS aspects, we’d like to share it with you;
The full demo+code is available here : http://blog.revolunet.com/angular-carousel
The goal is to transform any ng-repeat directive into a carousel, just by adding the rn-carousel attribute to its ul container. The directive take care of the dirty work for you, without any jQuery.
Here’s a very basic example of a Youtube API call, with the data displayed in a regular Angular template; We just add a rn-carousel attribute to the ul element to ask a carousel :)
This rn-carousel directive is responsible of :
1) wrapping the real ul/li in a carousel container and add CSS classes
We first wrap the original ul block in an outer div using JQlite wraps method during the directive link phase. This cannot be doneduring the compile phase as it would lead to an infinite recursion loop. (AngularJS will wrap again an again as the original directive stays untouched).
Then we add some CSS classes and an unique carousel identifier class so we can target that instance easily later.
The CSS makes the ul/li block appears as a single horizontal line composed of many li blocks, so its very easy to slide the blocks horizontally.
2) watching the ng-repeat expression
Because we want to monitor precisely the items in our carousel, and we want to be able to dynamically add/remove items, we need to extract and watch the original ng-repeat expression. We can then watch that expression and then be notified when its updated. This is useful to know how many slides we have and update our indicators accordingly for example.
This extraction is done by literally parsing the ng-repeat expression in a generic way, using the generated normalized comment node. Credits goes to @bennadel for this awesome trick.
Update : I ended up with just extracting the li ng-repeat attribute during the compile phase which is much less overhead.
3) binding touch and click events
Like most directives, we bind events in the linking phase. We just take care of binding both touch and mouse events.
When we detect a touchstart we just store the initial event position. On touchemove we update the horizontal offset and move the whole ul accordingly using CSS. Then on touchend, we detect the desired position (prev or next) and dynamically add CSS styles and classes to move the slides accordingly, or restore the current position in some cases.
The slide movement is made thanks to the CSS transition and translate3d properties to force CSS 3D transforms and thus animate the slides using the GPU which make the movement much more smooth especially on mobile devices.
12345678
// the offset value is simply : desiredSlideIndex * slideWidthcarousel.css({'-webkit-transform':'translate3d('+offset+'px,0,0)','-moz-transform':'translate3d('+offset+'px,0,0)','-ms-transform':'translate3d('+offset+'px,0,0)','-o-transform':'translate3d('+offset+'px,0,0)','transform':'translate3d('+offset+'px,0,0)'});
5) adding an indicator to our carousel
As we already watch the ng-repeat expression, we track the number of slides in the carousel and so its quite easy to add data-bound indicators to our carousel. You can enable these by adding a rn-carousel-indicator="true" attribute on your ul.
The indicators are produced by the rn-carousel-indicators directive, completely decoupled, during the linking phase. For the directive to be executed, we compile it through the $compile service before appending it to our container.
It just takes items and index attributes that will be injected in an isolated scope to produce the indicators and set the CSS classes.
1234567891011
// enable carousel indicatorvarshowIndicator=(iAttrs['rnCarouselIndicator']==='true');if(showIndicator){// as the HTML contains a directive, we need to $compile it// before appending it to our containervarindicator=$compile("<div id='"+carouselId+"-indicator' "+" index='carouselIndex' items='carouselItems' rn-carousel-indicators "+" class='rn-carousel-indicator'></div>")(scope);container.append(indicator);}
6) offer a two-way data binding for the active slide index
The carousel current index position can be data-bound to an optional rn-carousel-index attribute if provided. This allows you to display the carousel position somewhere else, add custom controls/indicators, initialise to a different slide…
12345678910111213141516171819202122
// set initial position at first slidescope.carouselIndex=0;if(iAttrs.rnCarouselIndex){// if a binding attribute is present, use it.varactiveModel=$parse(iAttrs['rnCarouselIndex']);scope.$watch('carouselIndex',function(newValue){// when the carousel internal index changes, update the modelactiveModel.assign(scope.$parent,newValue);});scope.$parent.$watch($parse(iAttrs.rnCarouselIndex),function(newValue){// when the model change, update the local position// this is also useful for the initial positionscope.carouselIndex=newValue;updateSlidePosition();});}else{// if no index attribute, just watch internal index and update displayscope.$watch('carouselIndex',function(newValue){updateSlidePosition();});}
The updateSlidePosition() function simply moves the ul block based on the carouselIndex value and the width of the slides. We do this with CSS transition and translate3d so this is animated and hardware accelerated.
7) tests and grunt automation
These subjects will have a dedicated article soon :)
Limitations
Only works with ul/li structure
Carousel dimensions is based on the first li detected
UPDATE : the carousel can now be buffered to improve performance with large datasets !
Easy isn’t it ?
If you have questions, suggestions, issues, pulls requests… just comment below or on Github :)
In the past few months we learned a lot of new AngularJS stuff. Here is a first bunch of tricks, please comment and help us improve theses exemples if your tricks are even more awesome :)
The official documentation is not crystal clear at first approach but it documents most of what you need to understand: http://docs.angularjs.org/guide/directive. So read it. And again. And again.
Watch an object or a list
If you watch a list or an object with the objectEquality parameter not set, then the $watch callback won’t be triggered if the object is only updated partially. Setting it to true will trigger it on any modification; this has performance impact so use carefully.
1234
// the last `true` means compare by value and not by ref, useful for nested objects :)$scope.$watch('myConfig',function(newValue,oldValue){console.log('myConfig changed !',newValue);},true)
Two way data binding attribute without explicit scope declaration.
Sometimes you need to access a directive attribute with a two-way data binding without declaring it explicitely in the directive scope configuration. You can do this using the $parse service.
If your directive scope is isolated (scope: {}) you have to use scope.$parent instead of scope.
Use a callback function with arguments in your directive
To call a function defined in one of your attribute, declare it in the scope with &.
If you need to pass arguments, you must execute the callback using an object form for the arguments. AngularJS then call the function with your arguments in the correct order comparing your object and the callback declaration.
The following example also demonstrates how to watch multiples values at once.
Custom transclusion
This example shows how to define a custom transclusion function and modify its scope.
Announcer/Notifier pattern
If you need to listen to DOM objects creation/deletion, you can simply create a ‘notifier’ directive and an ‘announcer’ directive that you’ll add to the objects you want to monitor. That directive will announce new instances creation (link called) and destruction (scope.$destroy called).
It can be useful if you want to monitor arbitrary objects lifecycles, for example a ng-repeat. The ‘announcement’ can be made via events, or better, using a custom notifier controller. All credits goes to @garanajpr for the ideas.
AngularJS team recently added the very expected animation feature to their framework. You can have a great overview with the Miško Hevery introduction video and a complete overview article at the great Year of Moo blog.
From now (AngularJS 1.1.4), you can easily animate any directive, just by adding an ng-animate attribute and defining the animation CSS class.
UPDATE : AngularJS team fixed the following problem in the last 1.1.5 release. The ng-animate will now be evaulated on each animation, Yahoo :)
As a mobile web developer, the first thing that come to mind is animating your mobile applications views. Its quite easy to add slide-in effects with the current routing system :
As you can see, the code is very simple code and the animation is always the same (appear from right). But typically, if you open a screen in your mobile application, and there is a ‘Back’ button, the user expects the slide animation to be reversed when he touches it. If you don’t do this, you expose your users to an unexpected behaviour, and an akward #WTF moment.
With the actual AngularJS implementation, there is a problem with the ng-view directive, which is heavily used for the AngularJS routing : it doesn’t handle dynamic ng-animate directive at all, despite what says the doc. You can only set the enter and leave animation once, because these are set at linking time in case of the ng-view. And thus, you can only have one pre-defined enter and leave animation for your application view and for the whole application lifecycle.
There are a fewissues opened and we can hope the team must be working on it and that should be resolved some day.
But an easy workaround to achieve this is to act on the enter and leave CSS classes themselves directly. Instead of changing the CSS classes names at the DOM level, one could update the CSS classes definitions to achieve the same result without even touching the DOM. The ng-view directive still has the same enter and leave CSS classes names and instead we change theses classes definition, and thus the animation direction.
There are several ways to do this. We could dynamically add a stylesheet to the document, or change the stylesheet source using ng-src attribute but this wouldn’t be very efficient due to multiple downloads of the ressource.
But, as we are AngularJS powered, we could simply bind a style tag to a javascript variable so it can be updated dynamically like any other DOM element.
Here’s how we’ve done bi-directionnal animations for the ng-view. Note the usage of the ng-bind-html-unsafe that take cares of not escaping the CSS output and the use of transition and transform CSS properties to force the use of GPU and improve the animation smoothness, especially on mobile devices.
Another clever solution, as pointed out by Andrej in the comments below, is to simply wrap the ng-view in another div that have a dynamic class name, which could change when we need to change the animation direction, like LR then RL. This way we just need to update that classname and the CSS will pick the good one.
When you switch to Octopress for blogging there are a very few things to know :
Command line
1234567891011121314
# create a new postrake new_post['Title of the post']# create a new page rake new_page['Title of the page']# preview your workrake preview
# publish itrake generate && rake deploy
# commit and backup(automatic message)git commit -am "`date`"&& git push origin source
Creating a post
You can create a post just by adding a .markdown file in the source/_posts folder and preview it with rake preview. The name of the file will be your post url so use an appropriate slugified name.
You must add some metas at the top of the file :
123456789
---
layout: post
title: My Awesome article.
date: 2013-05-1 00:00
categories: news technology web
author: Super Man
comments: truepublished: false---
If you set published: false, your posts will only be visible in preview mode.
Publish
When ready, just use rake generate && rake deploy to publish it :)
Here’s a micro script to simplify the publish process, jsut put it in the blog root folder :
12345
#!/bin/sh# push.sh : publish & commit with a single commandgit add sourcegit commit -am "`date`"&& git push origin sourcerake generate && rake deploy
Our good old WordPress blog has been shutdown since a few months and now its time for us to start a brand new blogging adventure with OctoPress. As expected, we’ll talk about Web technologies, Rich web applications, Javascript, Python and Phonegap among others.
We’ve got so many stories to tell, so many tips to share and so much code to dissect, so stay tuned.