Some Angular 1.3 Links

I decided to take some time earlier this week to find some blog posts around the new features in Angular 1.3 so that I could add them to my github repository. I thought I would also list the links here, in case some of you wanted to do some Angular 1.3 reading over the holidays (for those of you in the US who celebrate Thanksgiving).

If you know of other Angular 1.3 links that I am missing, please let me know. I’m mostly looking for articles that focus on the NEW features in Angular 1.3…

Taming Forms in AngularJS 1.3
Asynchronous form errors and messages in AngularJS
$touched is the new $dirty – AngularJS Migration Guide 1.2 to 1.3
Exploring Angular 1.3 – One-Time Bindings
-Exploring Angular 1.3 – ng-model-options
Working with Validators and Messages in AngularJS
Exploring Angular 1.3 – Angular-Hint
Exploring Angular 1.3 – Stateful Filters
ngEurope: what’s new in Angular 1.3?

AngularJS Tip: Adding App-Wide Messaging

Yesterday, someone left a comment in my Angular Best Practices post, asking the following question (paraphrasing):

If a promise is rejected during the UI Router resolve, how do you let the user know?

I thought about it a bit, and decided to answer this question instead:

What is a quick and easy way to enable app-wide messaging?

By “app-wide messaging” I mean the ability for any module in the app to display a message to the user. So if an error happens in a service, or an error happens in a directive, there should be a consistent way to tell the app to display a message to the user. I’m not a fan of using dialogs or modals for this, so my solution was to use an Alert to display messages. I came up with a solution that feels pretty simple (note the solution below has been cleaned up, thanks to commenters on this post and on reddit/angularjs). Basically, there will be a new directive (called app-messages) and a new service (appMessagesService). When a message needs to be shown, a module will call appMessageService.addMessage(). The app-messages directive has a reference to the list of messages maintained by the service. So when a message is added to the service, the app-messages directive will display an alert to the user. If you want to see this code in the angularBPSeed project, check out the app.js file, services/locationLookupService.js, and all the files in components/appMessages. I’m also going to explain the solution in more detail below.

The first thing we’ll do is create the directive, called appMessages (app-messages in the html file). I’m not going to show the full contents of all of the directive files (you can see the full files in the seed project), but I’ll include the main logic from the appMessagesCtrl below:

    
var self = this;

self.alerts = appMessagesService.getMessages();

/**
 * closes the alert and removes it from the list of alerts.
 * @param alertIndex
 */
self.closeAlert = function (alertIndex) {
    appMessagesService.removeMessage(alertIndex);
};

The alerts array is used to store the messages to display. This array is actually a reference to the array stored within the appMessagesService. The service will be explained below, but it contains logic for adding and removing messages, as well as getting a reference to the list of messages. When the service modifies its internal array, the directive’s array will also change (since JavaScript objects are ‘pass by reference’). And since Angular is ‘watching’ our self.alerts array, when it is changed, our view will be updated to reflect those changes.

The html for the directive looks like this:

    
    
    <alert ng-repeat="alert in appMessagesCtrl.alerts" type="alert.type"
        close="appMessagesCtrl.closeAlert($index)">{{alert.msg}}
    </alert>

We are using the alert directive from the Angular UI Bootstrap project. The type attribute specifies the type of alert to display (warning, success, etc), the close attribute is the method to call when the ‘x’ is clicked, and alert.msg is the message text to display.

Next, lets look at appMessagesService:

var self,
    messages = [];

self.addMessage = function (message) {
    messages.push({
        type: message.type,
        text: message.text
    });
};

self.getMessages = function() {
    return messages;
};

self.removeMessage = function(messageIndex) {
    messages.splice(messageIndex, 1);
};
 

You’ll notice that the service has a private reference to a messages array. It also exposes methods to add a message, remove a message, and get the list of message. Unlike previous version of this code, the $rootScope and events are no longer necessary. Everything is encapsulated within the service.

An example of using the service to send a message (from locationLookupService.js):

    
    appMessagesService.addMessage({
        type: 'warning',
        text: "Error looking up location with locId: " + locId
    });

As you can see, the code is fairly simple. We use the appMessagesService to add our message. That’s it..nothing to it!

Finally, a snippet from the index.html, to show where the directive is added to the html:

    <div app-messages></div>
<div class="container" ui-view="page"></div>

You’ll notice that I added the appMessages directive to the div ABOVE the ui-view. If you are unfamiliar with Angular UI Router, the ui-view is similar to ng-view. In other words, the ui-view div is where the views for our SPA live. So, by adding the app-messages directive above the ui-view, it means the app-messages directive can be shown at the top of every view within our app. Sorta like a global message center. Obviously, if you only need to display messages within certain views, you can add the appMessages directive to those views instead of making it a global directive like I did in the seed project.

Before my next post, I think I need to find a plugin to make code snippets look nice 🙂

 

Edit: Changed the $emit to a $broadcast.

Edit 2: Per a comment here on the blog, and on reddit, I added a appMessagesService, which is used to send the messages. Post has been updated to reflect this change.

Edit 3: Per further comments and discussion, I’ve removed the dependency on rootScope and event broadcasting.

Angular Best Practices Seed/Template

Last week I posted about my Angular Best Practices Guide (as noted, it was heavily inspired by Todd Motto’s guide). As useful as a guide can be, nothing beats looking at real code. So I decided to create a simple seed project to show many of the best practices in action. The result of that work can be found here: angularBPSeed.

More details, including instructions on how to run and build the seed project, can be found on the project’s Github page above. I will also list some of the features of this seed below:

Features

  • An example app following many of the best practices from my Angular Best Practices Guide
  • Built-in Express server for serving the app during development.
  • An optional proxy server for CORS functionality. This allows you to serve the app from your local machine, and also make requests to a 3rd party server if needed.
  • Includes 2 services, 2 directives, 2 top-level views, an Angular UI Bootstrap modal, “fake” server call using promises, a loading bar displays during calls to the server.
  • Uses AngularJS, Angular UI Router, Angular UI Bootstrap, Angular Loading Bar, Bootstrap, Grunt, Browserify, ngAnnotate, html2js (for compiling templates and adding them to the template cache
  • 2 builds: grunt build is used during development, and grunt (the default task) will run the build and prod tasks to build a production-ready version of the app.

In addition to highlighting the Best Practices, I wanted to show how you can integrate Browserify (and thus CommonJS) into your project. Browserify is really easy to use, and using CommonJS adds minimal overhead to your project. I’m far from an expert on Browserify, but I can’t imagine not using it on a project.

To use this project as a template for your own project, just clone it remove (or rename and customize) the existing services, directives, etc. It should be fairly easy to use this seed as a skeleton to start your own project.

If you would like further clarification on the ideas behind the code in the seed, or further explanation of how something works, feel free to ask me in the comments of this post.

Yet Another Opinionated AngularJS Best Practices Guide

A couple of months ago, I created an Angular Best Practices guide for the team I was on at the time. The ideas for those Best Practices came from several places: blog posts, Github repos, personal experience, ideas from others on the team, etc (in other words, I’m not claiming credit for the ideas below. They’ve come from various places, people/coworkers I respect, with some personal opinions added). Now that I’ve started a new role, I wanted to update my Best Practices guide. The original version was just a Google doc, which I then imported into a Word doc. But, I had thoughts of adding it to my Github account in case others were interested. Then, a few weeks ago, Todd Motto posted his Angular Styleguide. While it contained some of the same ideas from my original document, Todd also had many more that I hadn’t thought of, but really liked. My document was also very light on code samples/examples, which was something I wanted to fix. When I saw that Todd moved his Styleguide to a Github repo, I thought I would just fork it instead of starting my over. I liked the organization and formatting of his doc, so it made sense to start from there.

I spent a few hours working on my tweaks to his Guide, and finished it up over the weekend. So my fork of his guide is missing a few things from Todd’s, and contains many more that I’ve added. I know some of my additions are personal preferences, but I added them because I think they can provide consistency in how projects are structured (especially the stuff in the Files category).

I haven’t decided yet whether to commit any of my changes back to his repo. I thought I would post them first in my fork and get some community feedback.

You can view my fork of the styleguide (which I am calling Best Practices) at my Github repo: AngularJS Best Practices Guide. I also hope to create another repo containing an Angular starter project (another Github repo) that follow these guidelines. That way you can see what these guidelines look like when applied to a simple project.

I’ll list some of the additions I made below, but you’ll need to visit the repo to see further explanations and code samples:

General

  • When possible, use angular.element(), etc. instead of jQuery lookups and DOM manipulation.
  • Don’t wrap element inside of $(). All AngularJS elements are already jqobjects.
  • Do not pollute your $scope. Only add functions and variables that are being used in the templates.
  • Do not use $ prefix for the names of variables, properties and methods. This prefix is reserved for AngularJS usage.
  • Use ng-bind or ng-cloak instead of simple {{ }} to prevent a FOUC (Flash of Unrendered Content).
  • When you need to set the src of an image dynamically use ng-src instead of src with {{}}.
  • When you need to set the href of an anchor tag dynamically use ng-href instead of href with {{}}

Files

  • One module per file
  • Each file should get its own namespace
  • Each filename should match the controller/service/etc name
  • Function name and file name should match
  • Each file should be CommonJS compatible
  • A specific directory structure

Controllers

  • controllerAs ‘self’

Directives

  • Templating (avoid inline templates)
  • Each directive should live in its own directory
  • Use isolate scope in directives whenever possible

Routing Resolves

  • Promises (modified Todd’s entry to recommend ui-router, $stateProvider, etc)

AngularJS: Using $setViewValue and $render() to Update Models & Forms

Earlier this week, I ran into a situation in Angular that I hadn’t run across before. I had a form that had several fields: address, city, state, zip, latitude and longitude. The page also had a Google Map, that would allow the user to click on the map, and update the form fields with the newly selected address on the map. To give the user a visual clue that the form had updated with the new values from the map, I was using $dirty to change the styling of the form fields. To change the form fields, I was updating the model directly. However, it turns out that directly changing the model in a Controller, wasn NOT triggering the $dirty flag in my Angular form. It took me awhile to figure out what was going wrong, and how to solve it. I thought I would post my solution here, in case it might help someone else (or in case one of you might have an even better solution to the problem).

I don’t want to include my work code, so I created a plnkr to simulate the issue. You can view the plnkr here. Basically, I have 3 form fields. A snippet of one of them is below:

<div ng-class=”{‘has-warning’: myCtrl.simpleForm.city.$dirty}”>
<label for=”city” class=”col-lg-2 control-label”>
    City <span ng-show=”myCtrl.simpleForm.city.$dirty”>*</span>
</label>

<div class=”col-lg-2″>
    <input type=”text” class=”form-control” id=”city” name=”city”
        ng-model=”myCtrl.location.city”>
</div>

And in the controller, I am updating the model like so (in my real app, I would get the data from a service, but am keeping the code here simple):

self.updateModel = function updateModel() {
self.location = {
    city: ‘Atlanta’,
    state: ‘Georgia’,
    zip: ‘30339’
};

Notice that when you click the Update Model button, the model is updated, but the form fields are not marked $dirty, so the extra styling is not added to let the user know the form values have changed.

Doing some reseach on StackOverflow, I found a few references to the same problem, with the solution being to call $setViewValue() and $render(). Problem was, I didn’t know how to call $render. Thanks to the console.debug() statement, I dug into the object graph of one of the input fields and found a way to get the controller for each input. Once i have the ngModel controller for each input, I can call the $render() method on it.

So the answer turned out to be a 2 step solution. First, you update the view value in the input by calling $setViewValue. Updating the view value also triggers the $dirty flag for the view/input.

self.simpleForm.city.$setViewValue(‘Atlanta’);
self.simpleForm.state.$setViewValue(‘Georgia’);
self.simpleForm.zip.$setViewValue(‘37013’);

While this updates the view value, the mode value does not seem to get updated. (i.e if you just execute the 3 lines above, without $render(), the form fields will be marked $dirty, but the values in the form will not change). This is where $render() comes in. You need to tell the view (input) that just changed, to render itself so the model value is changed (so the new value displays in the form field). To call render, you need to get the ngModelController for the 3 elements we changed above. For example, the input for the city field has an id of city. We can get the controller for that input and call $render() on it like this:

angular.element(‘city’).controller(‘ngModel’).$render();

In the plnkr, you will notice that I made a utility method to call $render(), so that I could pass in an array of id’s to $render(). You can view the working plnkr here

So that is one way to update both the view and the model inside a controller, while also triggering $dirty on the form fields. I’m not thrilled with having to access the DOM in my controller, or having to reference element id’s in my controller. If someone knows of a better way to solve this issue, feel free to let me know in the comments.

AngularJS Learning Resources Update

Last year while learning AngularJS, I started compiling links to Angular blog posts that I liked, by adding them to a simple text file. After a couple of weeks of gathering links, I thought “hey, maybe other devs new to Angular would find this useful, too”. So I created a Github account, and created a project called AngularJS Learning Resources (which you can find here). I didn’t know anything about Github at the time, so the project wasn’t (and still isn’t) fancy. After creating the project, I decided to mention it on Hacker News, and I was rather surprised at the results. It ended up making it into the top 3 spots on the front page, and stayed there for almost a full day. Within a week, I believe it had 3000 followers, and is over 6000 now. I hope folks have found it useful, and I truly appreciate all the pull requests from others to add new links. Anytime you come across a nice Angular article, feel free to submit a pull request (or comment) to get it added.

Now that the list is about 15 months old now, it needs some attention. At this point, there are approximately 550 links in the list, and not all of them belong any more. I need to devote some serious time to going through all of the links, and “trimming the fat”. And I would like to reorganize the sections a bit. But first, the goal is to remove some links.

If anyone would like to help, I would certainly appreciate it. Reading the content of 550+ links is quite a job. For this first round, if you want to help, I would like to concentrate on removing links that meet one of more of the following criteria:

  1. The post is out of date (though just being old doesn’t matter, if the content is still relevant. But I would think most links over 12 months old are dated)
  2. The content is ‘fluff” and can easily be found in other places (like answers on Stack Overflow). In other words, if the content is high level and isn’t very useful, or doesn’t offer anything beyond the Angular documentation, it should be removed. That way the list isn’t cluttered with articles that don’t offer much in the way of  Angular teaching or insight.
  3. The content suggests something that goes against current Angular best practices.
  4. Similar to #3 above…the article uses bad JavaScript coding in general, or otherwise could lead developers new to Angular down the wrong path.

To prevent multiple people from editing the same sections, I will start a thread in Github repo for the project. If you would like to help, just leave a comment here and let everyone know what section you would like to clean up.

If you have other suggestions for the repo, feel free to comment here in this post.

Thanks in advance to anyone that wants to help out!

Must Read: The You Don’t Know JS Series

Usually when I review a tech book, I’ll give more details on the content and be specific about things I liked and didn’t like. However, this post will be more of a recommendation for the You Don’t Know JS series. I’ve read the first two books, but not recently enough to dig into specifics.

I thought I would start with a quick background of my experience. I spent my first 14 years (as a programmer) doing server-side Java. I burned out on that, and wanted to move into something else, so my next (brief) step was working on a native Android app for a previous company. After they completed the Android app, they wanted to start work on an iOS app. Having no Objective C experience on the team, they elected to try a hybrid app using PhoneGap. I was chosen to be the sole developer, so I got to jump in and learn proper JavaScript…and Backbone, RequireJS, Grunt, jQuery Mobile, etc…all at the same time! A bit overwhelming, especially since I had the same opinion as most other Java devs: JavaScript was silly and I didn’t want to mess with it.

Well, my mind quickly changed about 2 months into developing the iOS app. To learn JavaScript, I read a bunch of books..learning to respect JS as a programming language instead of “just a scripting language”. I quickly, and surprisingly, fell in love with JavaScript. And realized I didn’t want to do anything else. I lost interest in native mobile development, and decided that the next stage of my career would revolve around front-end development and hybrid mobile development (they can overlap quite a bit). To wrap this career summary up, I’ve spent the last 2 years focused solely on JavaScript, including most of the last year doing AngularJS-related stuff.

I see so many recommendations for JavaScript: The Good Parts by Douglas Crockford. It seems the book most recommend if you want to go from a good JS developer to a great JS developer. While I understand why The Good Parts gets so much love, I never really connected with it. And now, I think there is a better way to dig deep into the workings of JavaScript: The You Don’t Know JS (YDKJS henceforth, to save typing) series.

At the time of this post, the first two books in the YDKJS are available, though it looks like three more will be published over the next few months. The series appears to be:

Finally, we get to the whole purpose of this post. If you have an interest in JavaScript, care about the craft of programming, and REALLY want to know JS inside and out, the YDKJS series is a MUST read. I feel like I know JS pretty well at this point, though of course there is always more to learn. But I learned quite a bit from the first two YDKJS books. I will say that I think its best that you already know the basics before tackling these books. And even if you know JS well, be prepared to read some of the topics more than once. The author really dives deep into the corners. While some of this knowledge might not appear to help you in your everyday work, this is stuff you need to know. The better (and deeper) you know JS, the better your code will be.

So…if you want to become a serious JS developer, the YDKJS series is a must-read. I’m really looking forward to the rest of the books. I’m sure I’ll continue to find out that I don’t know JS quite as well as I thought (hence the appropriate title for the series). Again, sorry for the lack of detailed analysis of these books. I just wanted to recommend them, as I think they are 2 excellent technical books.

On a semi-related topic…I am mulling the idea of posting about how transitioned from a Java developer to a JavaScript developer. I’ve seen Java folks as that question on reddit, and thought I might give some background on how I approached it.