Angularjs

Angular-hint in Angular 1.3

With the release of version 1.3, the Angular project comes with a new module called angular-hint, that makes debugging and finding mistakes in the code base easier. It also gives us hints about best practices, so that our code is more maintainable and easier to read. In this article we’ll take a brief look at this module and explore how we can actually use it and what great features it provides. As a side note, this is the third article of our ”Exploring Angular 1.3” series, so you might want to check out our articles about ngModelOptions and one-time bindings too. Okay, let’s dive into the actual topic.

As already mentioned, angular-hint helps us writing better Angular code and makes finding very common mistakes in our code base easier. For example, did it ever happen to you, that you developed your Angular app, you grabbed a module from somewhere, then you started using the directives that the module comes with, and no matter how much you followed the usage instructions, it simply didn’t work. And after one hour of debugging you found out that you forgot to add the module dependency to your application. Yikes!

But let me tell you something. With angular-hint, these times are over. And that’s just one use case where angular-hint helps out. In fact, angular-hint comes with a couple of other sub modules for particular use cases.

These modules are:

Let’s start right away and see what the usage of angular-hint looks like.

Install and using angular-hint

Using angular-hint is super easy, since all we have to do is to install it via npm, embed the source in our application and use the ng-hint directive that takes care of the rest. Alright, so let’s install the module via npm:

$ npm install angular-hint

The angular-hint module declares all the sub modules (angular-hint-directives, angular-hint-controllers, …) as dependency, so you don’t have to care about installing them manually. The command above does the job for you. Also, the package comes with a pre-compiled hint.js file that contains the source of all mentioned angular-hint-* modules, so you can use it right away.

Once it’s installed, we can embed the source in our application right after Angular itself like this:

<script type="path/to/angular/angular.js"></script>
<script type="path/to/angular-hint/hint.js"></script>

Next, we apply the ng-hint directive in order to actually use the angular-hint module:

<body ng-app="myApp" ng-hint>
</body>

That’s it. We’re done. It’s that easy.

Applying the ng-hint directive to our document takes care of injecting all needed hint modules in your apps bootstrap phase. But how does ng-hint know, which hint modules we actually want to activate? By default, ng-hint injects all the mentioned hint modules. However, if we don’t want to get controller related hints, but are interested in DOM related hints, we can restrict the use of hint modules by using the ng-hint-include directive instead. The following code only injects angular-hint-dom:

<body ng-app="myApp" ng-hint-include="dom">
</body>

We can even define more than just one hint module if needed:

<body ng-app="myApp" ng-hint-include="dom directives">
</body>

As you can see, the names used as value for ng-hint-include map to the suffixes of the actual hint module names. E.g. dom and directives map to angular-hint-dom and angular-hint-directives respectively.

Module hints

Okay, so now that angular-hint is installed, let’s try to reproduce the “I forgot to add module dependency” scenario we were talking about. To do that, we declare an additional Angular module that act as our app dependency. For simplicity’s sake, we don’t add any ground breaking functionality here.

angular.module('myAppDependency', []);

Next we take a look at our actual app module definition. As you can see, we declare the module without any further dependencies a.k.a we simply forgot it.

angular.module('myApp', []);

Now, instead of fiddling around for an hour to find out why myAppDependency’s directives aren’t picked up, angular-hint is telling us that we might missed something. Simply open your browsers console and you should see something like this:

Angular Hint: Modules
  Module "myAppDependency" was created but never loaded.

This log occurs whenever an Angular module is present but not declared as dependency anywhere (You might see another message says that ngHintModules was also created but never loaded. This is a probably a bug and filed here).

There are a couple more things that this module tries to warn you about and you can read about them here.

Controller hints

If there’s one thing you should embrace when working on a bigger Angular app and especially when working in a bigger team, are best practices. The Angular team published their style guide for apps built with Angular internally at Google, that covers best practices and conventions.

One of these best practices is, when naming controllers, to suffix them with Controller instead of using short names like Ctrl. angular-hint helps with that too. Let’s take a look what happens when we define a controller with a name that doesn’t have this suffix:

angular.module('myApp', []).controller('AppCtrl', function () {

});

Having a controller registered like this, angular-hint gives us the following warning:

Angular Hint: Controllers
  The best practice is to name controllers ending with 'Controller'.
  Check the name of 'AppCtrl'

I think this makes pretty much clear what can be achieved with such a tool. Having a style guide with conventions and best practices that everybody agrees on, makes a projects structure easier to understand and debug. With angular-hint we actually have a tool to embrace and encourage these best practices and conventions and this is just the start!

Directive hints

When dealing with directives, there are a couple of things that can go wrong and stop us from being productive because we have to debug (once again) why a given directive doesn’t seem to work. Similar to the example where we forgot to add our module dependency, it also happens quiet often, that we misspell directive names. When a directive name is misspelled, for Angular, this is just an attribute (or element) that it doesn’t know about, so it gets completely ignored.

Just take a look at this small snippet:

<ul>
  <li ng-repaet="i in [1,2,3,4]">
    <!-- more dom goes here -->
  </li>
</ul>

As you can see, there’s a typo in the directive name. We actually wanted to type ng-repeat, but we typed ng-repaet. I can easily remember the last time, when I was debugging for an hour because I just misspelled a directive name. Because literally nothing happens.

However, when angular-hint is activated, we get the following very useful warning:

Angular Hint: Directives
  There was an AngularJS error in LI element.
  Found incorrect attribute "ng-repaet" try "ng-repeat"

How cool is that? Not only that angular-hint warns me about an incorrect directive name and on what kind of element it is applied, it also suggests me a directive that is actually registered and to use! And now think about how much time you can save with such a helper.

Conclusion

Even if we took a look at just a few of all provided angular-hint modules and features, I’m pretty sure you get an idea how useful it is. Of course, it’s still in early development and has one or the other bug here and there, but the initial idea of having such a module that you can easily apply and tells you about all your possible mistakes, is just awesome.

And again, this is just the start. I can’t even think of all the possibilities we have when extending the hint modules with additional functionality and hints. I could also imagine that this module could help out migrating from 1.x to 2.x in the future once the APIs are stable.

However, you should go and try it out in your apps today. If you find any bugs, make sure to file them at the dedicated repositories on GitHub, or fix them directly and send a pull request. Also, don’t hesitate to come up with new ideas on how the module could be extended. It’ll make all our lives easier!

Written by  Author

Pascal Precht