Creating dynamic menu from database data using AngularJS



Introduction

Generating dynamic menus is a common task if we have big web application and user will have role-based features.
If our application is simple and not any role based website then, in that case, we can create a static menu and use it in our website.
Let's now consider our application is a role-based application with the different type of user, who can get different features based on their role then it will be hard to maintain with a static menu.
Today I will show you how to build multi-level navigation menu with AngularJS where menu data comes from the database.
This type of menu creation is very useful when admin user wants to set the access permissions or restricting users from accessing some pages at runtime.

Just follow the following steps in order implement multi-level navigation menu with AngularJS

Here In this article, I have used Visual Studio 2013

Step-1: Create New Project.

Go to File > New > Project > ASP.NET  Web Application (under web) > Entry Application Name > Click OK > Select Empty template > Checked MVC (under "Add folders and core references for" option) > OK

Step-2: Add a Database.

Go to Solution Explorer > Right Click on App_Data folder > Add > New item > Select SQL Server Database Under Data > Enter Database name > Add.

Step-3: Create a table for store menu data.

In this example, I have used 1 table as below, where I have added ParentID column in our table to hold Parent and child relationships between the menus.

Step-4: Add Entity Data Model.

Go to Solution Explorer > Right Click on Project name form Solution Explorer > Add > New item > Select ADO.net Entity Data Model under data > Enter model name > Add.
A popup window will come (Entity Data Model Wizard) > Select Generate from database > Next >
Chose your data connection > select your database > next > Select tables > enter Model Namespace > Finish.

Step-5: Create a javascript file for angular components.

Here I have created a folder named "Scripts" first, and then I have added a javascript file for add angular components (module, controller etc). Here we will fetch menu data from the database.
Right Click on your solution file (from solution explorer) > Add > New Folder > Renamed your folder. and then
Right click on your folder (just created) > Add > New Item > select "javascript" file > Enter name (here "MyApp.js")> Ok.
Write following code
var app = angular.module('MyApp', []);
app.controller('menuController', ['$scope', '$http', function ($scope, $http) {
    $scope.SiteMenu = [];
    $http.get('/home/GetSiteMenu').then(function (data) {
        $scope.SiteMenu = data.data;
    }, function (error) {
        alert('Error');
    })
}])

Step-6: Create a CSS file for styling navigation menu.

Now we will create a CSS file for styling the navigation menu. Here in this example, our menu will be a multi-level menu.
In the same way, first I have added a folder named "css" and then added a CSS file.
Right Click on your solution file (from solution explorer) > Add > New Folder > Renamed your folder. and then
Right click on your folder (just created) > Add > New Item > select "style sheet" file > Enter name (here "navMenu.css") > Ok.
Write following code
/*Here I will write css for show horizantal nav menu*/
ul {
  list-style: none;
  padding: 0;
  margin: 0;
  background: #1bc2a2;
}

ul li {
  display: block;
  position: relative;
  float: left;
  background: #1bc2a2;
}
li ul { display: none; }

ul li a {
  display: block;
  padding: 1em;
  text-decoration: none;
  white-space: nowrap;
  color: #fff;
}

ul li a:hover { background: #2c3e50; }
li:hover > ul {
  display: block;
  position: absolute;
}

li:hover li { float: none; }

li:hover a { background: #1bc2a2; }

li:hover li a:hover { background: #2c3e50; }

.main-navigation li ul li { border-top: 0; }
ul ul ul {
  left: 100%;
  top: 0;
}
ul:before,
ul:after {
  content: " "; /* 1 */
  display: table; /* 2 */
}
ul:after { clear: both; }

Step-7: Create a Controller.

Go to Solution Explorer > Right Click on Controllers folder form Solution Explorer > Add > Controller > Enter Controller name > Select Templete "empty MVC Controller"> Add.

Here I have created a controller named "HomeController"

Step-8: Add new action into your controller for getting the view, where we will show navigation menu

It should be in the Layout page, but I have shown here in the Index page for making the post simple to understand.
Here I have added "Index" Action into "Home" Controller. Please write this following code
public ActionResult Index()
{
    return View();
}

Step-9: Add view for your Action & design for show multi-level navigation menu.

Right Click on Action Method (here right click on Index action) > Add View... > Enter View Name > Select View Engine (Razor) > Add.
HTML Code
@{
    ViewBag.Title = "Index";
}
<h2>Dynamic menu from database in AngularJS</h2>
@* Html code for show nav menu here, for mak the application simple 
    I will add ngapp and ngcontroller here *@
<div ng-app="MyApp">
    <div ng-controller="menuController">
        @* Here first of all we will create a ng-template *@
        <script type="text/ng-template" id="treeMenu">
            <a href="{{menu.Url}}">{{menu.Name}}</a>
            @* We will create submenu only when available *@
            <ul ng-if="(SiteMenu | filter:{ParentID : menu.ID}).length > 0">
                @*<li ng-repeat="menu in SiteMenu | filter:{ParentID : menu.ID}" ng-include="'treeMenu'"></li>*@
                <li ng-repeat="menu in SiteMenu | filter:{ParentID : menu.ID} : true" ng-include="'treeMenu'"></li>
            </ul>
        </script>
        <ul class="main-navigation">
            @* Here we will load only top level menu *@
            @*<li ng-repeat="menu in SiteMenu | filter:{ParentID : 0}" ng-include="'treeMenu'"></li>*@
            <li ng-repeat="menu in SiteMenu | filter:{ParentID : 0} : true" ng-include="'treeMenu'"></li>
        </ul>
    </div>
</div>
@* Add css here for nav menu *@
<link href="~/css/navMenu.css" rel="stylesheet" />

@* add js here for angular app *@
@section Scripts{
    <script src="~/Scripts/MyApp.js"></script>
}
Here you can see, I have used ng-include directive for including templates/HTML fragments.

Step-10: Add an another action into your controller for getting menu data from database

public JsonResult GetSiteMenu()
{
    using (MyDatabaseEntities dc = new MyDatabaseEntities())
    {
        var menu = dc.SiteMenus.ToList();
        return new JsonResult { Data = menu, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
    }
}

Step-11: Modify _Layout.cshtml page for load AngularJS library

_Layout.cshtml HTML Code
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>@ViewBag.Title - My ASP.NET Application</title>
    <link href="~/Content/Site.css" rel="stylesheet" type="text/css" />
    <link href="~/Content/bootstrap.min.css" rel="stylesheet" type="text/css" />
    <script src="~/Scripts/modernizr-2.6.2.js"></script>
</head>
<body>
    <div class="container body-content">
        @RenderBody()
        <hr />
        <footer>
            <p>&copy; @DateTime.Now.Year - My ASP.NET Application</p>
        </footer>
    </div>

    <script src="~/Scripts/jquery-1.10.2.min.js"></script>
    <script src="~/Scripts/bootstrap.min.js"></script>
    <!--HERE we will add angular.js library-->
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular.min.js"></script>
    @RenderSection("Scripts", false)
</body>
</html>

Creating dynamic menu from database data using AngularJS

Hello ! My name is Sourav Mondal. I am a software developer working in Microsoft .NET technologies since 2010.

I like to share my working experience, research and knowledge through my site.

I love developing applications in Microsoft Technologies including Asp.Net webforms, mvc, winforms, c#.net, sql server, entity framework, Ajax, Jquery, web api, web service and more.