Saturday, August 13, 2016

AngularJS - Bootstrap Datepicker Model Formatter

I have case to show datepicker for textbox, we can simply bind DateString field to textbox and update. But if we use BootStrap uibDatePicker then it requires to format as Date object before binding to ngModel.

So to resolve this issue, i have created directive to format ngModel value before binding and also parse back to string before updating to controller.

To check how to create BootStrap datepicker check here http://angular-ui.github.io/bootstrap/versioned-docs/1.3.3/#/datepickerPopup 

Just create Directive as follows

    app.directive('datePickerModelFormatter', function () {
        return {
            restrict: 'A',
            require: 'ngModel',
            link: function (scope, element, attr, ngModel) {
                function dateToString(dateValue) {
                    if (dateValue != null) {
                        var dateTimeToReturn = new Date(dateValue);
                        return dateTimeToReturn.toISOString();
                    }
                    return dateValue;
                }

                function stringToDate(stringValue) {
                    if (stringValue != null) {
                        var newOffsetDateTime = new Date(stringValue);
                        return new Date(newOffsetDateTime.setMinutes(newOffsetDateTime.getMinutes() + newOffsetDateTime.getTimezoneOffset()));
                    }
                    return stringValue;
                }

                ngModel.$parsers.push(dateToString);
                ngModel.$formatters.push(stringToDate);
            }
        };

    });



and on HTML just include this model

  <p class="input-group">
          <input type="text" class="form-control" uib-datepicker-popup="{{format}}" ng-model="dt" is-open="popup1.opened" datepicker-options="dateOptions" ng-required="true" close-text="Close" alt-input-formats="altInputFormats" date-picker-model-formatter />
          <span class="input-group-btn">
            <button type="button" class="btn btn-default" ng-click="open1()"><i class="glyphicon glyphicon-calendar"></i></button>
          </span>
        </p>


Thats it, it will convert to DateObject and Return back as StringObject (ISOString format)

Tuesday, June 28, 2016

AngularJS - BootStrap Popover Directive

In some cases we need to show some popover as tooltip or as dialog

Here am going to use BootStrap Popover, this plugin is part of BootStrap.js file or we can include spearately. For more information about that read here 

I am going to create simple popover

Step 1; Create your html pages, include BootStrap js files, AngularJS, JQuery basic setups

Step 2: Here is what I created directive to make PopOver work with AngularJS, add this directive to your application

var app = angular.module('appModuleName');

app.directive('popover', ['$compile',function ($compile) {
    return {
        restrict: 'A',
        link: function (scope, element, attrs) {
            $(element).popover({
                html: true,
                title:  attrs.popoverTitle || "Header",
                content: function () {
                    return $compile($("#" + attrs.popoverContent).html())(scope);
                },
                placement: attrs.popoverPlacement || "top"
            });
        }
    };

}]);


Step 3: In your HTML, just use this directive and pass attributes

<input type="button" popover popover-title="Header Text" popover-content="popover-content-id" popover-placement="top"/>

Step 4: Here you can pass your Title, ContentId, placement (Top, Bottom, Right, Left) etc.  This popover-content-id is div with contents

  <div id="popover-content-id" class="hide">
Some content here..
  </div>

Friday, May 6, 2016

AngularJS - Multiselect Drop down

In some cases, we need to create multi select dropdown. With AngularJS directive it is very easier to implement

Okay, let me first show basic multi select dropdown without any angularJS

<select data-ng-model="model" data-ng-options="value as name for item in itemlist" multiple>
    <option value="" style="color:gray;">-Select Item-</option>
</select>

Here we used simple Select element with multiple attribute. It allows you to select multiple items from dropdown. But drawback is, we should use Ctrl key to select multiple items and also style is not that much easier to customize.


To resolve these dependencies, we can choose AngularJS directive as solution.

app.directive('multiSelectDropDown', function () {
        return {
            restrict: 'AE',
            scope: {
                model: '=',
                options: '=',
                optionsName: '@',
                optionsValue: '@',

            },
            template: "<div class='btn-group dropdown' style='width:100%'>" +
             "<input type='text' value='{{model.toString()}}' data-toggle='dropdown' class='dropdown-toggle' placeholder='Click to select' disabled>" +
             "<button class='btn btn-small dropdown-toggle' data-toggle='dropdown'><span class='caret'></span></button>" +
                     "<ul class='dropdown-menu' style='width:100%'  aria-labelledby='dropdownMenu'>" +
                         "<li><a data-ng-click='selectAll()'><i class='glyphicon glyphicon-ok'></i>  Select All</a></li>" +
                         "<li><a data-ng-click='deselectAll();'><i class='glyphicon glyphicon-remove'></i>  Deselect All</a></li>" +
                         "<li class='divider'></li>" +
                         "<li data-ng-repeat='option in options'>" +
                         "<a data-ng-click='setSelectedItem()'><span class=\"{{isChecked(option) ? 'glyphicon glyphicon-ok' : ''}}\"></span>&nbsp;{{option[''+optionsName+'']}}&nbsp;</a>" +
                         "</li>" +
                     "</ul>" +
                 "</div>",
            controller: function ($scope) {

                $scope.selectAll = function () {
                    $scope.model = [];
                    $scope.options.forEach(function (option, index) {
                        $scope.model.push(option[$scope.optionsValue]);
                    });
                };

                $scope.deselectAll = function () {
                    $scope.model = [];
                };

                $scope.setSelectedItem = function () {
                    var selected = this.option;
                    if ($scope.model == undefined || $scope.model == null)
                        model = [];

                    if (_.contains($scope.model, selected[$scope.optionsValue])) {
                        $scope.model = _.without($scope.model, selected[$scope.optionsValue]);
                    } else {
                        $scope.model.push(selected[$scope.optionsValue]);
                    }

                    return $scope.model;
                };

                $scope.isChecked = function (selected) {
                    if ($scope.model == undefined || $scope.model == null)
                        $scope.model = [];

                    if (_.contains($scope.model, selected[$scope.optionsValue])) {
                        return true;
                    }
                    return false;
                };
            }
        }

    });



This directive you can include into your AngularJS application as directive

 var app = angular.module('yourAppName');


In HTML, we can call this directive simply like below

 <multi-select-drop-down model="model" options="itemlist" options-name="name" options-value="value "></multi-select-drop-down>



This requires BootStrap css file, Glyphicons to make work.


Thursday, March 31, 2016

MVC - Domain Route for Multi tenancy application to handle different URL

In some cases, we should handle Multi-tenant application with single code base and different domain URLs.

So how do we handle that in MVC Routing?

We have got "Constraints" concept in MVC routing, this is very helpful to filter URL based on domain also.

Okay, let us consider we have different URLs for same code base  for ex:  CompanyAName.com, CompanyBName.com. So here we have to handle two different domain URLs considering URLs already configured for same application.

routes.MapRoute(
    name: "CompanyARoute",
    url: "{controller}/{action}/{id}",
    defaults: new { controller = "Index", action = "Home", id = UrlParameter.Optional },
    constraints: new { host = "CompanyAName.com" });


routes.MapRoute(
    name: "CompanyBRoute",
    url: "{controller}/{action}/{id}",
    defaults: new { controller = "Index", action = "Home", id = UrlParameter.Optional },

    constraints: new { host = "CompanyBName.com" });



This code will handle two different domains, "host" in constraints is default syntax and will map to domain automatically. here we can change default Controller, Action to anything or even we can pass some parameters. 


Suppose, if we want to add some subdomain as companyname. For ex;   DefaultURL.com/CompanyName

We can use same "Constraints" to handle this

  routes.MapRoute(
    name: "SubRoute",
    url: "{companyName}/{controller}/{action}/{id}",
    defaults: new { controller = "Index", action = "Home", id = UrlParameter.Optional },
    constraints: new { companyName = "CompanyA" });


To handle multiple company names we can create more routing same like this or even in companyName we can add more like "(CompanyA|CompanyB)". "companyName" in constraints mapped to {companyName} in url.


We can utilize IRouteConstraint interface to extend each constraints attributes.

routes.MapRoute(
  name: "ConstraintRoute,
  url: "{controller}/{action}/{id}",
  defaults: new { controller = "Index", action = "Home", id = UrlParameter.Optional },
  constraints: new { host = new HostRouteConstraint("CompanyAName.com") });

"HostRouteConstraint" is a class extended from IRouteConstraint

using System.Web.Routing;
public class HostRouteConstraint : IRouteConstraint
    {
        private readonly string _host;

        public DomainConstraint(string host)
        {
            _host = host.ToLower();
        }

        public bool Match(HttpContextBase httpContext,
            System.Web.Routing.Route route,
            string parameterName,
            RouteValueDictionary values,
            RouteDirection routeDirection)
        {
//Here you can do your custom logic to match host
            return httpContext.Request.Url.AbsoluteUri.ToLower().Contains(_host);
        }
    }


Friday, January 8, 2016

AngularJS - Custom form validation

We can have some situation to use custom validations to our input fields, we can use following code to implement it.

Here my case is, I want to validate multiple emails field and have to show field error using AngularJS Form Validation.

For multiple email JavaScript validation check here http://rbalajiprasad.blogspot.in/2015/04/javascript-validate-multiple-email.html 

For AngularJS Form validation check here http://www.w3schools.com/angular/angular_validation.asp


HTML Page:

<p>Email:<br>
  <input type="email" name="email" ng-model="email" required>
  
<span style="color:red" ng-show="myForm.email.$dirty && myForm.email.$invalid">
  
<span ng-show="myForm.email.$error.required">Email is required.</span>
  
<span ng-show="myForm.email.$error.validEmail">Invalid email address.</span>
  
</span>
</p>
<p>
  
<input type="button" ng-click="submit()"
  ng-disabled=
"myForm.email.$dirty && myForm.email.$invalid">
</p>


AngularJS Controller

$scope.Submit = function () {
     //your validation
            var isValidEmail = isValidEmailAddress($scope.email.ToAddress);
            $scope.myForm.email.$setValidity("validEmail", isValidEmail);

            var isValid = $scope.myForm.$valid;
            if (!isValid) { return; }

//your logic goes here

        };