Wednesday, 25 May 2016

How to implement Cascading Dropdownlist with Angular JS in ASP.NET MVC 5

2 comments
In this post i would like to explain about How to implement Cascading Dropdown list using Angular JS in ASP.NET MVC 5 application.Thank you for comments and feedback for previous post How to create Registration page using Angular JS.your encouragement makes me feel proud to be blogger.Your feedback helps me to create more quality articles. If you are new to angular JS check the basics click here i have explained briefly about angular js here.

Description:

Sometimes we need to create a drop down lists where populated values depends on the previous drop down selected values these are called Cascading drop down lists.You can see these types of drop down lists in many of the web applications.For example States drop down populated based on the country we selected(In this article i am creating same Country-State cascading drop down).
Now lets see How we are going to implement Cascading Drop down list using Angular js in ASP.NET application.

The application UI is look like this....

cascading dropdown using angular js in mvc5

Steps:

Step 1: Creating Tables for Dropdown Data

1.Create Two tables in Database Country , States tables
2.I created two tables with below columns.


cascading dropdown list in angularjs states table

Step 2: Add ADO.NET Entity Data Model

1.Right click on Solution--> Add --> New Item -->Select ADO.NET Entity Data Model(Under Data) --> name it -->Add --> select Add from Database (In Entity Data Model wizard) --> Next
2.Select Database --> give name for web.config.
3.Choose your Database objects(tables) and click finish.

Step 3: Add Action Methods to Get Country,States data

1.Create Controller and name it as HomeController and add below action methods to get data from the database and to send data to angular controller ($http service get data from this action method).
2.GetCountries() : Fetch country values.
3.GetStates() : Fetch States values.
4.Replace below code in Home Controller.
// get country list from DB
        public ActionResult GetCountries()
        {
            List countrylist = new List();
            using (MyDatabaseEntities dc = new MyDatabaseEntities())
            {
                countrylist = dc.Countries.OrderBy(a => a.CountryName).ToList();
            }
            return new JsonResult { Data = countrylist, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
        }
        // Get States based on Country selected in dropdown

        public ActionResult GetStates(int countryID)
        {
            List statelist = new List();
            using (MyDatabaseEntities dc = new MyDatabaseEntities())
            {
                statelist = dc.States.Where(a => a.CountryID.Equals(countryID)).OrderBy(a => a.StateName).ToList();
            }
            return new JsonResult { Data = statelist, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
        }

Step 4: Add new script files for Angular Module & Controller

1.Right click on Scripts folder and add new java script file for angular module creation.
(function () {
    //Create a Angular Module 
    var app = angular.module('MyApp', []);  
    //name of angular application is 'MyApp'
})();

2.Now attach or extend this angular module by creating angular controller.
3.Here i named it as "DropdownController".
4.Add below code in DropdownController,js files.
angular.module('MyApp').controller('DropdownController', function ($scope,StateService) {
    //create a angular controller  
    // expained about controller in Part2 // Here LocationService (Service) Injected

    $scope.CountryID = null;
    $scope.StateID = null;
    $scope.CountryList = null;
    $scope.StateList = null;

    $scope.StateTextToShow = "Select State";
    $scope.Result = "";

    // Populate Country list using GetCountry()
    StateService.GetCountry().then(function (d) {
        //assign countries to $scope.CountryList
        $scope.CountryList = d.data;    //success
    },
    function (error) {
        alert('Error!');    //throws error for failure
    });
    // This function to Populate State 
    // it is called after selecting country from dropdownlist
    $scope.GetState = function () {
        $scope.StateID = null; // Clear Selected State if any
        $scope.StateList = null; // Clear previously loaded state list
        $scope.StateTextToShow = "Please Wait..."; // this will show until load states from database

        //Load State 
        StateService.GetState($scope.CountryID).then(function (d) {
            $scope.StateList = d.data;
            $scope.StateTextToShow = "Select State";
        }, function (error) {
            alert('Error!');
        });

    }
    // Function for show result
    //it will be displayed after clicking on button
    $scope.ShowResult = function () {
        $scope.Result = "Selected Country ID : " + $scope.CountryID + " State ID : " + $scope.StateID;
    }

})
.factory('StateService', function ($http) { //factory methos to get data from server.
    var fac = {};
    fac.GetCountry = function () {
        return $http.get('/Home/GetCountries')
    }
    fac.GetState = function (countryID) {
        return $http.get('/Home/GetStates?countryID='+countryID)
    }

    return fac;
});

5.Here in above code i created a angular service StateService to get data from remote server through ajax calls.
6.ShowResult function returns the selected values in two drop down lists and displays in a modal popup created by using Bootstrap responsive framework.

Note : Here i explained  How to integrate and use Bootstrap framework in ASP.NET MVC5 application.

Step 5: Add Index View to display Dropdown lists

1.Create Index Actin Method in HomeController.
// GET: /Home/        
        public ActionResult Index()
        {
            return View();
        }

2.Add View to Index action method and replace code with following code.
@{
    ViewBag.Title = "Cascading Dropdown using AngularJS and MVC5";
}
<style>
    body{
        margin-top:50px;
        margin-left:30px;
        margin-right:400px;
    }
</style>
<div class="panel panel-info">
    <div class="panel-heading">
        Cascading Dropdown using AngularJS and MVC5
    </div>
    <div class="panel-body">
        <div ng-controller="DropdownController">
            <div class="dropdown">
                Country :
                <select class="btn btn-primary dropdown-toggle" ng-model="CountryID" ng-options="I.CountryID as I.CountryName for I in CountryList" ng-change="GetState()">
                    <option value="">Select Country</option>
                </select>

                State :
                <select class="btn btn-primary dropdown-toggle" ng-model="StateID" ng-options="I.StateID as I.StateName for I in StateList">
                    <option value="">{{StateTextToShow}}</option>
                </select>

                <input class="btn btn-success" type="button" value="Get Selected Values" ng-click="ShowResult()" data-toggle="modal" data-target="#myModal" />

                <div class="modal fade" id="myModal" role="dialog">
                    <div class="modal-dialog">

                        <div class="modal-content">
                            <div class="modal-header">
                                <button type="button" class="close" data-dismiss="modal">&times;</button>
                                <h4 class="modal-title">Modal Header</h4>
                            </div>
                            <div class="modal-body" id="myModal">
                                {{Result}}
                            </div>
                            <div class="modal-footer">
                                <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
                            </div>
                        </div>
                    </div>
                </div>
            </div>

         </div>
     </div>
    <div class="panel-footer">
        Microsoft tech Developments 2016
    </div>
</div>
@section scripts{ 
<script src="~/Scripts/DropdownController.js"></script>
}
ng-options: Here ,i used ng-options directive to repeat the elements in CountyList . We can do this using ng-repeat directive and in any cases it is easy to implement also. but, using ngOptions is more flexible campared to ngRepeat.

ng-change: ngChange directive triggers an event time Element is changed.

3.Add Scripts references in Index.cshtml page like below(I added Myapp.js file reference in Layout page for angular module)
@section scripts{  
<script src="~/Scripts/DropdownController.js"></script>
}
Modify _Layout page with below modifications.
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width" />
    <title>@ViewBag.Title</title>
    @Styles.Render("~/Content/css")
    @Scripts.Render("~/bundles/modernizr")
    <link href="~/Content/bootstrap.min.css" rel="stylesheet" />
</head>
    @* Here  ng-app="MyApp" is used for auto-bootstrap an AngularJS application(it create angular application). here ng-app="MyApp" means <body> element is the owner 
    of AngularJS application*@
<body ng-app="MyApp">      
    @RenderBody()

    @Scripts.Render("~/bundles/jquery")
    <script src="~/Scripts/bootstrap.js"></script>
    @* Add Angular Library Here *@
    @Scripts.Render("~/bundles/angular")
    <script src="~/Scripts/MyApp.js"></script>
    @RenderSection("scripts", required: false)
</body>
</html>
Now run the application Press F5
we will get the selected values in modal popup like below screen shot.

cascading dropdown list in angularjs

You may also like below

Download source code this application Here.

Conclusion:
I hope this article is understandable for every reader.Please recommend if you want to improve the readability of this article through comments.If you are not subscribed to this site please subscribe...


2 comments:

  1. i think that there is a mistake in the HomeController

    ReplyDelete
  2. IN THE BUNDELCONFIG YOU SHOULD ADD
    bundles.Add(new ScriptBundle("~/bundles/angular").Include(
    "~/Scripts/angular.js",
    "~/Scripts/angular-route.js"));

    ReplyDelete