Getting Started with AngularJS – The Application Module

As with all applications there has to be a starting point. Where does the application start? In AngularJS that starting point is the module.

And because a module is, well, modular, you can plug modules into each other to build the application, share components and so on.

Actually, I suppose in Angular it actually starts with a directive, that points to the module to start with, because, if you have more than one, which one do you start with?

<html ng-app="angularCatalogue">
  
</html>

The ng-app directive bootstraps the application by telling AngularJS which module contains the root of the application.

A module is defined like this:

angular.module("angularCatalogue",[])

The name of the above module is "angularCatalogue", the name of the application, which is what is placed in the ng-app directive in the html element previously.

You can also add as a second parameter to the module an array of other modules to inject. The modules don’t necessarily have to be loaded in any particular, so it is okay to refer to a module that may not exist at that point.

The module function returns a Module object, which you can then set up as you need it. Typically an application will have some sort of configuration, controllers, directives, services and so on.

Wiring up the view

In the html you will need to indicate where the view is to be placed.

You can do this via the ng-view directive, which can look like this:

<ng-view></ng-view>

or

<div ng-view></div>

Everything inside the element will be replaced with the contents of the view.

The application then needs to be told where the view is. You can configure the application module with that information, like this:

angular.module("angularCatalogue") 
    .config(["$routeProvider", function($routeProvider){
        $routeProvider.when("/",
            {
                templateUrl:"/ngapp/templates/search.html",
                controller: "productSearchController"
            });
    }]);

The config call on the module allows the module to be configured. It takes an array that consisted of the names of objects to be injected into the configuration and the function that performs the configuration.

The function has a $routeProvider injected into it. This allows routing to be set up. In the example above a route is set up from the home page of the application ("/") that inserts the given template into the element (ng-view) that designated the view and it uses the given controller.

I’ll move onto controllers in an upcoming post.

A note on the dependency injection

If you never minify you javaScript you can get away with something like this:

angular.module('myApplication')
    .config(function($routeProvider){
        ...
     });

You’ll notice that there is no array, it is just taking a function. Angular can work out from the parameter names what needs to be injected. However, if the code is minified most minifiers will alter the parameter names to save space in which case angular’s built in dependency injection framework fails because it no longer knows what to resolve things to. Minifiers do not, however, minify string literals. If the string literals exist then it will use them as to determine what gets resolved into which parameter position. The strings must match the position of their counterpart in the function parameters.

Therefore the minifier friendly version of the previous snippet becomes:

angular.module('myApplication')
    .config(['$routeProvider', function($routeProvider){
        ...
     }]);

A note on naming conventions

You can name things what you like but AngularJS has some conventions reserved for itself.

  • Its own services are prefixed with a $ (dollar). Never name your services with a dollar prefix as your code may become incompatible with future versions of angular.
  • Its own directives are prefixed with ng. Similarly to the previous convention, don’t name any of your directives with an ng prefix as it may clash with what’s in future versions of angular.
  • In javaScript everything is camel cased (the first word is all lower cased, subsequent words have the first letter capitalised), in the HTML dashes separate the words. So if you create a directive called myPersonalDirective when that directive is placed in HTML it becomes my-personal-directive.

Automatically replacing an image on an HTML page when it is not found.

The project I’m working on has just moved the image hosting to Amazon S3. Previously what happened was that we had a big folder full of images that had been uploaded from our users and that if the site needed to render an image it would check the directory for the image it needed, if it didn’t have it, it would look for the original and then resize and render that (storing the resized version in the folder so it can be found the next time). If the original couldn’t be found either it displayed a replacement image in place that was basically an image that said “There is no image available.”

That worked well enough with a small number of users but it really didn’t scale well.

Now that we’ve moved the hosting to Amazon S3 we create all the image sizes needed at the time they are initially uploaded. If we need a new size we have a tool that will go and create all the resized versions for us. The only issue that remains is that some images don’t exist for various reasons. Much of the legacy data came from systems that were installed on people’s desktops and the image data simply never got sync’ed to the central server properly.

But there is a way around this on the browser. The img tag can have an onerror attribute applied, which can then call a function which replaces the image src with a dummy image that contains the message for when there is no image.

For example:

<div>
  <img src="error.jpg" onerror="replaceImage(this, 'replacement.jpg');" title="This image is replaced on an error"/>
</div>

<script type="text/javascript">
  function replaceImage(image, replacementUrl){
    image.removeAttribute("onerror");
    image.src=replacementUrl;
  }
</script>

Although this looks a little ugly (putting in lots of onerror attributes on images) there is a lot less code to be written. When trying to achieve the same results in jQuery I eventually gave up. That’s not to say that it can’t be done, just that for pragmatic reasons I didn’t pursue it as I was spending too much time trying to get it to work.

The function does two things, first it removes the onerror because if the replacementUrl is also broken it will just recurse the call to the error handler and the browser will just slow right down. Second, it performs the actual replacement.

To see it in action there is an example page to demonstrate it.

I also tried to create a jQuery based solution to fit in with everything else. However, there were a couple of problems with a jQuery solution that were less than ideal.

  • You can’t attach an error event to the images because by the time you have done so the error event will be long past. You have to loop around all the images initially to find out which didn’t load before jQuery got a chance to get going.
  • For images that are added to the page by jQuery itself the .on does not work because delegated events, which allow you to create event handlers on elements before they are created, need the events to bubble up to a parent that did exist at the point the event handler was attached. The error event, among a small set of other events, does not bubble up. And if you attach it directly to the newly created element on the page then it will likely be too late, especially on a fast connection, as it will have already fired off the error event. You could do the same as before and check manually to see if the image loaded or not – but then the code is getting rather unwieldy and unmanageable.

In the end I found that the small bit of code that is called from the onerror attribute on each img element that needed it was more compact and didn’t require lots of extra lines of code to ensure that all the errors were corrected in the case that jQuery just didn’t get there in time.

Finally, if anyone has a solution in jQuery that does not require cluttering up the HTML, I’d like to see it

Quick guide to Geolocation in Javascript

In some modern browsers, such as Chrome and Firefox you can access the geolocation of the device. That is, where the device is physically located.

The main function for achieving this is getCurrentPosition, which doesn’t return a position as you might expect. Rather, it takes a callback (and optionally a second if you want to handle error conditions).

I’ve put together a small example page showing this, which I’ll now walk through.

In the example, when the user clicks on the button on the page it will attempt to get the physical location of the device. This may or may not work for several reasons. If it doesn’t work then the browser may not support it, or the user may refuse to give permission to the site, or the geolocation service may not be working.

This first bit of code checks to see if the browser supports the geolocation API and if it does calls the function to get the location passing in the callbacks for success and error handling.

if (navigator.geolocation) {
    navigator.geolocation.getCurrentPosition(successCallback, errorCallback);
} else {
    displayErrorMessage("The browser does not support the Geolocation API.");
}

In this small example, the successCallback simply fills various spans with the results in the position and creates a URL that links to google maps to display a pin at the coordinates.

function successCallback(position) {
    $("#latitude").html(position.coords.latitude);
    $("#longitude").html(position.coords.longitude);
    $("#accuracy").html(position.coords.accuracy);
    $("#displayMap").attr("href", "http://maps.google.com/?q=" + position.coords.latitude + "," + position.coords.longitude);
    $("#displayMap").removeClass("disabled");
}

The position has a timestamp and a set of coordinates. Since the geolocation may be cached the timestamp will give you an indication of how old the geolocation is.

The coords gives you various bits of information about the geolocation. The three values that will always be available are latitude, longitude and accuracy. The other values (such as altitude, heading and speed) may be nullable. The accuracy is in meters and can be used to gauge how good the lat/long is. The Lat/Long is in WGS84 decimal degrees.

In the event of an error, the errorCallback will receive some indication about what went wrong. The most common may be that the permission was denied, but other potential errors exist.

function errorCallback(error) {
    switch (error.code) {
        case error.PERMISSION_DENIED:
            displayErrorMessage("The request was denied. If a message seeking persmission was not displayed then check your browser settings.");
            break;
        case error.POSITION_UNAVAILABLE:
            displayErrorMessage("The position of the device could not be determined. For instance, one or more of the location providers used in the location acquisition process reported an internal error that caused the process to fail entirely.");
            break;
        case error.TIMEOUT:
            displayErrorMessage("The request to get user location timed out before the operation could complete.");
            break;
        case error.UNKNOWN_ERROR:
            displayErrorMessage("Something unexpected happened.");
            break;
    }
}

 

How your browser reacts to requests for geolocation

Your browser may give you some form of alert to indicate that the site is requesting the geolocation. Chrome, for example, displays a bar just under the omnibox

Chome asks if it is okay to use geolocation

If a site has permission to get the geolocation then the icon above will be displayed in the omnibox to the right of the URL. If not, the icon will have a red cross over it. You can click this icon to change the settings at any time.

 

Finally, if you want to read the spec in full, it is available here: http://www.w3.org/TR/geolocation-API/

Tip of the day: When other things populate elements on web pages

I work in a web team of 6 developers and we have a diverse range of skills. Some are more skilled dealing with the front end, the UI, and working with HTML, JavaScript and CSS. Others are better with the back end of things, the business logic and dealing with databases. However, there is an overlap.

One thing I noticed earlier this year when we took on our first front end specialist is that she did all sorts of things to optimise the HTML, CSS and JavaScript. It was wonderful, the application worked a lot better and looked a lot nicer. Unfortunately, some of the optimisations broke things because we’d been populating divs and spans from Ajax calls, third party code, or other bits of JavaScript. Because we knew where the data was coming from, having the full view as we did, we’d not bother commenting the HTML (and HTML comments waste bandwidth, right?)

It became obvious that something was going to need to be done if we were going to work with a specialist like this. It occurred to us that the ASP.NET rendering engine allows us to create server side comments that are not transmitted to the client. That helped keep the HTML clean on the client and allowed us to indicate to our specialist that there was a div or span that is needed (and shouldn’t be optimised away)

<div id="sizeSurchargesInfo"><%-- Populated by an AJAX Callback --%></div>

In hindsight, it seems rather obvious to simply comment the code. However, in these enlightened times it does seem unnecessarily frowned upon.

HTML5 text boxs for numbers and email addresses

In HTML5 there are a few new types of text box available that can help with mobile development. For example, on mobile devices it can be useful to have the on-screen keyboard be defaulted to display a specific configuration when it is displayed, such as the numeric keypad.

Not all browsers support these new text box types at the moment, but it seems that if the browser doesn’t understand the type assigned to an input element it renders it as a textbox anyway.

Regular Textbox

By regular text box I mean something rendered with something like the following HTML:

<input type="text />

Normally, I use SwiftKey, but for this demonstration I’ve switched to the default Android keyboard.

Keyboard for regular text box

Numeric Textbox

You can set the default keypad to numeric by specifying an input like this:

<input type="number" />

Numeric input displaying numeric keypad

Email text box

Finally, there is an email input type that configures the keyboard to display a key for “.com” and a specific key for the “@” as well as dedicated keys for the “-” and “_”  next to the space bar (at least that’s how the default Android keyboard configures itself in this mode – YMMV). The input element looks like this:

<input type="email" />

Email keyboard

Finally

If you want to try this out for yourself, there is an example available.

JsRender looping, nested objects, and conditional statements.

So far, I’ve posted a couple of very basic introductory posts on JsRender. In this post, I’ll get a little bit more into the meat of the templating language and show looping, conditional statements, and some other bits and pieces.

In the example, I’ve put together a supermarket receipt. It shows the items bought, their quantities and any savings from offers. Here’s the data:

var theReceipt =
  {
    items:
      [
        {
          description:"800g Wholemeal Bread",
          quantity:2,
          price:1.05,
          offer: {qty_needed:2, price:1.90}
        },
        {
          description:"Kellog's Fruit & Nut",
          quantity:1,
          price:2.69
        },
        {
          description:"2 litres Semi-skimmed Milk",
          quantity: 3,
          price:1.18,
          offer: {qty_needed:3, price:3.00}
        },
        {
          description:"1 litre Pineapple Juice",
          quantity:2,
          price:1.10
        }
      ],
      total: 9.79,
      saving: 0.74
  };

The data contains an array of items, each of which contains the the description, quantity, and price of each item. On some items there is also details of any offer. There is also the precomputed total and the saving that the customer has made.

Looping

In the previous post I showed what happens when the object you pass JsRender is an array. But what if the data contains an array as some sub-element? In that case you can use the for tag followed by the name of the array to indicate the start of the loop (and which array to loop over). At the end of the loop repeat the tag but with a slash in front of it (rather like HTML). For the data above, it would look like this:

{{for items}}
  Put repeating template here
{{/for}}

The tags inside the for block will be for current element. So, for the items above, I could use tags such as description, quantity, and so on.

Conditional statements

You can render parts of a template conditionally if you like. You can use the if tag to do that. Again at the end of the block, you put the slash in front of the tag to indicate its end.

{{if some_condition}}
  Put template to render if true here.
{{else some_other_condition}}
  Put template to render here if the second condition is true.
{{else}}
  Put template to render here if previous conditions are false.
{{/if}}

In the example, the test is whether the offer object exists or not. However, it acts just like an if conditional statement works in javascript. So if offer evalates to false, zero, etc. then it will be regarded as false, other values are regarded as true.

{{if offer}}
  <tr>
    <td></td>
    <td><em>{{:offer.qty_needed}} for £{{:offer.price}}</em></td>
    <td><em>save:</em></td>
    <td><em>£{{:offer.price - (quantity * price)}}</em></td>
  </tr>
{{/if}}

Nested object

In the looping section you can access the elements of each item being iterated over. The looping mechanism takes care of that for you, so when you are in the loop each tag is an element of the current item.

You can, as you can see in the conditional statements section above, also see that you can use the standard dot-notation to access nested elements. In this case the elements in the offer object.

Calculations

In the conditional statements section you can see some basic calculations.

{{:offer.price - (quantity * price)}}

The result of the calculation will be rendered to the page.

Rendering options

You will have noticed that templating statements are all in two braces. Where something is rendered the initial opening braces are followed by a colon. This simply outputs the results directly on to the page. This is great if the output is safe (or it is HTML), however if you want to ensure that the output is correctly encoded for a web page you can use a right-cheveron.

  {{:some_html_to_be_rendered}}
  {{>some_text_to_be_escaped}}

The example

The example for this post can be found here. You are encouraged to view the source of the example.

Tip-of-the-day: Columns in CSS

The CSS Multi-column layout module is a Candidate Recommendation that allows CSS to specify various aspects of column layout for page flow. It has some implementations in Chrome and FireFox but it does not work in IE yet. (I’ve not tested it on other browsers). Because of this you have to specify the Webkit and Mozilla extensions in the CSS. e.g.

div.example
{
  column-width: 300px;
  -moz-column-width: 300px;
  -webkit-column-width: 300px;
}

To show you what it can do, I’ve created some small simple examples using a list of cities, a poem and some prose. (The links open in new windows. You are encouraged to look at the page source too)

Without Columns With Columns

Tip of the day: IE Quirks Mode Vs. Standards Mode

If you are setting the DOCTYPE declaration in an HTML page to define the standard your page complies with ensure that you don’t put anything before that DOCTYPE declaration.

Some browsers will ignore comments and such like before the DOCTYPE declaration but IE doesn’t and if there is a comment it will then ignore the DOCTYPE which then puts your browser into Quirks Mode (and that can screw up the rendering of your page)

So, if I put this at the top of the document:

<!-- This will trigger IE into quirks mode -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">

Then quirks mode will be rendered.

However, if I put the comment after the DOCTYPE everthing is fine, like this:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<!-- This won't trigger IE into quirks mode as the DOCTYPE is first -->
Follow

Get every new post delivered to your Inbox.

Join 26 other followers