使用MVC和WCF REST+Angular实现动态菜单

来源链接

http://www.codeproject.com/Articles/996614/Angular-JS-Dynamic-Menu-Creation-using-MVC-and-WCF

新手翻译,看到一些好文,将其转过来,希望能对大家起到一点点的帮助.

1,为什么我们需要动态创建菜单:


如果我们只是需要创建一个只有几个页面的网站,那么用静态菜单就可以。

但是如果要开发一个大型Web应用的话,例如ERP Web应用.

在这种情况下,会有2个以上的开发者一起工作,而且页面可能会超过50-100,这种情况下,用静态菜单将会是一个很大的挑战.

而且在开发中或之后,我们的客户可能会要求我们增加5个新的菜单,或移除掉一个菜单元素.

在使用静态菜单的情形下,这将会是一个很耗时的操作.

而且在开发大型Web项目时,比如ERP,我们需要基于用于角色来显示菜单,如果我们使用静态菜单的话,这将会一

件很难成.

为了解决这些情况,我们应该基于用于角色配置来创建菜单

谁应该管理这些菜单?

这是非常重要的部分,例如管理或超级用户可以 添加/编辑/删除 这些菜单或用户.

当管理员登录后,他能添加新菜单,编辑现有菜单和删除菜单元素。

这篇文章的关注点并不在于菜单管理而在于如何创建一个主菜单和菜单详情表,Insert一些示例菜单进我们的数据表,然后在我们的MVC Web页上使用AngularJS WCF Rest服务来动态的显示它.

这篇文章将会说明:

1,如何创建一个WCF Rest服务和从数据库中查询数据 

2,如何安装Angular JS PackageMVC 应用.

3,如何使用Angular JS建立一个动态菜单应用.

4,如何在Angular JS里使用WCS 服务显示动态菜单

注意:你首先必须安装Visual Studio 2013



面向服务的应用使用这个协议,我们能在网络上分享我们的服务

举个例子,让我们设想一个场景,我们正在完成一个项目,需要创建一些公用数据库方法,并且需要被另外多个在不同地点的项目通过Internet连结调用.

在这种情况下,我们可以创建一个WCF 服务并且将我们的公用数据库方法放到这个WCF 服务类中,然后将这个WCF 服务布署在IIS,通过URL将其开放出去.

在这段代码中,让我们看看如何创建一个WCF Rest服务,并且将它用在我们的AngularJS 应用中.

如果你想了解更多的关于WCF的资料,请点击这里link.

AngularJS 

我们可能会对Model,ViewView Model(MVVM)Model,ViewController(MVC)比较熟悉.AngularJS 也是一个纯粹的用于Html,CSSJS的类似框架
MVCMVVM模式相似,AngularJS使用Model,ViewWhatever(MVW)模式
在例子中,我使用了Model,View和服务,在下面这段代码中,让我们看看如何将AngularJS引和我们的MVC应用中.

使用这段代码

我们将基于MenuDB数据库,创建一个主菜单和详情菜单表

注意:主菜单和菜单详情表用于动态加载我们的菜单,我们需要知道如何插入详情菜单到表中,以用于显示正常显示菜单.

在这篇文章中,我们将示例三级水平分级菜单,如图:

 

第一级-> Inventory;

第二级-> inventory Details

 第三级> Finished Goods Receipt and Finished Goods Issue.

现在让我们看看如何创建表用于关联主菜单和详情菜单

 

主菜单表

1级菜单Insert

Insert into MenuMaster(Menu_RootID,Menu_ChildID,UserID,CreatedDate) values('Root','Inventory','Shanu',getdate()-23)

2 级菜单Insert

Insert into MenuMaster(Menu_RootID,Menu_ChildID,UserID,CreatedDate) values('Inventory','INV001','Shanu',getdate()-23)

3 级菜单Insert

Insert into MenuMaster(Menu_RootID,Menu_ChildID,UserID,CreatedDate) values('INV001','FG001','Shanu',getdate()-23)Insert into MenuMaster(Menu_RootID,Menu_ChildID,UserID,CreatedDate) values('INV001','FG002','Shanu',getdate()-23)

 

详情菜单表

1 级菜单Insert

Insert into MenuDetails(Menu_ChildID,MenuName,MenuDisplayTxt,MenuFileName,MenuURL,UserID,CreatedDate)values('Inventory','Inventory','Inventory','Index','Inventory','Shanu',getdate()-23)

2 级菜单Insert

Insert into MenuDetails(Menu_ChildID,MenuName,MenuDisplayTxt,MenuFileName, MenuURL,UserID,CreatedDate)values('INV001','Inventory','Inventory Details','Index','Inventory','Shanu',getdate()-23)

3 Level hierarchies Insert

Insert into MenuDetails(Menu_ChildID,MenuName,MenuDisplayTxt,MenuFileName, MenuURL,UserID,CreatedDate)values('FG001','FGIN','FG Receipt','FGIN','Inventory','Shanu',getdate()-43) Insert into MenuDetails(Menu_ChildID,MenuName,MenuDisplayTxt,MenuFileName, MenuURL,UserID,CreatedDate)values('FG002','FGOUT','FG Issue','FGOUT','Inventory','Shanu',getdate()-13)

字段与详情菜单的关系

 

我们已使用的字段与主菜单的关系

下面的脚本用于创建数据库,表和示例中用到的InsertQuery.

在你的SQL中运行这个脚本,我使用的是SQL2012

-- =============================================                             
-- Author      : Shanu                               
-- Create date : 2015-03-20                               
-- Description : To Create Database,Table and Sample Insert Query                            
-- Latest                               
-- Modifier    : Shanu                               
-- Modify date : 2015-03-20                           
-- =============================================
--Script to create DB,Table and sample Insert data
USE MASTER
GO
-- 1) Check for the Database Exists .If the database is exist then drop and create new DB
IF EXISTS (SELECT [name] FROM sys.databases WHERE [name] = 'MenuDB' )
DROP DATABASE MenuDB
GO

CREATE DATABASE MenuDB
GO
USE MenuDB
GO

-- 1) //////////// ToysDetails table
-- Create Table  ToysDetails ,This table will be used to store the details like Toys Information

IF EXISTS ( SELECT [name] FROM sys.tables WHERE [name] = 'MenuMaster' )
DROP TABLE MenuMaster
GO
CREATE TABLE MenuMaster
(
   Menu_ID int identity(1,1),
   Menu_RootID VARCHAR(30)  NOT NULL,
   Menu_ChildID VARCHAR(30)  NOT NULL,
   UserID varchar(50),
   CreatedDate datetime
CONSTRAINT [PK_MenuMaster] PRIMARY KEY CLUSTERED      
(    
  [Menu_ID] ASC   ,
  [Menu_RootID] ASC,
  [Menu_ChildID] ASC 
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]    
) ON [PRIMARY]  
GO
--delete from MenuMaster
-- Insert the sample records to the ToysDetails Table
Insert into MenuMaster(Menu_RootID,Menu_ChildID,UserID,CreatedDate) values('Root','Home','Shanu',getdate()-23)
--Insert into MenuMaster(Menu_RootID,Menu_ChildID,UserID,CreatedDate) values('Home','Home','Shanu',getdate()-23)
Insert into MenuMaster(Menu_RootID,Menu_ChildID,UserID,CreatedDate) values('Home','About','Shanu',getdate()-23)
Insert into MenuMaster(Menu_RootID,Menu_ChildID,UserID,CreatedDate) values('Home','Contact','Shanu',getdate()-23)
Insert into MenuMaster(Menu_RootID,Menu_ChildID,UserID,CreatedDate) values('Root','Masters','Shanu',getdate()-23)
Insert into MenuMaster(Menu_RootID,Menu_ChildID,UserID,CreatedDate) values('Masters','ITM001','Shanu',getdate()-23)
--Insert into MenuMaster(Menu_RootID,Menu_ChildID,UserID,CreatedDate) values('ITM001','ITM001','Shanu',getdate()-23)
Insert into MenuMaster(Menu_RootID,Menu_ChildID,UserID,CreatedDate) values('ITM001','ITM002','Shanu',getdate()-23)
Insert into MenuMaster(Menu_RootID,Menu_ChildID,UserID,CreatedDate) values('ITM001','ITM003','Shanu',getdate()-23)
Insert into MenuMaster(Menu_RootID,Menu_ChildID,UserID,CreatedDate) values('Masters','CAT001','Shanu',getdate()-23)
Insert into MenuMaster(Menu_RootID,Menu_ChildID,UserID,CreatedDate) values('CAT001','CAT001','Shanu',getdate()-23)
Insert into MenuMaster(Menu_RootID,Menu_ChildID,UserID,CreatedDate) values('CAT001','CAT002','Shanu',getdate()-23)
Insert into MenuMaster(Menu_RootID,Menu_ChildID,UserID,CreatedDate) values('CAT001','CAT003','Shanu',getdate()-23)
Insert into MenuMaster(Menu_RootID,Menu_ChildID,UserID,CreatedDate) values('Root','Inventory','Shanu',getdate()-23)
Insert into MenuMaster(Menu_RootID,Menu_ChildID,UserID,CreatedDate) values('Inventory','INV001','Shanu',getdate()-23)
Insert into MenuMaster(Menu_RootID,Menu_ChildID,UserID,CreatedDate) values('INV001','FG001','Shanu',getdate()-23)
Insert into MenuMaster(Menu_RootID,Menu_ChildID,UserID,CreatedDate) values('INV001','FG002','Shanu',getdate()-23)


select * from MenuMaster
-- 1) END //

-- 2) Cart Details Table
IF EXISTS ( SELECT [name] FROM sys.tables WHERE [name] = 'MenuDetails' )
DROP TABLE MenuDetails
GO

CREATE TABLE MenuDetails
(
   MDetail_ID int identity(1,1),
   Menu_ChildID VARCHAR(20) NOT NULL,
   MenuName VARCHAR(100) NOT NULL,
   MenuDisplayTxt VARCHAR(200) NOT NULL,
   MenuFileName VARCHAR(100) NOT NULL,
   MenuURL VARCHAR(500) NOT NULL,
   USE_YN Char(1) DEFAULT 'Y',
   UserID varchar(50),
   CreatedDate datetime
CONSTRAINT [PK_MenuDetails] PRIMARY KEY CLUSTERED     
(    
  [MDetail_ID] ASC,
  [Menu_ChildID] ASC      
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]    
) ON [PRIMARY]  
GO

----delete from MenuDetails

Insert into MenuDetails(Menu_ChildID,MenuName,MenuDisplayTxt,MenuFileName,MenuURL,UserID,CreatedDate)
values('Root','Home','Shanu Home','Index','Home','Shanu',getdate()-23)

Insert into MenuDetails(Menu_ChildID,MenuName,MenuDisplayTxt,MenuFileName,MenuURL,UserID,CreatedDate)
values('Home','Home','Shanu Home','Index','Home','Shanu',getdate()-23)

Insert into MenuDetails(Menu_ChildID,MenuName,MenuDisplayTxt,MenuFileName,MenuURL,UserID,CreatedDate)
values('About','About','About Shanu','About','Home','Shanu',getdate()-43)

Insert into MenuDetails(Menu_ChildID,MenuName,MenuDisplayTxt,MenuFileName,MenuURL,UserID,CreatedDate)
values('Contact','Contact','Contact Shanu','Contact','Home','Shanu',getdate()-13)

Insert into MenuDetails(Menu_ChildID,MenuName,MenuDisplayTxt,MenuFileName,MenuURL,UserID,CreatedDate)
values('Masters','Masters','Masters','ItemDetails','Masters','Shanu',getdate()-13)

Insert into MenuDetails(Menu_ChildID,MenuName,MenuDisplayTxt,MenuFileName,MenuURL,UserID,CreatedDate)
values('ITM001','ItemMaster','Item Master','ItemDetails','Masters','Shanu',getdate()-13)

Insert into MenuDetails(Menu_ChildID,MenuName,MenuDisplayTxt,MenuFileName,MenuURL,UserID,CreatedDate)
values('ITM002','ItemDetail','Item Details','ItemDetails','Masters','Shanu',getdate()-13)

Insert into MenuDetails(Menu_ChildID,MenuName,MenuDisplayTxt,MenuFileName,MenuURL,UserID,CreatedDate)
values('ITM003','ItemManage','Item Manage','ItemManage','Masters','Shanu',getdate()-13)

Insert into MenuDetails(Menu_ChildID,MenuName,MenuDisplayTxt,MenuFileName,MenuURL,UserID,CreatedDate)
values('CAT001','CatMaster','Category Masters','CATDetails','Masters','Shanu',getdate()-13)

Insert into MenuDetails(Menu_ChildID,MenuName,MenuDisplayTxt,MenuFileName,MenuURL,UserID,CreatedDate)
values('CAT002','CATDetail','Category Details','CATDetails','Masters','Shanu',getdate()-13)

Insert into MenuDetails(Menu_ChildID,MenuName,MenuDisplayTxt,MenuFileName,MenuURL,UserID,CreatedDate)
values('CAT003','CATManage','Category Manage','CATManage','Masters','Shanu',getdate()-13)


Insert into MenuDetails(Menu_ChildID,MenuName,MenuDisplayTxt,MenuFileName,MenuURL,UserID,CreatedDate)
values('Inventory','Inventory','Inventory','Index','Inventory','Shanu',getdate()-23)

Insert into MenuDetails(Menu_ChildID,MenuName,MenuDisplayTxt,MenuFileName,MenuURL,UserID,CreatedDate)
values('INV001','Inventory','Inventory Details','Index','Inventory','Shanu',getdate()-23)

Insert into MenuDetails(Menu_ChildID,MenuName,MenuDisplayTxt,MenuFileName,MenuURL,UserID,CreatedDate)
values('FG001','FGIN','FG Receipt','FGIN','Inventory','Shanu',getdate()-43)

Insert into MenuDetails(Menu_ChildID,MenuName,MenuDisplayTxt,MenuFileName,MenuURL,UserID,CreatedDate)
values('FG002','FGOUT','FG Issue','FGOUT','Inventory','Shanu',getdate()-13)

select * from MenuMaster

select * from MenuDetails

             select   A.Menu_RootID,
                 B.MDetail_ID,
                 B.Menu_ChildID,
                 B.MenuName,
                 B.MenuDisplayTxt,
                 B.MenuFileName,        
                 B.MenuURL ,          
                 B.UserID                                                     
                 FROM
                 MenuMaster A
                 INNER JOIN MenuDetails B
                 ON A.Menu_ChildID=B.Menu_ChildID

2) 创建WCF Rest服务:

打开Visual Studio 2013 然后选择 文件--新建--项目,然后选择WCF 服务,设定好你的应用名和存储路径后单击OK.

 

创建好后,我们可以看到IService.csService1.svc在解决方案浏览器中.

 

  • IService.CS:在 “IService.CS” 中,我们可以看到3默认成员方法.
  • [ServiceContract]: 
  • 描述这个服务的方法和可用的操作,Service Contract可以使用      [OperationContract]属性声明.
  • [OperationContract]: 类似于 web service [WEBMETHOD].
  • [DataContract]: 
  • 描述客户端与服务的数据交互格式
  • [ServiceContract]
  • 下列代码在Iservice.cs文件中会自带创建我们可以在其中写入我们自己的代码.

 

 public interface IService1
    {
        [OperationContract]
        string GetData(int value);

        [OperationContract]
        CompositeType GetDataUsingDataContract(CompositeType composite);

        // TODO: Add your service operations here
    }
 // Use a data contract as illustrated in the sample below to add composite types to service operations.

    [DataContract]
    public class CompositeType
    {
        bool boolValue = true;
        string stringValue = "Hello ";

        [DataMember]
        public bool BoolValue
        {
            get { return boolValue; }
            set { boolValue = value; }
        }

        [DataMember]
        public string StringValue
        {
            get { return stringValue; }
            set { stringValue = value; }
        }
    }

Data Contract

在我们的例子中,我们需要从数据库中获取全部详情菜单,所以我创建了一个Data Contracts,“MenuDataContract”,可以看到,我已经创建了一些成员变量名字同于表的列名.

public class MenuDataContract    {
        [DataContract]
        public class MenuMasterDataContract
        {
            [DataMember]
            public string Menu_ID { get; set; }

            [DataMember]
            public string Menu_RootID { get; set; }

            [DataMember]
            public string Menu_ChildID { get; set; }

            [DataMember]
            public string UserID { get; set; }
        }


        [DataContract]
        public class MenuDetailDataContract
        {
            [DataMember]
            public string MDetail_ID { get; set; }

            [DataMember]
            public string Menu_RootID { get; set; }

            [DataMember]
            public string Menu_ChildID { get; set; }

            [DataMember]
            public string MenuName { get; set; }

            [DataMember]
            public string MenuDisplayTxt { get; set; }


            [DataMember]
            public string MenuFileName { get; set; }


            [DataMember]
            public string MenuURL { get; set; }

            [DataMember]
            public string UserID { get; set; }
        }
    }

Service Contract

在 Operation Contrac中我们可以看到 “WebInvoke” 和 “WebGet”使用WCF Rest服务从数据库中查询数据

     RequestFormat = WebMessageFormat.Json,

     ResponseFormat = WebMessageFormat.Json,

我们可以看到requestresponse格式,这里我们使用Json格式.

  • JSON是一种轻量级的数据交互格式
  • UriTemplate: 填入我们的方法名称

我们声明了三个方法 “GetMenuDetails” . The “GetMenuDetails” 用于获取主菜单和详情菜单,AngularJS可以调用其过滤显示指定的菜单项.

 [ServiceContract]     public interface IService1     { [OperationContract]         [WebInvoke(Method = "GET",            RequestFormat = WebMessageFormat.Json,            ResponseFormat = WebMessageFormat.Json,            UriTemplate = "/GetMenuDetails/")]         List<MenuDataContract.MenuDetailDataContract> GetMenuDetails();  }

Iservice.Cs -> 全部源码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;

namespace ShanuMenuCreation_WCF
{
    // NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IService1" in both code and config file together.
    [ServiceContract]
    public interface IService1
    {
        [OperationContract]
        [WebInvoke(Method = "GET",
           RequestFormat = WebMessageFormat.Json,
           ResponseFormat = WebMessageFormat.Json,
           UriTemplate = "/GetMenuDetails/")]
        List<MenuDataContract.MenuDetailDataContract> GetMenuDetails();
        // TODO: Add your service operations here
    }

 // Use a data contract as illustrated in the sample below to add composite types to service operations.
    public class MenuDataContract
    {
        [DataContract]
        public class MenuMasterDataContract
        {
            [DataMember]
            public string Menu_ID { get; set; }

            [DataMember]
            public string Menu_RootID { get; set; }

            [DataMember]
            public string Menu_ChildID { get; set; }

            [DataMember]
            public string UserID { get; set; }
        }

        [DataContract]
        public class MenuDetailDataContract
        {
            [DataMember]
            public string MDetail_ID { get; set; }

            [DataMember]
            public string Menu_RootID { get; set; }

            [DataMember]
            public string Menu_ChildID { get; set; }

            [DataMember]
            public string MenuName { get; set; }

            [DataMember]
            public string MenuDisplayTxt { get; set; }

            [DataMember]
            public string MenuFileName { get; set; }

            [DataMember]
            public string MenuURL { get; set; }

            [DataMember]
            public string UserID { get; set; }
        }
    }
}

使用ADO.Net Entity添加数据库

右键单击你的WCF项目然后选择新建ADO.NET Entity Data Model.

选择 EF Designer From DataBase 然后单击下一步

 

单击新建连接

 

选择数据库服务器名然后输入你的数据库UserID和密码.我们已经建立了一个MenuDB,所以我们选择这个数据库并单击OK.

 

单击下一步然后选择我们需要使用的数据表,单击完成.

我们已经创建了ShanuMenuModel

 

Service1.SVC

“Service.SVC.CS” 继承了IService接口并且重写了默认的Operation Contract方法.

示例:可以看到我已经实现了IService1在Service1 类中,创建一个EntityModel的对象,并且使用GetMenuDetails 方法和Linq Join Query我们可以获取到主菜单和详情菜单数据.

public class Service1 : IService1
    {
        ShanuMenuCreation_WCF.MenuDBEntities OME;

        public Service1()
        {
            OME = new ShanuMenuCreation_WCF.MenuDBEntities();
        }

        public List<MenuDataContract.MenuDetailDataContract> GetMenuDetails()
        {
            ////var query = (from a in OME.MenuDetails
            ////             select a).Distinct();
             var query = (from A in OME.MenuMaster  
                         join B in OME.MenuDetails on A.Menu_ChildID equals B.Menu_ChildID
                         select new  
                         {  
                            A.Menu_RootID,
                            B.MDetail_ID,
                            B.Menu_ChildID,
                            B.MenuName,
                            B.MenuDisplayTxt,
                            B.MenuFileName,
                            B.MenuURL ,
                            B.UserID
                         }).ToList().OrderBy(q => q.MDetail_ID); 

            List<MenuDataContract.MenuDetailDataContract> MenuList = new List<MenuDataContract.MenuDetailDataContract>();

            query.ToList().ForEach(rec =>
            {
                MenuList.Add(new MenuDataContract.MenuDetailDataContract
                {
                    MDetail_ID = Convert.ToString(rec.MDetail_ID),
                    Menu_RootID = rec.Menu_RootID,
                    Menu_ChildID = rec.Menu_ChildID,
                    MenuName = rec.MenuName,
                    MenuDisplayTxt = rec.MenuDisplayTxt,
                    MenuFileName = rec.MenuFileName,
                    MenuURL = rec.MenuURL,
                    UserID = rec.UserID,
                });
            });
            return MenuList;
       }    
    }

Web.Config:

对WCF项目的web.config进行下列修改

1) 修改 <add binding="basicHttpsBinding" scheme="https" /> 为 <add binding="webHttpBinding" scheme="http" />

2) 替换 </behaviors> 为

<endpointBehaviors><behavior> <webHttp helpEnabled="True"/></behavior> </endpointBehaviors>   

运行WCF服务: -> 现在我们已经创建了WCF Rest服务,让我们运行测试一下,使用我们的服务URL,我们可以看到返回的Json结果.

 

创建MVC Web应用

现在我们已经完成了WCF,是时候开始创建MVC AngularJS应用了.

我们可以按下列操作添加一个MVC Web应用项目进去.

右键单击解决方案中的项目,然后选择添加一个新的项目,输入项目名后确定.

 

选择MVC 单击OK

好的,我们已经建好了MVC 应用,该添加WCF 服务和安装AngularJS包进我们的解决方案了.
添加WCF 服务: 右键单击MVC解决方案然后选择添加服务引用

 

输入我们的WCF URL地址

http://localhost:3514/Service1.svc/     

输入名称然后单击OK

现在我们已建成功引用了刚写好的WCF进我们的MVC应用.

 

下一步开始安装AngularJS 

右键单击你的MVC项目标然后选择管理NuGet Packages

在线搜索Angular JS.然后单击安装.Angular JS引入我们的MVC项目中。

  • Modules.js
  • Controllers.js
  • Services.js

按步骤创建 AngularJS脚本文件:

右键单击脚本文件夹,然后创建我们的AngularJS Model/Controller Services Js脚本.创建三个JS文件 Module.js,Controller.jsServices.js如下图

 

Modules.js: 这里我们可以引用Angular.js 脚本,并给模块命名为“RESTClientModule” .

/// <reference path="../angular.js" />/// <reference path="../angular.min.js" />  var app;(function () {    app = angular.module("RESTClientModule", []);})();

 

Services.js: 这里我们创建一个shanucontroller.js.用于Angular Service"AngularJs_WCFService",你可以用你自定义的名称,但注意须同时修改Controllers.js中的该名称,Angularjs可以接收Json格式数据,这里已完成了调用WCF完成从数据库中数据的获取.

/// <reference path="../angular.js" /> 
/// <reference path="../angular.min.js" />  
/// <reference path="Modules.js" />    

app.service("AngularJs_WCFService", function ($http) {
    //Get Order Master Records 
    this.geMenuDetails = function () {
        return $http.get("http://localhost:3514/Service1.svc/GetMenuDetails");
    };    
});

AngularJs Controller: 

这里我们可以添加Module.jsService.js的引用,Services类似,我给新建的Controller命名为"AngularJsShanu_WCFController".这个Controller完成了业务逻辑并且从WCF获取返回的Json数据,以给予我们的Html Page.

1) 变量声明

首先我们声明$scope.date用于存储当前日期.



注意: $scope.subChildIDS = "ITM001";  这个变量已用于过滤二级菜单. 

2) 方法

getAllMenuDetails() : 这个方法用于获取所有的详情菜单Json数据并与MainPage绑定.

$scope.showsubMenu = function (showMenus,ids) {}这个方法用于鼠标移入时显示二级详情菜单和添加菜单元素进菜单列表.

shanuController.js 全部源码

/// <reference path="../angular.js" /> 
/// <reference path="../angular.min.js" />  
/// <reference path="Modules.js" />  
/// <reference path="Services.js" />  

app.controller("AngularJsShanu_WCFController", function ($scope, $window, AngularJs_WCFService) {
    $scope.date = new Date();
    $scope.showDetails = false;
    $scope.showSubDetails = false;
    $scope.subChildIDS = "ITM001";
    $scope.Imagename = "R1.png";
    getAllMenuDetails();
    //To Get All Records  
    function getAllMenuDetails() {
        var promiseGet = AngularJs_WCFService.geMenuDetails();
        promiseGet.then(function (pl) {
            $scope.MenuDetailsDisp = pl.data
        },
             function (errorPl) {
             });
    }

    $scope.showMenu = function (showMenus) {

        if (showMenus == 1) {
            $scope.Imagename = "R2.png"
            $scope.showDetails = true;
        }
        else {
            $scope.Imagename = "R1.png"
            $scope.showDetails = false;
        }
    }

    $scope.showsubMenu = function (showMenus,ids) {    

        if (showMenus == 1) {
            $scope.subChildIDS = ids;        
            $scope.showSubDetails = true;       
        }
        else if(showMenus == 0) {
            $scope.showSubDetails = false;        
        }    
        else {       
           $scope.showSubDetails = true;       
        }      
    }
});

现在我们已经创建了AngularJS Module/Controller/Service,然后下一步要做什么呢?S

创建MVC控制器和视图用于显示我们的结果.

添加控制器

右键菜单Controllers,然后选择创建一个新的MVC 5 空控制器.

public class MastersController : Controller
    {
        // GET: Masters
        public ActionResult Index()
        { return View(); }

        public ActionResult ItemDetails()
        { return View(); }

        public ActionResult ItemManage()
        { return View(); }
        public ActionResult CATDetails()
        { return View(); }

        public ActionResult CATManage()
        { return View(); }
    }


public class InventoryController : Controller
    {
        // GET: Inventory
        public ActionResult Index()
        {
            return View();
        }

        public ActionResult FGIN()
        {
            return View();
        }
        public ActionResult FGOUT()
        {
            return View();
        }

    }

 

 

1) Index 视图
在这个视图中设计你的页面并引入Angular.js,Modules.js,Services.jsControllers.js
在Angular JS中我们使用{{}}绑定或显示数据
首先我创建一个表并加入一些东西

<li data-ng-repeat="menus in MenuDetailsDisp | filter:{Menu_RootID:'Root'}">
                                        @{
                                            var url = Url.Action("{{menus.MenuFileName}}", "{{menus.MenuURL}}", new { id = "{{id=menus.MenuURL}}" });
                                            url = HttpUtility.UrlDecode(url);
                                        }
                                        <a data-ng-href="@url">{{menus.MenuDisplayTxt}}</a>
                                        <ul class="sub-menu">
                                            <li data-ng-repeat="submenus in MenuDetailsDisp | filter:{Menu_RootID:menus.Menu_ChildID}" ng-mouseover="showsubMenu(1,submenus.Menu_ChildID);" ng-mouseout="showsubMenu(0,submenus.Menu_ChildID);">
                                                @{
                                                    var url1 = Url.Action("{{submenus.MenuFileName}}", "{{submenus.MenuURL}}", new { id = "{{id=submenus.MenuURL}}" });
                                                    url1 = HttpUtility.UrlDecode(url1);
                                                }
                                                <a data-ng-href="@url1">{{submenus.MenuDisplayTxt}}</a>
Here we can see for the 2nd level hierarchy I have filtered by data-ng-repeat="submenus in MenuDetailsDisp | filter :{Menu_RootID:menus.Menu_ChildID}" where menus.Menu_ChildID is the top level menu id.
 
Same like this for 3rd level Hierarchy I will give the 2nd level hierarchy root id as below.
Hide   Shrink    Copy Code
<div style="overflow:visible;height:100px;">
                                <ul class="menu">
                       <li data-ng-repeat="menus in MenuDetailsDisp | filter:{Menu_RootID:'Root'}">
                                        @{
                                            var url = Url.Action("{{menus.MenuFileName}}", "{{menus.MenuURL}}", new { id = "{{id=menus.MenuURL}}" });
                                            url = HttpUtility.UrlDecode(url);
                                        }
                                        <a data-ng-href="@url">{{menus.MenuDisplayTxt}}</a>
                                        <ul class="sub-menu">
                                            <li data-ng-repeat="submenus in MenuDetailsDisp | filter:{Menu_RootID:menus.Menu_ChildID}" ng-mouseover="showsubMenu(1,submenus.Menu_ChildID);" ng-mouseout="showsubMenu(0,submenus.Menu_ChildID);">
                                                @{
                                                    var url1 = Url.Action("{{submenus.MenuFileName}}", "{{submenus.MenuURL}}", new { id = "{{id=submenus.MenuURL}}" });
                                                    url1 = HttpUtility.UrlDecode(url1);
                                                }
                                                <a data-ng-href="@url1">{{submenus.MenuDisplayTxt}}</a>
                                                <ul ng-show="showSubDetails" class="sub-menu2">
                                                    <li data-ng-repeat="sub1menus in MenuDetailsDisp  | filter:{Menu_RootID:subChildIDS}" ng-mouseover="showsubMenu(3,9);">
                                                        @{
                                                            var url2 = Url.Action("{{sub1menus.MenuFileName}}", "{{sub1menus.MenuURL}}", new { id = "{{id=sub1menus.MenuURL}}" });
                                                            url2 = HttpUtility.UrlDecode(url2);
                                                        }
                                                        <a data-ng-href="@url2">{{sub1menus.MenuDisplayTxt}}</a>
                                                    </li>
                                                </ul>
                                            </li>
                                        </ul>
                                    </li>
                                </ul>
                            </div>

我们可以看到2级菜单已经过滤, data-ng-repeat="submenus in MenuDetailsDisp | filter :{Menu_RootID:menus.Menu_ChildID}" where menus.Menu_ChildID 是顶级菜单ID 

同三级分级一样,我将给二级菜单root id如下.

 

好的,运行程序吧

 

<li data-ng-repeat="menus in MenuDetailsDisp | filter:{Menu_RootID:'Root'}">
                                        @{
                                            var url = Url.Action("{{menus.MenuFileName}}", "{{menus.MenuURL}}", new { id = "{{id=menus.MenuURL}}" });
                                            url = HttpUtility.UrlDecode(url);
                                        }
                                        <a data-ng-href="@url">{{menus.MenuDisplayTxt}}</a>
                                        <ul class="sub-menu">
                                            <li data-ng-repeat="submenus in MenuDetailsDisp | filter:{Menu_RootID:menus.Menu_ChildID}" ng-mouseover="showsubMenu(1,submenus.Menu_ChildID);" ng-mouseout="showsubMenu(0,submenus.Menu_ChildID);">
                                                @{
                                                    var url1 = Url.Action("{{submenus.MenuFileName}}", "{{submenus.MenuURL}}", new { id = "{{id=submenus.MenuURL}}" });
                                                    url1 = HttpUtility.UrlDecode(url1);
                                                }
                                                <a data-ng-href="@url1">{{submenus.MenuDisplayTxt}}</a>
Here we can see for the 2nd level hierarchy I have filtered by data-ng-repeat="submenus in MenuDetailsDisp | filter :{Menu_RootID:menus.Menu_ChildID}" where menus.Menu_ChildID is the top level menu id.
 
Same like this for 3rd level Hierarchy I will give the 2nd level hierarchy root id as below.
Hide   Shrink    Copy Code
<div style="overflow:visible;height:100px;">
                                <ul class="menu">
                       <li data-ng-repeat="menus in MenuDetailsDisp | filter:{Menu_RootID:'Root'}">
                                        @{
                                            var url = Url.Action("{{menus.MenuFileName}}", "{{menus.MenuURL}}", new { id = "{{id=menus.MenuURL}}" });
                                            url = HttpUtility.UrlDecode(url);
                                        }
                                        <a data-ng-href="@url">{{menus.MenuDisplayTxt}}</a>
                                        <ul class="sub-menu">
                                            <li data-ng-repeat="submenus in MenuDetailsDisp | filter:{Menu_RootID:menus.Menu_ChildID}" ng-mouseover="showsubMenu(1,submenus.Menu_ChildID);" ng-mouseout="showsubMenu(0,submenus.Menu_ChildID);">
                                                @{
                                                    var url1 = Url.Action("{{submenus.MenuFileName}}", "{{submenus.MenuURL}}", new { id = "{{id=submenus.MenuURL}}" });
                                                    url1 = HttpUtility.UrlDecode(url1);
                                                }
                                                <a data-ng-href="@url1">{{submenus.MenuDisplayTxt}}</a>
                                                <ul ng-show="showSubDetails" class="sub-menu2">
                                                    <li data-ng-repeat="sub1menus in MenuDetailsDisp  | filter:{Menu_RootID:subChildIDS}" ng-mouseover="showsubMenu(3,9);">
                                                        @{
                                                            var url2 = Url.Action("{{sub1menus.MenuFileName}}", "{{sub1menus.MenuURL}}", new { id = "{{id=sub1menus.MenuURL}}" });
                                                            url2 = HttpUtility.UrlDecode(url2);
                                                        }
                                                        <a data-ng-href="@url2">{{sub1menus.MenuDisplayTxt}}</a>
                                                    </li>
                                                </ul>
                                            </li>
                                        </ul>
                                    </li>
                                </ul>
                            </div>

初次翻译,如有错误请见谅.

 

原文地址:https://www.cnblogs.com/CoffeeBreak/p/4554363.html