Putting ng-init to good use with good practice29 Nov 2014, by Developer in
Ng-init is an AngularJS that will execute code when that ng-init is initialized. So when the page loads, if we have an ng-init somewhere, it’ll be evaluated immediately. It seems like a viable way to initialize variables for our view, but we can always do that in the controller which is better because it separates our logic from our view. So what can we do that would could be considered good use for ng-init?
Executing our “init” or initialization function.
The first usage I noticed when working with another developer is that he uses ng init to initialize our controller data. Something like this:
<div ng-init=”init()”> … </div>
This will execute our controller’s init function when the page loads. This is useful because it helps us keep track of all the code that should execute when the view loads. Otherwise, we would just have random tidbits of code in our controller that execute when the controller loads which is typically undesirable. Another benefit is testing, when testing our controller, Jasmine will execute any code when it loads and that would require us to handle any mocking for all tests. If we use an init function then the jasmine test runner won’t be able to execute that code unless we explicitly tell it to. So we can make our testing much easier and cleaner by creating an init function. It will even allow us to write a test like “When the page loads, it should do this and that.” Because now we can simulate the view loading by calling our init function.
Utilizing ng-init for local scope variables.
One of the great things about AngularJS is how it utilizes scopes for practically everything. So when we use an ng-repeat, each item in the list actually creates its own scope. Thus allowing us to put an ng-init on that and create things like in an inline edit or delete easily. Here is an example using ng-repeat: http://codepen.io/MoeBDC/full/ZYbGov/ . As you can see by hovering over each item in the list we can have a local Boolean for toggling inline edit mode and then saving those changes. I don’t need to create extra logic, track the changes in my controller, or even tell my controller that I’m editing anything since AngularJS has 2-way binding. We can even assign properties to our object in a similar fashion by simple doing something like:
<div ng-repeat=”…” ng-init=”item.sortOrder = $(index)”>…</div> //had to wrap (index) with parenthesis because it breaks the code snippet otherwise
Inside our ng-repeat to assign the sort order property the value of the index created by ng-repeat, fairly useful when expecting gaps in your data that will need to be handled anyway.
Keep in mind, that depending on how you setup your controller either with ng-controller or using ngRoute (or the route provider of your choice) that AngularJS evaluates things in a certain order. So don’t expect to be able to access a controller variable if you’re using ng-controller after an ng-init because angularJS uses a depth first approach when evaluating the DOM so just keep that in mind. Most well engineered applications will use a route provider that will load the controller prior to the view so that won’t be an issue. I may cover how AngularJS’s executes its compiling phase in a different post.
These are a just a few ways that I like to use ng-init and find that they are invaluable when developing software. The amount of code saved by using an inline local edit mode alone is worth the mention. I do think we should standardize utilizing ng-init to execute our controller’s init function as it helps tremendously when testing and the only downside might be that we have to wait for AngularJS to evaluate the DOM but that problem has yet to occur in any application that I’ve worked on. And it your HTML is taking more than a second to load, you need to go back and rethink that screen because it probably needs to be broken down.