In Part 1 and Part 2 we covered the basics of getting our dependencies into ASP.Net MVC. Today we will finally get angular running, and make our home page more than a blank site.
Let us first start off by creating an angular module called app. This is a super simple one, but it will fill our needs for this demo. I am going to start by creating my new directory structure inside of Visual Studio for my angular application.
A lot of people have differing opinions on folder structures for AngularJS apps, but I prefer to just do it by feature. As you can see, this looks a lot like a server side MVC folder structure, the only difference is that the code and the views live inside the folders.
Next step is to create our main module file. For the JS files, I will be using a naming convention of “<name>.<function>.js” so for our module, I create an app.module.js with the following content:
'use strict';
var My = My || {};
My.AngularJS = My.AngularJS || {};
My.AngularJS.Module = angular.module('app', ['ngRoute']);
I have scoped this, it isn’t necessary, but is good practice. Additionally, I went ahead and referenced the ngRoute module as a dependency since we will cover that below.
Now in our HTML, we need to either call angular.bootstrap via JS, or we can simply add the ng-app attribute to our page. For this demonstration, we will be using ng-app on the HTML element.
<html data-ng-app="app"></pre>
Not to horribly impressive as of yet, but wait… there’s more. Let’s bind a few elements on our page, so it isn’t as boring.
You can get the specific HTML for this on the github repo, but it is using the standard jumbotron template that is available on getboostrap.com.
Now that we have our template, we need to add some additional bundles for our angular app, because right now navigating will give us a javascript exception, because we have yet to include our code.
In our BundleConfig class, lets add a new bundle for our app:
bundles.Add(new ScriptBundle("~/bundles/ng-app.js")
.IncludeDirectory("~/app/", "*.utility.js", true)
.Include("~/app/app.module.js")
.IncludeDirectory("~/app/", "*.config.js", true)
.IncludeDirectory("~/app/", "*.run.js", true)
.IncludeDirectory("~/app/", "*.service.js", true)
.IncludeDirectory("~/app/", "*.controller.js", true)
.IncludeDirectory("~/app/", "*.directive.js", true)
.IncludeDirectory("~/app/", "*.filter.js", true)
);
Again, this is personal preference, but I really like laying out my app like this, and it allows me to easily separate out all of the files cleanly. This also means that any time I add a file and build, it will automatically make it into the bundle.
How to just include it in our html page real fast…
@System.Web.Optimization.Scripts.Render("~/bundles/ng-app.js")
Now we are pretty much loaded and running and our application is loaded… but how can you tell? Let’s do some quick house cleaning…
Add data-ng-cloak attribute to the body tag, this will prevent the page from displaying until angular has done it’s data binding, very useful.
<body data-ng-cloak>
Now, let’s add a model to our root scope, this will be for the entire site. The only way to set objects on the $rootScope is to do it via a run script. One thing to note is the definition syntax, unless you are using a custom minifier for angular files, you will be required to setup your dependency injection with Inline Array Annotations.
'use strict';
My.AngularJS.Module.run(['$rootScope', function ($rootScope) {
var site = {
name: 'My Angular Site',
copyright: '2014 - Your Company Here'
};
$rootScope.site = site;
}]);
This is a pretty simple model, but now lets change those static pieces in our html to use these bindings.
In the Header:
<a class="navbar-brand" href="/">{{ site.name }}</a>
In the Footer:
<p>{{ site.copyright }}</p>
Looks… pretty much the same, but that was intentional!
Finally, let’s add our routing, so we can get that about page working. Create an routing.config.js in the app directory (again, why I name these things this way)
'use strict';
My.AngularJS.Module.config(['$routeProvider', function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl: '/app/home/home-view.html'
})
.when('/about', {
templateUrl: '/app/home/about-view.html'
})
.otherwise({
redirectTo: '/'
});
}]);
Next we will need to modify our html a bit, create the app/home/home-view.html and migrate out the jumbotron html, then create the app/home/about-view.html, and finally hook-up an ngView directive to the content area of the site.
<div class="container body-content">
<div data-ng-view></div>
<hr />
<footer>
<p>© {{ site.copyright }}</p>
</footer>
</div>
Now when we run the application, we have navigation to both the home and about page! You can even refresh on the about page. One of the great benefits of this as well, is the templates are only ever downloaded once.
In the next article we will take advantage of the bootstrap angular template, and start creating our own directives for style components.
You can find the code used in this Blog Post on my GitHub Repository.
No comments:
Post a Comment