Wednesday, July 30, 2014

Where is Model in AngularJS

We all know that Angular follows MV* design pattern and in this pattern M stands for Model. But where is the Model in AngulaJS. In all the demos and samples we see the model mysteriously disappeared. Some people claim that $scope is the model. This may not be correct on how you look at the model.

Before going further let’s check the definition of model. Here is the definition from Microsoft on model

Model. The model manages the behavior and data of the application domain, responds to requests for information about its state (usually from the view), and responds to instructions to change state (usually from the controller).

So a model should include a stateful object along with business and validation logic. Most of the times model also includes the data access layer. In case of Angular the data access layer is a RESTful call. Currently in most of the apps controller is doing the model’s responsibility. Most controllers persist the state (sometimes in $scope) and these controllers perform the data fetching and validation. This is ok for a trivial demo or for small applications. But for complicated or large applications we need clear separation of concerns and hence cannot convolute controllers with the model functionality.

If you see ASP.NET MVC, the model includes only a stateful POCO object and validations. As per the design pattern this is may not appear as the true implementation of model. Our model should include business and data access. In large ASP.NET MVC projects we typically have business and data layers. Hence our model actually consists of a stateful object with business and data layers. So our model was split into multiple files, a stateful object and a business object. Let’s extend the same to AngularJS

Putting “M” back in Angular

Similar to ASP.NET MVC let’s split our model into two files, one contains the stateful object and another a service which acts as business and data layer. In our next section we will move the stateful object to the right place where it belongs.

Let’s assume that we are working on a project where we are using contacts. With that premise let’s create a stateful object called contactModel.js with the following code

'use strict'

angular.module('ngmodels').value("contactModel", contactModel());

function contactModel() {
    return {
        ContactID: 21,
        FirstName: 'Praval',
        LastName: 'Pattam'
    };
}

In the above code we defined an angular value that contains a model with ID, FirstName and LastName properties. Next let’s define an angular service that performs business rules. Here is the sample code:

'use strict'

angular.module('ngmodels').factory('contactService', contactService);
contactService.$inject = ['contactModel'];


function contactService(contactModel) {
    return {
        get: get,
        save: save
    }

    function get() {
        //fetching the contacts
        return contactModel

    }
 

    function save() {
        //saving the contacts
    }
}

As you see our contactModel and contactService together form the Model. With this approach we can use this model in our controller. Let’s see how our controller looks like:

'use strict';

angular.module('ngmodels').controller('contact', contact);
contact.$inject = ['contactService'];

function contact(contactService) {

    var vm = {
        model: {},
        save: save
    };

    initialize();

    return vm;

    function initialize() {
        vm.model = contactService.get();
    }

    function save() {
        contactService.save(vm.model);
    }

}

As you see in the above code we are injecting the contactService (which is part of our model) and our controller passes this model to the view using viewmodel pattern.

Now with our Model we were able to clearly separate the layers and made our controller clean.

In most of the applications we bring the data from the server using a RESTful call. The web server fetches the data from database, executes business logic and returns it as a JSON object. So in our server we typically define a contact object that holds the contact data and sends it back. Here is the definition of the Contact class in C# that is returned to Angular using WebAPI

    public class ContactModel
    {
        public int ContactID { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }

When this object is returned as JSON, JavaScript automatically creates a stateful object. This will remove the need of defining the contactModel in javascript. With the server side model, our contactService will be changed to use resources to fetch the model from server using the below code.

'use strict'

angular.module('ngmodels').factory('contactService', contactService);

contactService.$inject = ['$resource'];

function contactService($resource) {
    return $resource(
        "/api/contact"
    );
}

So sometimes it is argued that in Angular the model resides on the server. The client uses that server model in the view. But as explained earlier, model contains two pieces. In Angular the definition of the stateful model resides on the server and some part of the data and business resides on the client. Hence the model resides in two layers. It’s funny as it sounds but that is correct.

As you have seen Model is a complex piece in Angular.

You can download the sample code used in this blog from my github site.

Sunday, July 27, 2014

ASP.NET MVC routing for Angular

As you know Angular is a single page application, hence there will be only one page on the server. So in MVC we just need a controller and an associated view. So why is there a need for routing in MVC.

It depends if you are supporting the evergreen browsers and using HTML5 Mode instead of Hashbang Mode for URL rewriting then URL looks as below

http://www.domain.com/contact/list

If you user bookmarked one of these Angular’s HTML5 mode URL and navigated to that url, the browser first makes a request to the server with the above url. ASP.NET routing engine deduces this routing as a List action in a ContactController and tries to fetches that controller. Since it is not present the server will return 404 error.

Another reason is why you don’t need the default MVC routing is there is only one controller. Instead of giving 404 error on the server, we can redirect the users to our home page or give some friendly error message which is hosted in the Angular app.

In either of the above two scenarios we need catch all the incoming requests and route it to the only action we have. This can be done by the below MVC route configuration

            routes.MapRoute(
                "Default",
                "{*url}",
                new { controller = "Home", action = "Index" }
            );

As you see I am catching all the incoming urls and routing it to the only controller and action I have. With this route configuration I truly have only one page on my server which kick starts my angular app.

Wednesday, July 23, 2014

Visual Studio Project Structure for Angular

We all know how important is to have a proper project structure for any project. To jump start this Microsoft provided several project templates. You can also download additional templates. In this blog I show you the project structure I adopted for my Angular project after examining and reviewing several available project templates and recommendations.

Before going in detail, here is my recommended visual studio project structure:



As you see this is in line with Microsoft recommended structure with an addition of “app” folder. As you aware this app folder is used for Angular stuff. Here is the folder structure for this app folder:


First I will quickly cover the salient features of my MVC folder structure (some of which you already know):
  • I am using Bundle.config to bundle all my javascript files written for Angular app using the below bundle configuration entry. This is in addition to bundling the vendor javascripts such as Angular, Kendo etc..
            bundles.Add(
                new ScriptBundle("~/scripts/app")
                    .Include("~/app/app.js")
                    .IncludeDirectory("~/app", "*.js", true)

                );
  • As our app is a single page application, MVC routing is not needed. I will override this default MVC routing with a catch all routing. This helps to directly go to the Angular routing and avoid 404 errors
            routes.MapRoute(
                "default",
                "{*url}",
                new { controller = "Home", action = "Index" }
            );
  • We just need a single View (Home/Index) which renders the necessary html and Angular start up script. Here is what I used

        <html data-ng-app="AngularKendoBootstrapApp">
        <head>
            <meta name="viewport" content="width=device-width" />
            <title>Angular Kendo Bootstrap Application</title>
            @Styles.Render("~/Content/css")
        </head>
        <body>
            <a href="/home">Home</a> <a href="/contact">Contact</a>
            <div ng-view>
                <div id="splash" class="splash">
                    Loading ...
                </div>
            </div>
                @Scripts.Render("~/scripts/libraries")
                @Scripts.Render("~/scripts/app")
        </body>
        </html>

The below are the salient features of my app folder for Angular development

  • I am segregating based on the functionality or modules. So each folder will host both my angular controller and view. In addition these folders will also include the services and directives required to display the page
  • My UI layout such as master pages and other global UI elements go under the layout folder
  • As the name suggests common contains the shared files across the app
  • Finally app.js contains the configuration and initialization script. If it is a big project then I will split this app.js in to multiple small files, such as app.route.js, app.config.js etc.
This is the folder structure I am incorporating for my projects. You can find the source code of this project at mygithub site. You can also download the Visual Studio template file for this project from here.

Sunday, July 20, 2014

Visual Studio Angular Project without using Templates

There are several Visual Studio templates which quick start your Angular development. I also created one template. If you are interested please go over to here. You can also download the source code of this blog at my github site.

These templates are great for a quick start, but one issue is that these templates create more or less functionality than we really need. Another issue is that we may not understand the purpose of all the files. If you are like me, then you want to know the plumbing code. In this blog I will go over step by step instructions on building an MVC Angular project without using Visual Studio Templates.

In my project I am planning to include the following javascript libraries. Please see below the list of libraries along with its purpose and location where you can download them. Where ever possible let’s download the non-minified version, we will use our .NET bundling to bundle these files. Alternatively you can use CDN also.
  • AngularJS
         https://angularjs.org  
  • AngularJS Route – For routing with our single page application
         https://angularjs.org  
  • Bootstrap – We will use this primarily for layout and responsive design. If need you can also use its JavaScript components such as DatePicker (you may need bootstrap directives for this)
  • Kendo UI Core with Angular Directives – These are open source UI controls from Telerik. These includes Angular directives. This is optional
  • JQuery – You may not need this but if you are using KendoUI then you need this

In addition to these javascript libraries we also need some nuget packages, they are:

  • Microsoft ASP.NET MVC – For the start up file
  • Microsoft ASP.NET Web API – For Ajax requests from Angular
  • Microsoft.AspNet.Web.Optimization – For bundling and minification of javascript and css

As our project main UI components are Angular, Kendo & Bootstrap, let us call our project as AngularKendoBootstrap. So let’s get started.

Fire up Visual Studio to create our project.

  • In Visual Studio 2013 create an ASP.NET Web Project and give the name as AngularKendoBootstrap     

  • While creating the project select an empty template


  • As you see we have a blank project in our solution explorer


  • Using Nuget Install ASP.NET MVC


  • Similarly install Web API


  • Using Nuget install the ASP.NET Web Optimization framework. This is used for bundling and minification


  • After installing using Nuget, create the following folder structure. As you are aware this is a typical MVC folder structure with an addition “app” folder


  • As per the MVC folder structure let’s include the files
  • Under the script folder include all the javascript files we downloaded


  • Similarly include the css files under the content folder


  • As recommended by MVC add the config files in the App_Start folder. These are the standard config file for any typical MVC & Web API project.


  • Add global.asax file and call our configs from it
protected void Application_Start(object sender, EventArgs e)
{
    WebApiConfig.Register(GlobalConfiguration.Configuration);
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    RouteConfig.RegisterRoutes(RouteTable.Routes);
    BundleConfig.RegisterBundles(BundleTable.Bundles);
}

  • Let’s bundle all out javascripts and css files using Bundle.config. In addition let’s also bundle all the our javascript files (that we place under app folder)

//including all the libraries used in our app such as angular
bundles.Add(
    new ScriptBundle("~/scripts/libraries")
        .Include("~/scripts/angular/angular.js")
        .Include("~/scripts/angular/angular-route.js")
        .Include("~/scripts/bootstrap.js")
        .Include("~/scripts/jquery.js")
        .Include("~/scripts/kendo/kendo.ui.core.js")
    );

//including all the css used in our app
bundles.Add(
    new StyleBundle("~/content/css")
        .Include("~/content/normalize.css")
        .Include("~/content/bootstrap/bootstrap.css")
        .Include("~/content/bootstrap/bootstrap-theme.css")
        .Include("~/content/kendo/kendo.common.css")
        .Include("~/content/kendo/kendo.blueopal.css")
        .Include("~/content/app.css")
    );

//including the javascript files in our app
bundles.Add(
     new ScriptBundle("~/scripts/app")
     .Include("~/app/app.js")
     .IncludeDirectory("~/app""*.js"true)
      );
  • Let’s create a HomeController and a correspond view. This serves the starting page for our angular app. Here is code for our MVC view

<html data-ng-app="AngularKendoBootstrapApp">
<head>
    <meta name="viewport" content="width=device-width" />
    <title> Angular Kendo Bootstrap Application</title>
    @Styles.Render("~/Content/css")
</head>
<body>

    <a href="/home">Home</a> <a href="/contact">Contact</a>
    <div data-ng-view>
        <div id="splash" class="splash">
            Loading ...
        </div>
    </div>
        @Scripts.Render("~/scripts/libraries")
        @Scripts.Render("~/scripts/app")
</body>
</html>

In the above as you see we defined an angular app “AngularKendoBootstrapApp” and included all the necessary javascript files

This completes our MVC setup. Let move to the Javascript part of our setup
  • Create the following directory structure for app folder. This is the directory structure we will use for our angular scripts.

  • In our app.js define the routing for our pages in the app as shown below:
angular.module('AngularKendoBootstrapApp', ['ngRoute'])
  .config(function ($routeProvider, $locationProvider) {

    $routeProvider
        .when("/home", {
                controller: "home",
                templateUrl: "/app/home/home.html"
            })
        .when("/contact", {
            controller: "contact",
            templateUrl: "/app/contact/contact.html"
        })
        .otherwise({ redirectTo: "/home" });
    $locationProvider.html5Mode(true);
});

We are done J. We built an Angular app from scratch without using any templates. Compile your project and run it.

You can find the source code of this project at my github site

You can also download the Visual Studio template file for this project from here.

Friday, July 11, 2014

Knockout Custom Array Data-bind

I am working on a scenario where I need to bind a div tag to multiple ko variables. I want to show these multiple ko variables as a comma separated string. One way to do this is to concatenate these variables while binding to the div element as shown below:

    <div data-bind="text: model.CostPrice() + ',' + model.SalePrice()"></div>

The above works great. But in my scenario I have to do this in multiple places. Instead of concatenating the strings within the binding, I wanted to implement a custom binding which takes multiple ko variables and concatenates these variables into strings. Here is my custom binding

    ko.bindingHandlers.displaytext = {
        init: function (element, valueAccessor, allBindingsAccessor, data) {
            var field = valueAccessor();

            var computedtext = ko.computed(function () {
                var disptext = "";
                for (var index = 0; index < field.length; index++) {
                    if (field[index]() !== undefined && field[index]() !== "") {
                        disptext += field[index]() + ", ";
                    }
                }
                return disptext;
            });

            ko.applyBindingsToNode(element, {
                text: computedtext
            });
        }
    };

As you see in the above custom binding, I defined a computed variable which concatenates all the passed in variables. Whenever there is a change in any of the input variables, the computed variable re-computes the concatenated string and bind it. Here is how I am using it

   <div data-bind="displaytext: [model.CostPrice, model.SalePrice]"></div>

With this custom binding attribute, I can pass any number of knockout variables (which are passed as an array) and show them as a concatenated string.