Monday, April 18, 2016

Dynamically Loading AngularJS Controllers using JQuery

Hi, My code is not new and most of the code is copied from

It acts as useful code snippet for myself and anyone who is looking for one.

I adapted the code to load the js files using JQuery instead of RequireJS, and it follows predefined naming convention for url, templates and js files:
  1. Url and file name: all small letters with each word separated with - (hyphen).
  2. Controller name: first letter of each word is caps with no gaps and ends with 'Ctrl'.
Save $controllerProvider as a property of angularjs app module and use RouteProvider object in $routeProvider config:
   var app = angular.module("app", ['ngRoute']);
        app.config(function ($routeProvider, $controllerProvider) {
            var route = new RouteProvider(); 
            .when('/view-one', route.resolve("view-one"))
            .when('/view2', route.resolve("view2"))
            .when('/view3', route.resolve("view3"))
                redirectTo: '/'

            app.register =
                controller: $controllerProvider.register

RouteProvider takes care of dynamically loading of js controller files using Jquery:
       var RouteProvider = function () {
            var scriptPath = "/Scripts/";
            var templatePath = "/Templates/";

            this.resolve = function (name) {
                var route = {};
                route.templateUrl = templatePath + name + ".html";
                route.controller = getControllerName(name) + "Ctrl";
                route.controllerAs = "vm";
                route.resolve = {
                    load: ['$q', '$rootScope', function ($q, $rootScope) { return loadController($q, $rootScope, scriptPath + name + ".js"); }]
                return route;
            var getControllerName = function (name) {
                var ctrlName = "";
                name.split("-").forEach(function (input) { ctrlName += input.substring(0, 1).toUpperCase() + input.substring(1).toLowerCase(); });
                return ctrlName;
            var loadController = function ($q, $rootScope, path) {
                var defer = $q.defer();
                    dataType: "script",
                    cache: true,
                    url: path
                }).done(function () { 
                return defer.promise;

Register the controller (view3.js) after load with $controllerProvider:
(function (app) {
    app.register.controller('View3Ctrl', ['$http', function ($http) {
        var vm = this;
        vm.value = "Hello from view3";
        vm.gotHttp = !!$http;
})(app || angular.module("app"));

view3.html template code:
<div> <h3>view three</h3> <span ng-bind="vm.value"></span> <br /> <div>got $http - {{vm.gotHttp}}</div> </div>

Libraries used: jquery, angularjs v1.4 and angular-route

Monday, November 10, 2014

Asp.Net MVC Dynamic View

Dynamic type view is not new, in this post i explain how a single view supports multiple types of Models.
As We know, a view created with dynamic type gets neither intellisense support nor strongly typed templated helpers and you have to deal with the model's properties which may be intrinsic or complex and may also be readonly.
In order to show you that a single view supports any type viewModel, i have created 3 Model classes:
Hotel - which contains basic and complex type properties. (complex type here List<HotelRoom>)
Customer - which contains basic and complex type properties. (complex type here is HotelRoom type)
HotelRoom - which contains only basic types.

These are the ViewModels passed to the view:
  1. List<HotelRoom>
  2. Hotel
  3. Customer
Below are the screenshots for each viewModel rendered by single view:
 ViewModel - List<HotelRoom>

ViewModel - Customer

ViewModel - Hotel

What View contains?
The view contains the logic to iterate over the ViewData.ModelMetadata.Properties to generate label and control for each field and also checks for readonly metadata for a field and injects disabled attribute into the html control.
For complex type handling whether its a property or ViewModel, calling the Editor() will takes care of rendering it. If the ViewModel type is a collection, we have to provide a custom EditorTemplate (partial view) for the type used in the collection.
Note: For a property which is applied with readonly metadata attribute on a Model, it doesn't get its value submitted (even if you use hidden field it doesn't works) means it gets null value when (form post) submitted.

I don't recommend this approach for real scenarios, consider it as an example case where you can learn something from its code.

This sample contains:
  • 2 View files (view, partial-view)
  • 1 Class file (contains 3 Models)
  • 1 Controller file (3 Get Action methods and 3 Post Action Methods)
You can find the above files for download (only MVC folders):
Dowload Link

Monday, February 17, 2014

AngularJS CRUD Grid


      I created a sample web application which showcases how to do CRUD operations + search + sort + page on a Table (lets call it DataGrid) using AngularJS, Bootstrap for standalone version and angular-notifications, NodeJS, MySql for servercode version.

What I learned:
    While am doing edit functionality for this application, i tried to get the edit textboxes values (DOM code) into the controller, after i learned somewhere the good practice - "DOM code should not be used in controller" - i wanted to try mapping bindings to these textboxes.
    First i approached with adding edit option (property) in each item instance, later i realized its just a waste of code repetition, so i came with edit option on $scope which maintains just ID of item instance in edit-mode. Later i refined it as 'updateItem' object on $scope, it maps binding to these textboxes in edit-mode and maintains values and error statuses. This object is also reused in insert operation.

While developing, i faced a challenge, how can i track 'records count' when angularjs built-in filter is used for search?
I found a way, i tracked it in 'paging' filter (which i created for page navigation on grid). To get access of 'records count' property of $scope into filter, there is no easy way, of course we can pass scope from UI into filter as parameter, but that's not good practice, so i had to create a service (SharedObject) which contains properties shared between controller and filter.

I created another service (HelperService), so that scope related logic should not get mixed-up with unrelated (reusable, independent) code blocks.

Javascript coding has:

1 Controller - appCtrl
2 Services:

  • RecordCount - which tracks total records count used between controller and paging filter.
  • HelperService - provides generic functionalities: validation operation, deletes a record from set of records, parses error object.

1 Filter:
paging - to support page navigation on the grid.

You can find both standalone (html), and restful supported versions for download below.
I haven't created test-cases for unit-testing the angular code.

RESTful support:

       Javascript code is implemented slightly different here than standalone version.

For restful support i have used:
at serverside:

  • node.js with express package used as restful server.
  • for database, i have used mysql.

at clientside:
  • ngResource - angularjs directive which is useful in restful coding.
  • ng-notification - is a third-party angularjs module, used as notification service.

Why MySql?
         I used mysql because my system (Ubuntu) already has it as part of LAMP stack. I don't want to install another DB (like, MongoDB) just because for this Application. Of course you can change app code to use MongoDB with minor changes if you like.
I used Phpmyadmin to create DB and Table, you can find the scripts in sql file in download Zip.

What i learned:
Mysql returns date with GMT time, but not with serverside local time (here IST).
It creates problem, it returns date with one day less with GMT time, because it converts serverside local time to GMT time while returning json. To resolve it, i did convert json date string to date object then manually create correct date string. (browser by default coverts GMT date to local (here IST: +5:30) date). If you think there is a better solution, you can share in comments.

I modified CSS, js code of ng-notification, to suit our purpose and to support bootstrap for icons.

For testing the restful server, i have used 'Postman' plugin for Chrome. (you can find 'postman_dump' file in downloads for your local import and test). Application development done in Ubuntu OS with sublime text editor.

In download Zip file, i haven't included node.js dependencies - express, mysql npm packages - you have to add them manually into unzipped folder (TestOne) or, since the Zip file has package.json, you can try running "npm install" using CLI pointing to the unzipped folder to install dependencies for the restful server (WebSqlRest.js).

How to Execute:
Run server from CLI pointing to the unzipped folder:

$ node WebSqlRest.js

Now open browser and type the url:

References:   (for color themes)

Download and Demo:
Check the Demo here (and save locally)!
Download the Zip file here (restful)!

Saturday, May 18, 2013

Ways of object serialization using C#

       Here i discuss how to serialize object state to a file in different formats, showing you 5 different serialization formats plus how to read object from config file:
  • Binary
  • XML
  • JSON
  • Base64
  • DataContract
  • Object in config file
I took a simple 'Person' class to be used for serializations and 'ConfigPerson' class for object read from config file. I used 'ConfigPerson' class for config read, since 'Person' class cant be used for config specific implementation.

For serialization process i created a component called 'Serializer' with below classes. 
'ObjectSerialize' class contains the nested classes for each serialization format and access methods for these classes. Each nested class inherits from abstract base class 'BaseFileChecker' (for logic reuse: file create & open) and implements 'IFormat' interface (for methods decouple: serialize & deserialize).
Check each nested class for format specific code.

For Testing this component i created a console application.
Pressing 1 shows the below result which is showing 'ConfigPerson' object read from app.config file.
Pressing any other key, prompts for serialization formats (applied on 'Person' class) 

When completed all 5 formats, you will see below files in your folder (folder name hardcoded in console project, change it for your requirement).

 Share your thoughts, alternative solutions and other serialization formats in below comments.


Download the project solution as Zip file.

Saturday, April 13, 2013

Drill through rdlc report with empty dataset

    Here i will explain how to create a simple rdlc drillthrough report with filtering option and dynamic datasource/dataset updated with custom object collection programmatically.

Master Report
Drillthrough Report
Below are the step by step explanation to accomplish:
  • Create a web project from VisualStudio.
  • Add a rdlc file and name it LocalReport.rdlc
  • Add a typed dataset (.xsd) and name it DataSet1.xsd
  • Add two tables manually (right-click select from designer) with schema as in below image.

  • Now open LocalReport.rdlc designer, Add a Table Control by dragging it from toolbox onto report body.
  • From Report Data pane, click New -> Dataset, from the wizard, set: Name: DataSet1    Data source: DataSet1    Available datasets: Emp      then click ok. (check image below)

  • Now Report Data pane shows DataSet1 with its fields. Drag these 3 fields onto report table one by one and set its (first-row) header with background color.
  • Add textbox control for Report Title with value - Emp Details and set its background, foreground colors from its properties.
  • Add a parameter: from Report Data pane, click New -> Parameter and name it - pDesignation

  • Select report table, right-click for Tablix properties, select Filters option and set its fields as per below image.

  • Add a class file to the project and name it Entities.cs
  • Add 2 classes - Emp, EmpDetails with properties similar to tables schema in DataSet1.xsd
  • Also add static class DataProvider with 2 methods which returns collection of above types.(check code in download files)

  • Add an aspx file to the project and name it LocalReport.aspx, add a dropdownlist for filtering and ReportViewer controls.
  • Assign the LocalReport.rdlc to ReportViewer from webpage in designer mode.
  • At code-behind, update the Datasource with custom Emp Collection from DataProvider and assign it to report.
  •  Update the dropdownlist with unique Emp Designations and handle change-event to update report.
Till now we have completed single master report with filtering option.
You can give it a Run to test filtering.

Adding Drillthrough feature:
  • For Drillthrough we need another report, add a report to the project and name it SubReport.rdlc
  • Now open SubReport.rdlc designer, Add a Table control by dragging it from toolbox onto report body.
  • From Report Data pane, click New -> Dataset, from the wizard, set Name: DataSet1    Data source: DataSet1    Available datasets: EmpDetails           then click ok.
  • Now Report Data pane shows DataSet1 with its fields.
  • Drag 3 fields except EmpID onto report table one by one and set its (first-row) header with background color.
  • Add textbox control for Report Title with value - Emp Details (sub Report) and set its background, foreground colors from its properties.
  • Add a parameter: from Report Data pane, click New -> Parameter and name it - pEmpID
  • Select report table, right-click for Tablix properties, select Filters option and set its fields: Expression: [EmpID]      Operator: =     Value: [@pEmpID]
  • Now update the master report LocalReport.rdlc to support drillthrough
  • Open LocalReport.rdlc designer, right-click EmpID cell (not header), select Textbox properties -> Action and set fields as per below image.
  • Style the EmpID to blue color and decorate it with underline. 
  • Open LocalReport.aspx (in source mode) and add this attribute to the ReportViewer: ondrillthrough="ReportViewer1_Drillthrough" 
  • From its code-behind, write this code to handle drillthrough link.

Thats all, Now Run the application.

Note: Drillthrough reports are not linked reports.
Download: The Zip file and check the code.

Saturday, December 1, 2012

IndexedDB.js updated

      IndexedDB.js is a JavaScript library file, which provides api to easily connect and do transactions for data storage and retrieval on in-browser database system (IndexedDB). Its older version is used in my previous post - PetStore, the file been updated to support many if not all features which IndexedDB supports. Its api offers the following operations:
  1. Opens DB connection (creates new if not exists)
  2. Add a data record 
  3. Bulk data insertion
  4. Updates a record
  5. Deletes a record
  6. Get single record (by key)
  7. Get all records
  8. Get records count
  9. Clear/delete all records
       A sample html page along with this file is provided for download, which showcases many of the above features (except, bulk insertion). This html uses Knockout.js, download it to check its working, and how to use this api (don't try it from filesystem, run it from web server).
sample html in action

       From screenshot, you can see grid supports inline edit, delete and insertion, and they can be performed simultaneously. The bottom portion shows the status or result of all operations.
For supporting browsers check my previous blog post.

Download the Zip file or check the demo.

Tuesday, November 27, 2012

PetStore web App using Knockout and IndexedDB

         PetStore is a web application (SPA? you decide), which shows how we can store large amounts of data at clientside (browser) and also works in offline. Presently it doesn't relies on web server to process any logic or storage. It is self-sufficient and works pure clientside (except for first time serve, and when offline & web data are deleted).

Why IndexedDB?
         The older "Web Database api" (aka WebSQL) became obsolete and replaced by indexedDB.  IndexedDB stores large amounts of data in JSON format at clientside. For data storage limits check the site references below (it could be unlimited). You can also find my old post on - Web Database api.
         Browsers supporting IndexedDB provided Async api to communicate with it. Because of lack of support, Sync communication approach may be omitted in future from W3C specification.

       Knockoutjs is a javascript MV* framework, provides two-way data bindig using MVVM pattern. In this application, the temporary data and state is maintained by knockout until data gets flushed into DB, during that time you can do all CRUD operations.

Features of PetStore:

  • CRUD operations using knockout.
  • uses browser built-in validations.
  • stores data in IndexedDB.
  • works in offline.
      The PetStore contains only 3 screens: Add/Edit, Unsaved, Saved Records. Check the screenshots below for each screen. With this application we can do: 
  • Add or Edit Pet details.
  • Check the unsaved records to decide for edit or delete and 
  • Finally save all records into IndexedDB and show them (even after revisit and offline).

Initial screen - Add a Pet
Unsaved Records

Edit and update Pet details

Saved records from IndexedDB

         Download the Zip file (check link below) and try running the application for yourself. For web server i have used NodeJS (httpster), but you can use any of your preferred web server. This Zip file contains the code files, wherein the functionality specific code is segregated into different files (like IndexedDB.js, ko_VM.js), which makes easy to understand and debug code. Out of them, its worth mentioning IndexedDB.js file, it provides the api to communicate with browser's storage - IndexedDB. (following standards: it works with latest version of browsers. Check the supported versions below). To better make use of this js file, i also provided another html "IndexedDB_Test.html", so that you can understand its working. The limitations of this api is: Delete and Update operations are not implemented, but you can: OpenDB, Read and Write.

Supported browsers: 
Tested on Chrome 23 and Firefox 16.02. IE10 may also support.


Download Link:

IndexedDB.js file has been updated, check the new post.