Angular2

I have being playing around with Angular2 for last couple of months.

Here is my list of links on Angular2 that helped me in my journey:

Functional Reactive Programming(FRP) in Angualr2

 

AngularJs scripts and minification

AngularJS provides Dependency Injection where a controller, service or module can expect Angular to pass the dependencies.

For e.g. if we have two services and a controller then controller can get the service dependency by writing the formal parameter in it’s constructor with the same name as service name.

var myModule = angular.module('simpleApp',[]);
myModule.service('dataService',function($http){
	this.getData = function() {
		return $http.get('/some/url');
	}

});
myModule.controller('simpleController',function($scope, dataService){
	dataService.getData().then(function(data){
		$scope.data = data;
	});
});

In the code above, simpleController is getting the dataService dependency because the parameter is also name as dataService. If the name is something else Angular will not be able to fulfill the dependency.

JavaScript Minification

With JavaScript minification the same JavaScript code will look like this

var myModule=angular.module("simpleApp",[]);

myModule.service("dataService",function(e){this.getData=function(){return e.get("/some/url")}});

myModule.controller("simpleController",function(e,t){t.getData().then(function(t){e.data=t})})

Due to minification the parameters have been renamed to a smaller length name like ‘e’, ‘t’. As now the service parameter name in simpleController is ‘t’ AngularJS will not be able to fulfill the dependency.

Dependency Injection with JavaScript minification

To enable DI we have to write controller and service methods with an array whose elements are list of all parameter names in string followed by the function.

var myModule = angular.module('simpleApp',[]);
myModule.service('dataService',[ '$http', function($http){
	this.getData = function() {
		return $http.get('/some/url');
	}

}]);
myModule.controller('simpleController',['$scope', 'dataService', function($scope, dataService){
	dataService.getData().then(function(data){
		$scope.data = data;
	});
}]);

And the code post minificaiton

var myModule=angular.module('simpleApp',[]);

myModule.service('dataService',['$http',function(e){this.getData=function(){return e.get('/some/url')}}]);

myModule.controller('simpleController',['$scope','dataService',function(e,t){t.getData().then(function(t){e.data=t})}])

Note the strings are not getting changed so now AngularJS will pass ‘dataService’ to parameter

‘t’ in the above minified code.

Alternatively, if you are not using module constructor and service calls then you can set $inject as array of parameter names.

var myModule = angular.module('simpleApp',[]);
function dataService($http){
this.getData = function() {
  console.log('called getData');
		return  'done';
	};
};
dataService.$inject = ['$http'];
myModule.service('dataService', dataService);
	
 function simpleController($scope, dataService){
	$scope.msg = 'loading'; 
   
     $scope.msg = dataService.getData();
	  
 }
 simpleController.$inject = ['$scope','dataService'];
 
 myModule.controller('simpleController',simpleController);

RemoteDataSource in Upshot.js

RemoteDataSource in Upshot.js can be used to fetch and save data using DataProvider.

Let’s see it’s constructor.

RemoteDataSource takes an options object as single parameter.

The options can have following parameters:

1. bufferChanges: (Optional) If ‘true’, edits to model data are buffered until RemoteDataSource.commitChanges.  Otherwise, edits are committed to the server immediately.
            
2. result:
(Optional) The observable array into which the RemoteDataSource will load model data.
       
3. dataContext:
(Optional) A DataContext instance that acts as a shared cache for multiple DataSource instances.  When not supplied, a DataContext instance is instantiated for this RemoteDataSource.
       
4. entityType:
The type of model data that will be loaded by this RemoteDataSource instance.
       
5. provider:
(Optional) Specifies the DataProvider that will be used to get model data and commit edits to the model data.  Defaults to upshot.DataProvider which works with System.Web.Http.Data.DataController.
       
6. providerParameters:
(Optional) Parameters that are supplied to the DataProvider for this RemoteDataSource and used by the DataProvider when it gets model data from the server.
       
7. mapping:
(Optional) A function (typically a constructor) used to translate raw model data loaded via the DataProvider into model data that will be surfaced by this RemoteDataSource.
       

RemoteDataSource have four public methods:

1. setSort : Establishes the sort specification that is to be applied as part of a server query when loading model data.

Parameter: sort (required)

Should be supplied as an object of the form { property: <propertyName> [, descending: <bool> ] } or an array of ordered objects of this form.
 
When supplied as null or undefined, the sort specification for this RemoteDataSource is cleared.

2. setFilter : Establishes the filter specification that is to be applied as part of a server query when loading model data.

Parameter: filter (required)

Should be supplied as an object of the form { property: <propertyName>, value: <propertyValue> [, operator: <operator> ] } or an array of ordered objects of this form.
 
When supplied as null or undefined, the filter specification for this RemoteDataSource is cleared.

3. refresh: Initiates an asynchronous get to load model data matching the query established with setSort, setFilter and setPaging.

Parameters:

  1. options (optional) : There are no valid options recognized by RemoteDataSource.
  2. success (optional) : A success callback with signature function(entities, totalCount).
  3. error(optional): An error callback with signature function(httpStatus, errorText, context).

OData access using jsonp

The upshot.js ver. 1.0 does not support jsonp calls. To enable jsonp I have modified the DataProvider.OData get method enable jsonp callback like this.

var jsonpCall ;
            if (parameters) {
                operation = parameters.operationName;
                operationParameters = parameters.operationParameters;
                jsonpCall = parameters.jsonpCall ? (parameters.jsonpCall === true): false;
            }
            if(jsonpCall){
              OData.defaultHttpClient.enableJsonpCallback = true;
             }

Using odata provider access Netflix OData :

(function () {
    var Netflix = window.Netflix = window.Netflix || {};

    Netflix.Movie = function (properties) {
        var self = this;

        self.Name = properties.Name;
        self.ShortName = properties.ShortName;
        self.ShortSynopsis = properties.ShortSynopsis;
        self.AverageRating = properties.AverageRating;
        self.ReleaseYear = properties.ReleaseYear;
        self.Runtime = properties.Runtime;

    }
    Netflix.Movie.Type = "Title:#Netflix.Catalog.v2"

    Netflix.CourseViewModel = function (options) {
        var self = this;

        var dataprovider = new upshot.ODataDataProvider();
        var courseDataSourceParameters = {
            provider: dataprovider,
            providerParameters: { url: options.serviceUrl, dataType: 'jsonp', operationName: "Titles", operationParameters: { "$top": "10"}, jsonpCall : true },            
            entityType: Netflix.Movie.Type,
            bufferChanges: true
        };
        var courseDataSource = new upshot.RemoteDataSource(courseDataSourceParameters);
        self.Titles = [];
        courseDataSource.refresh({}, function (entities, totalCount) {
            self.Titles = [];
            $.each(entities, function (index, item) {
                var entity = new Netflix.Movie(item);
                self.Titles.push(entity);
            });

            alert("Total movies loaded " + self.Titles.length);
        });

    }

})();

Upshot.js

This post is part of series of post on Single Page Application using ASP.NET MVC 4. We will explore the upshot, nav and history JavaScript libraries in this post.

What is Upshot.js?

Upshot is a new JavaScript library coming out of Microsoft. It’s based on previously previewed JavaScript library RIA/JS.  It is available through NuGet http://nuget.org/packages/upshot. As it is relatively undocumented, expect some of what is written below to change.

Upshot is for data access and related functionalities like paging, sorting, change tracking. Upshot.js is designed to work with DataController and oData (only data reading).

Objects provided by Upshot

  • EntitySource :  a wrapper of array of Entities which are observable. provides method to bind/unbind events
  • EntityView : inherits from EntitySource and provides change tracking on it
  • DataSource : inherits from EntityView and add paging, sorting and filterting support on it.
  • RemoteDataSource 
  • LocalDataSource
  • DataProvider : a wrapper over jQuery ajax to get and submit entity values
  • ODataDataProvider
  • riaDataProvider
  • EntitySet : inherits from EntitySource and provides change tracking on EntityType. This object does the heavy lifting of managing entities
  • DataContext
  • AssociatedEntitiesView

TODO: Update more about these objects

Usage of Upshot in ASP.NET MVC4 SPA

On creating a Single Page Application controller, we got code generated for the View and ViewModel. In the ViewModel code we can some usage of Upshot.

Creating RemoteDataSource

var gridDataSource = new upshot.RemoteDataSource(dataSourceOptions);

var editorDataSource = new upshot.RemoteDataSource(dataSourceOptions);

The RemoteDataSource are created with dataSourceOptions. DataSource options contains property values for dataProvider parameters ( url and oprationName), entityType , bufferChanges, mapping

Fetching data using DataSource

self.todoItems = gridDataSource.getEntities();

self.editingTodoItem = editorDataSource.getFirstEntity();

In the above code getEntities() method is used to get all TodoItem entities, and getFirstEntity() to get first TodoItem entity.

Another way to load data is to call refresh.

// Load and begin editing an existing todoItem instance

editorDataSource.setFilter({ property: "TodoItemId", value: Number(navEntry.params.edit) }).refresh();

// Not editing, so load the requested page of data to display in the grid

gridDataSource.refresh();

Saving data using DataSource

editorDataSource.commitChanges(function () {

                self.successMessage("Saved TodoItem").errorMessage("");

                self.showGrid();

            });

Deleting data using DataSource

editorDataSource.deleteEntity(todoItem);

Knockout.js

This post is part of series of post on Single Page Application using ASP.NET MVC 4. We will explore the knockout JavaScript library in this post.

What is Knockout.js?

Knockout.js is a JavaScript library for building HTML UI using Model-View-ViewModel (MVVM) pattern. The library is MIT licensed and source code is hosted on GitHub at https://github.com/SteveSanderson/knockout and project web hosted at http://knockoutjs.com/

Salient features of this library are:

  • Declarative bindings. A way to bind UIs to underlying data model using declarative bindings like data-bind=”text: firstName”
  • Dependency tracking. The build in dependency tracking updates the right UI when the underlying data changes by doing dependency check.
  • Templating

What is MVVM?

Model-View-ViewModel is a design pattern for building user interfaces.

  • Model: an application’s persisted data.
  • View: an application’s visible, interactive UI component.
  • ViewModel: In MVVM ViewModel is the an abstract layer to separate View and Model. ViewModel is a code based representation of data and operations on a UI.

Using Knockout.js

ViewModel in Knockout.js is a JavaScript object like:

var contact = {

    firstName : 'John',

    lastName  : 'Clark',

    email     : 'john.clark@company.com'

}

To bind this to UI, data-bind attribute are used like:

Contact's first name is  <span data-bind="text: firstName"> </span> 

 

For binding view to viewmodel, call Knockout.js activateBindings method as given here:

ko.activateBindings(contact);

To automatically update UI when the data model changes, we need to use Knockout’s observable as given below:

var contact = {

    firstName   : ko.observable('John'),

    lastName    : ko.observable('Clark'),

    email       : ko.observable('john.clark@company.com')

};

Built-in bindings:

  1. text : use text binding to display text value
  2. html : use html binding to display HTML
  3. css : use css binding to add or remove CSS classes
  4. style : use style binding to add or remove style values to the DOM node
  5. attr : use attr binding to
  6. visible : use visible binding to control the DOM element’s visibility
  7. foreach : use  foreach to loop around array and create markup on them
  8. if : use if to control a section of markup’s visibility
  9. ifnot : similar to if binding but works if the conditional is false
  10. with : use with in templates for creating new binding context
  11. click : use click binding to add an event handler to the click event to elements like a, input and buttons
  12. event : use event  binding to add an event handler to specified events like mouseover, mouseout, keypress, keydown etc. on the DOM element
  13. submit : use submit binding to add an event handler to the DOM node which would be called when the element value is being submitted like in case of form submit
  14. enable : use enable  binding to enable the DOM element based on the specified boolean expression. This is typically used for DOM elements like input, select, textarea.
  15. disable : use disable binding to disable the DOM element based on the specified boolean expression
  16. value : use value binding to  link the DOM element’s value with a property in view model. Typically used with input, select, textarea
  17. hasfocus : use hasfocus  binding to link a DOM element’s focus state with a property in view model
  18. checked : use checekd  binding with checkbox or radio button to link it with property on view model
  19. options  : use options binding to control the options  of a select control (<select>) 
  20. selectedOptions : use selectedOptions binding to control the elements selection in a multi-select list. Use this with <select> element and options binding
  21. uniqueName :
  22. template : use template  binding to render a templates output to the associated DOM element

In addition to the built-in bindings, knockout.js supports creating custom bindings.