Wednesday, August 13, 2014

SPA with AngularJs

 

AngularJS is a JavaScript frame work which use to create dynamic web applications. Its runs with plain JavaScript and HTML, so you don’t need use any other things when you are creating a web applications. You can read and learn more about the AngularJs from this link. In this post going to explain about the steps needs to follow when creating a SPA (Single Page Application) with AngualrJS.

Open your visual studio and create an empty web application. Install AngularJS core and router files using NuGet. After that create a folder called “app”. In this folder going to hold the old AngularJS related scripts files. Inside of this folder create a file calle “app.js”. In this JavaScript file is going to initialize all configurations when angular start up. Folder structure would be like as shown in below.

app

---------controller

--------------main.js

--------------submain.js

---------app.js

views

---------main

------------main.html

index.html

inside app folder contain the controller folder. It hold two angular controllers such as main and submain. And there is views folder for keep all the views. There is another subfolder call “main” to hold the views belongs to main controller. Index view is the initial view start in the application. In app.js file place the following code snippets.

var app = angular.module('spaapp', ['spaapp.controllers', 'ngRoute']);

var appctrl = angular.module('spaapp.controllers', []);

app.config(['$routeProvider', '$locationProvider', function ($routeProvider, $locationProvider) {
    $routeProvider
      .when("/",
      {
          templateUrl: "views/main/main.html",
          controller: "main"
      })
      .when("/sub",
      {
          templateUrl: "views/main/submain.html",
          controller: "submain"
      })
      .otherwise({
          redirectTo: '/'
      });

    $locationProvider.html5Mode(true);
}]);
In here main module create as “spaapp”. Its getting inject with “ngRoute” and “spaapp.controllers”. The “ngRoute” use for client side routing inside the application and “spaapp.controllers” use as module of the controllers in the application. after that shows routing configuration of the application. When user navigate to root url, route configuration load the main controller with main.html view. As the same way it does for the “/sub” path.
So lets create content of the index.html view. 
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
    <base href="/" />
</head>
<body ng-app="spaapp">

  <ng-view></ng-view>

    <script src="Scripts/angular.min.js"></script>
    <script src="Scripts/angular-route.min.js"></script>
    <script src="app/app.js"></script>
    <script src="app/controller/main.js"></script>
    <script src="app/controller/submain.js"></script>
</body>
</html>
Now what we left to do is creation of the main and submain controllers.
main controller
appctrl.controller('main', ['$scope', function ($scope) {
    $scope.message = 'main';
}]);
In main controller use the controller module created earlier in app.js file. This controller inject with $scope for handle the model. In this controller bind message to the $scope property called “message”. Following shows the main.html view for the above controller. This view contain route for the sub controller.
main.html view
<p>The controller name is {{message}}!</p>

<a href="/sub"> Sub Controller </a>
submain controller 
appctrl.controller('submain', ['$scope', function ($scope) {
    $scope.message = 'sub main';
}]);

The submain controller is doing same thing as the main controller. In below showing a submain.html view. This view also same likes the main.html view. It has a link to navigate to the main view.

sub main view
<p>The controller name is {{message}}!</p>

<a href="/"> Back to Main Controller </a>

In this SPA, we load to views dynamically to the index.html. This magic happens through “<ng-view>” tag in the index.html. main and submain views get append to the “<ng-view>” tag when it called through the router. Route configuration handle the controller and view according to the route. Now run the application.
Main View
1_thumb[3]

Sub Main View, you can see url of the browser.

2_thumb[1]

So we created SPA using an AngularJs. Give a try on this.

Happy Coding wlEmoticon-smile[2]

Sunday, August 3, 2014

Windows 8.1 : Flyouts

In windows 8 apps development if wants to integrate flyout for app you don't have any straight forward way to do it. For this kind of a things I used popup control as flyout or third party library like callisto. But in windows 8.1 app development you don't need to be struggle like that way. Because now its integrate with base control library. 

Let's get a scenario like needs to get information from the button click. Now you can do this very simply way setting up the flyout property in the button. 

<Button x:Name="AddButton" Content="Add" Foreground="Black" Height="66" Margin="-3" Width="157" BorderBrush="Black" VerticalAlignment="Top" HorizontalAlignment="Right" FontSize="26.667"> <Button.Flyout> <Flyout Placement="Bottom"> <StackPanel Height="439" Width="294" HorizontalAlignment="Right" Margin="0,5,0,0"> <TextBlock Style="{StaticResource BaseTextBlockStyle}" Text="Add Task" Height="29" FontWeight="Bold" SelectionHighlightColor="{x:Null}" FontSize="21.333" Margin="10,0,10,20"/> <TextBlock HorizontalAlignment="Left" Height="24" Margin="10,0,0,10" TextWrapping="Wrap" Width="145" Text="Projects" FontSize="18.667"/> <ComboBox Height="35" Margin="10,0,10,10"/> <TextBlock HorizontalAlignment="Left" Height="20" Margin="10,0,0,10" TextWrapping="Wrap" Text="Task" Width="199" FontSize="18.667"/> <ComboBox Height="35" Margin="10,0,10,10"/> <TextBlock HorizontalAlignment="Left" Height="30" Margin="111,0,0,10" TextWrapping="Wrap" Text="Hours" Width="77" FontSize="18.667"/> <Slider Height="42" Margin="10,0"/> <TextBox Height="30" Margin="111,0,106,20" TextWrapping="Wrap" Text="1" TextAlignment="Center" BorderThickness="2"/> <CheckBox Content="Billable" Height="37" Margin="7,0,54,10" VerticalAlignment="Stretch" FontSize="18.667"/> <Button Margin="0,5,0,0" Content="Done" Width="120"/> </StackPanel> </Flyout> </Button.Flyout> </Button>

When you click on the add button flyout will shows up like below.


The place where flyout shows up can change using the placment property in the flyout. In above example I used placement position as bottom. You can select top, right, left, full or bottom as placement options. But this depends on the space available on the screen. 

This flyout can have one content item, because of that reason complex UI component must wrapped with StackPanel or Grid item. In this example I used StackPanel. Adding the click event to the button inside the flyout you can perform the action and hide the flyout programmatically.

Sunday, July 20, 2014

Use of ICommand in Windows 8.1 app

Recently I was creating a windows 8.1 app following a MVVM pattern. I was using RelayCommand class in WPF application to create commands that XAML can bind. But unable to build the project because CommandManger class not reference to the WinRT.  The RelayCommand class used for command bind shows in below.

using System; using System.Diagnostics; using System.Windows.Input; namespace WindowsAppMvvm { public class RelayCommand : ICommand { #region Members private readonly Action execute; private readonly Func&lt;bool&gt; canExecute; #endregion #region Constructor public RelayCommand(Action execute) : this(execute, null) { } public RelayCommand(Action execute, Func&lt;Boolean&gt; canExecute) { if (execute == null) throw new ArgumentNullException("execute"); _execute = execute; _canExecute = canExecute; } #endregion #region ICommand Members public event EventHandler CanExecuteChanged { add { if (_canExecute != null) CommandManager.RequerySuggested += value; } remove { if (_canExecute != null) CommandManager.RequerySuggested -= value; } } public Boolean CanExecute(Object parameter) { return _canExecute == null ? true : _canExecute(); } public void Execute(Object parameter) { _execute(); } #endregion } }
Error shown in visual studio.


To solve this issue need to define RelayCommand class without CommandManager. Inside ICommand Members region do following changes.

 1. Remove current CanExecuteChanged event handler and replace with following line
 
public event EventHandler CanExecuteChanged;
 2. Add following method.

public void RaiseCanExecuteChanged() { if (CanExecuteChanged != null) CanExecuteChanged(this, new EventArgs()); }
 Now problem solved and project build successfully.

Tuesday, June 10, 2014

File upload REST service

I needed to create REST service which have capability to upload the file sent from the any client application consume this service.  To achieve this used Web API to create REST service. Following code snippets shows the REST service method written in FileUpload controller.

  /// 
  /// Uploads the file.
  /// 
  /// 
  /// Status of the file upload.
  /// 
  /// 
  public async Task UploadFile()
  {
   if (!Request.Content.IsMimeMultipartContent())
   {
    throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
   }

   string root = HttpContext.Current.Server.MapPath("~/App_Data");
   MultipartFormDataStreamProvider provider = new MultipartFormDataStreamProvider(root);

   try
   {
    await Request.Content.ReadAsMultipartAsync(provider);
    return Request.CreateResponse(HttpStatusCode.OK);
   }
   catch (System.Exception e)
   {
    return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, e);
   }
  }

In this scenario client application would be MVC web application. Following shows code snippets for the view.
@{
    ViewBag.Title = "File Upload";
}

File Upload

@ViewBag.Message @using (Html.BeginForm("Index", "Home", FormMethod.Post, new { enctype = "multipart/form-data" })) { }

After needs to create controller action which can get the file from view and upload it via REST service. Action method code snippets shown in below. This controller contain with GET and POST action methods.
  /// 
  /// Indexes this instance.
  /// 
  /// 
  /// Result for the user given request.
  /// 
  [HttpGet]
  public ActionResult Index()
  {
   return View();
  }

  /// 
  /// Indexes the specified file.
  /// 
  /// 
  /// The uploaded file.
  /// 
  /// 
  /// Response for the status of the file upload.
  /// 
  [HttpPost]
  public async Task Index(HttpPostedFileBase file)
  {
   string uploadUrl = "http://localhost/FileUpload/api/FileUpload/UploadFile";

   if (file != null && file.ContentLength > 0)
   {
    try
    {
     using (HttpClient client = new HttpClient())
     {
      using (MultipartFormDataContent content = new MultipartFormDataContent())
      {
       BinaryReader br = new BinaryReader(file.InputStream);
       byte[] buffer = br.ReadBytes(file.ContentLength);
       br.Close();

       content.Add(new StreamContent(new MemoryStream(buffer)), "UploadedFiles", file.FileName);
       HttpResponseMessage httpResponse = await client.PostAsync(uploadUrl, content);

       if (httpResponse.IsSuccessStatusCode)
       {
        ViewBag.Message = "File uploaded successfully";
       }
      }
     }
    }
    catch (Exception ex)
    {
     ViewBag.Message = string.Format("ERROR: {0}", ex.Message);
    }
   }
   else
   {
    ViewBag.Message = "You have not specified a file.";
   }

   return View();
  }

Now run and test the application.


Tuesday, May 13, 2014

Sequence of SQL Query Statement

As a developer all of us write SQL queries for access and manipulate data in  the database. When retrieve data from database SQL query start with SELECT statement. In these SQL queries are create English-like manner. But its logical execution not process like that way. The SELECT statement logically execute in following order.

  1. FROM
  2. WHERE
  3. GROUP BY
  4. HAVING 
  5. SELECT
  6. ORDER BY 
Following SQL query retrieve employee detail from EmployeeLeave table. 


SELECT EmpId, FirstName, COUNT(*) AS NumLeaves
FROM EmployeeLeave
WHERE EmpId = 12
GROUP BY DepId, LeaveYear
HAVING COUNT(*) > 1
ORDER BY EmpId, DepId

But this query logically process in following manner. 

FROM EmployeeLeave
WHERE EmpId = 12
GROUP BY DepId, LeaveYear
HAVING COUNT(*) > 1
SELECT EmpId, FirstName, COUNT(*) AS NumLeaves
ORDER BY EmpId, DepId

Following shows the way of this query works,
  1. Queries the rows from EmployeeLeave table
  2. Filters only records where employee ID equal to 12
  3. Groups the records by department ID and leave year
  4. Filters only groups having more than one leave
  5. Selects for each group the employee ID, first name and number of leaves
  6. Order the rows in the output by employee ID and department ID
The knowing the way of logical execution of SQL query is very important when write the queries for our business scenarios. It give us more understand about how our query works and its a big help to structure the query as well.  

Saturday, April 26, 2014

PhoneGap App : Google Map MarkerClusterer

In last post I was described how to get current location and show it as marker in the map. Let's think a scenario which is you have to show lot of markers in the map. In this case map going to be the fill with markers and user can't get an idea on looking at the map. This going to be loose the user experience. So solution for this kind of a requirement is group the markers in the map. There are various approaches for achieve the solution for this. Today I'm going to explain one method belongs to Clustering which is MarkerClusterer. Clustering  is simplifies your data visualization by consolidating data that are nearby each other on the map in an aggregate form.

The MarkerClusterer is a client side library. This use grid-based clustering to a collection of markers. It works by iterating though the markers in the collection that you wish to cluster and adding each one into the closest cluster if it is within in a minimum square pixel bounds. For demo this approach I used the previous post implementation as basement. Actually this is a extending the previous post implementation.

To develop marker clusterer in your application first you have to reference it in your HTML page. You can download the markerclusterer.js from here. Other than there is no any changes in the HTML page from the previous post.

<!DOCTYPE html> <html> <head> <title>Map View</title> <link href="style/jquery.mobile-1.4.2.css" rel="stylesheet" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> </head> <body> <div data-role="page" id="map-page" data-url="map-page"> <div data-role="header"> <span style="align-content:center;">Map</span> </div> <div data-role="content" data-position="fixed" id="map_canvas"> <!-- map loads here... --> </div> <div data-role="footer"> Footer </div> </div> <!--Jquery--> <script type="text/javascript" src="scripts/jquery-1.9.1.min.js"></script> <!--Jquery Mobile--> <script type="text/javascript" src="scripts/jquery.mobile-1.4.2.js"></script> <!--Cordova--> <script type="text/javascript" src="scripts/cordova.js"></script> <!--Google Map--> <script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?v=3&amp;sensor=true&amp"></script> <!--Google Map Marker Cluster--> <script type="text/javascript" src="scripts/markerclusterer.js"></script> <!--Map View--> <script type="text/javascript" src="scripts/JS/MapView.js"></script> <script type="text/javascript"> $(document).ready( function () { var mapView = new PhoneGapMapApp.MapView(); mapView.init(); } ); </script> </body> </html>
In MapView.js added new methods for create collection of locations, load themarkers to the map, initiate and create the clusterer in the map. After fire devereday event belongs to cordova create the location collection. after the start to create the marker belongs to relevant location in the collection. after create marker collection form locations initiate and create the cluster view in the map. You can see the implementation in below code.

PhoneGapMapApp = {} PhoneGapMapApp.MapView = function () { this._map = null; this._currentLocation = null; this._locations = null; this._markerClusterer = null; } PhoneGapMapApp.MapView.prototype = { init: function () { this._defaultLocation = new google.maps.LatLng(6.5006036, 80.2711642); this._attachEventHandlers(); }, /** * Attach event handlers. */ _attachEventHandlers: function () { document.addEventListener("deviceready", this._onDeviceReady(this), false); }, /** * device APIs are available. */ _onDeviceReady: function (obj) { console.log('device ready'); obj._getRealContentHeight(); obj._loadMap(); obj._identifyCurrentLocation(); obj._loadLocationData(); obj._loadMapMarkers(); }, /** * Setup the content hieght. */ _getRealContentHeight: function () { var header = $.mobile.activePage.find("div[data-role='header']:visible"); var footer = $.mobile.activePage.find("div[data-role='footer']:visible"); var content = $.mobile.activePage.find("div[data-role='content']:visible:visible"); var viewport_height = $(window).height(); var content_height = viewport_height - header.outerHeight() - footer.outerHeight(); if ((content.outerHeight() - header.outerHeight() - footer.outerHeight()) <= viewport_height) { content_height -= (content.outerHeight() - content.height()); } $('#map_canvas').height(content_height); }, /** * create map. */ _loadMap: function () { var myOptions = { zoom: 4, center: this._defaultLocation, mapTypeId: google.maps.MapTypeId.ROADMAP }; this._map = new google.maps.Map(document.getElementById('map_canvas'), myOptions); }, /** * Identify current location. */ _identifyCurrentLocation: function () { if (navigator.geolocation) { browserSupportFlag = true; var that = this; var currentPositionCallback = function (position) { that._identifyCurrentLocationCompleted(position); }; var noGeolocationCallback = function () { that._handleNoGeolocation(browserSupportFlag); }; navigator.geolocation.getCurrentPosition( currentPositionCallback, noGeolocationCallback, { 'enableHighAccuracy': true, 'timeout': 20000 }); } else { browserSupportFlag = false; this._handleNoGeolocation(browserSupportFlag); } }, /** * Handles the situation when current location not found * or not allow from the user for access current location. */ _handleNoGeolocation: function (errorFlag) { this.goTo(this._defaultLocation); }, /** * Current location identify operation success callback. */ _identifyCurrentLocationCompleted: function (position) { this._currentLocation = new google.maps.LatLng( position.coords.latitude, position.coords.longitude); this.goTo(this._currentLocation); }, /** * Show current location in the map. */ goTo: function (position) { this._setMarkerForLocation(position); this._map.setCenter(position); }, /** * Set marker for location. */ _setMarkerForLocation: function (latLng) { var marker = new google.maps.Marker({ position: latLng, map: this._map, title: "You are here !!!" }); }, /** * Load markers for the map. */ _loadMapMarkers: function () { if (this._locations != null) { this._displayParksListInMap(); } }, /** * Create marker list from location details. */ _displayParksListInMap: function () { var markers = []; for (var locationIndex = 0; locationIndex < this._locations.length; locationIndex++) { var location = this._locations[locationIndex]; var marker = null; //Add new location to the markers var latLng = new google.maps.LatLng ( location.LocationLatitude, location.LocationLongitude ) marker = new google.maps.Marker ({ position: latLng, title: location.LocationName }); markers.push(marker); } this._initializeMarkerClusterer(markers); }, /** * Initialize marker cluster view in the map. */ _initializeMarkerClusterer: function (markers) { this._markerClusterer = new MarkerClusterer( this._map, markers, { maxZoom: 18, gridSize: 15 }); }, /** * Create local static data. */ _loadLocationData: function () { var location = {}; var locations = new Array(); location = { LocationID: 01, LocationName: 'Asiri Surgical Hospital', LocationLongitude: 79.880167, LocationLatitude: 6.894737 }; locations.push(location); location = { LocationID: 02, LocationName: 'The Asiri Central Hospital', LocationLongitude: 79.8658391, LocationLatitude: 6.9205805 }; locations.push(location); location = { LocationID: 03, LocationName: 'Majestic City', LocationLongitude: 79.8547562, LocationLatitude: 6.8940211 }; locations.push(location); location = { LocationID: 04, LocationName: 'Liberty Plaza', LocationLongitude: 79.8515386, LocationLatitude: 6.911252 }; locations.push(location); this._locations = locations; } }

Friday, April 4, 2014

Show current location of the PhoneGap map app

In last post I was described the way to develop PhoneGap map app using google map API v3. In this post Im going to show you how to get the user current location and show it on the map as marker. For this approach I use same code I wrote for the previous post. In below showing the implementation I did to achieve this task.

PhoneGapMapApp = {} PhoneGapMapApp.MapView = function () { this._map = null; this._currentLocation = null; } PhoneGapMapApp.MapView.prototype = { init: function () { this._defaultLocation = new google.maps.LatLng(6.5006036, 80.2711642); this._attachEventHandlers(); }, /** * Attach event handlers. */ _attachEventHandlers: function () { document.addEventListener("deviceready", this._onDeviceReady(this), false); }, /** * device APIs are available. */ _onDeviceReady: function (obj) { console.log('device ready'); obj._getRealContentHeight(); obj._loadMap(); obj._identifyCurrentLocation(); }, /** * Setup the content hieght. */ _getRealContentHeight: function () { var header = $.mobile.activePage.find("div[data-role='header']:visible"); var footer = $.mobile.activePage.find("div[data-role='footer']:visible"); var content = $.mobile.activePage.find("div[data-role='content']:visible:visible"); var viewport_height = $(window).height(); var content_height = viewport_height - header.outerHeight() - footer.outerHeight(); if ((content.outerHeight() - header.outerHeight() - footer.outerHeight()) <= viewport_height) { content_height -= (content.outerHeight() - content.height()); } $('#map_canvas').height(content_height); }, /** * create map. */ _loadMap: function () { var myOptions = { zoom: 4, center: this._defaultLocation, mapTypeId: google.maps.MapTypeId.ROADMAP }; this._map = new google.maps.Map(document.getElementById('map_canvas'), myOptions); }, /** * Identify current location. */ _identifyCurrentLocation: function () { if (navigator.geolocation) { browserSupportFlag = true; var that = this; var currentPositionCallback = function (position) { that._identifyCurrentLocationCompleted(position); }; var noGeolocationCallback = function () { that._handleNoGeolocation(browserSupportFlag); }; navigator.geolocation.getCurrentPosition( currentPositionCallback, noGeolocationCallback, { 'enableHighAccuracy': true, 'timeout': 20000 }); } else { browserSupportFlag = false; this._handleNoGeolocation(browserSupportFlag); } }, /** * Handles the situation when current location not found * or not allow from the user for access current location. */ _handleNoGeolocation: function (errorFlag) { this.goTo(this._defaultLocation); }, /** * Current location identify operation success callback. */ _identifyCurrentLocationCompleted: function (position) { this._currentLocation = new google.maps.LatLng( position.coords.latitude, position.coords.longitude); this.goTo(this._currentLocation); }, /** * Show current location in the map. */ goTo: function (position) { this._setMarkerForLocation(position); this._map.setCenter(position); }, /** * Set marker for location. */ _setMarkerForLocation: function (latLng) { var marker = new google.maps.Marker({ position: latLng, map: this._map, title: "Greetings!" }); }, }
The _identifyCurrentLocation method called by after create the map object. In this method has success callback and failure callback. In _setMarkerForLocation method set marker for the current location. If current location not found then app will shows the default location.