原文地址:http://www.codeproject.com/Articles/808213/Developing-a-Large-Scale-Application-with-a-Single

AngularUI

下面的示例中使用了AngularUI的各种UI组件。AngularUI 是AngularJS 框架的一个辅助套件。示例中使用的主要组件大部分来在AngularUI 的一个子集UI Bootstrap。UI Bootstrap是从Twitter Bootstrap派生出来的,它使用AngularJS编码实现。 UI Bootstrap库包含了一套使用Bootstrap标识和样式的AngularJS 指令。 这使得它不依赖jQuery.js和Bootstrap.js。

Alert (ui.bootstrap.alert)

AngularJS Alert 是由Bootstrap alert 派生过来的。 使用ng-repeat指令,可以实现动态弹窗提示模型里的数据问题。

<div style="padding-top:20px">
<alert ng-repeat="alert in alerts" type="{{alert.type}}" close="closeAlert($index)">
<div ng-bind-html="MessageBox"></div>
</alert>
</div>

为了更好的拓展警告指令, 这个示例应用程序包含了一个自定义的指令服务(custom alerts service).它可以在整个应用程序中使用,以渲染警告信息.信息的内容设置在$rootScope里面,它来自于服务器的业务层的验证过程,并在AJAX请求完成后渲染到客户端.

// alertsService.js

define(['application-configuration'], function (app)
{
app.register.service('alertsService', ['$rootScope', function ($rootScope) { $rootScope.alerts = [];
$rootScope.MessageBox = ""; this.SetValidationErrors = function (scope, validationErrors) {
for (var prop in validationErrors) {
var property = prop + "InputError";
scope[property] = true;
}
} this.RenderErrorMessage = function (message) {
var messageBox = formatMessage(message);
$rootScope.alerts = [];
$rootScope.MessageBox = messageBox;
$rootScope.alerts.push({ 'type': 'danger', 'msg': '' });
}; this.RenderSuccessMessage = function (message) {
var messageBox = formatMessage(message);
$rootScope.alerts = [];
$rootScope.MessageBox = messageBox;
$rootScope.alerts.push({ 'type': 'success', 'msg': '' });
}; this.RenderWarningMessage = function (message) {
var messageBox = formatMessage(message);
$rootScope.alerts = [];
$rootScope.MessageBox = messageBox;
$rootScope.alerts.push({ 'type': 'warning', 'msg': '' });
}; this.RenderInformationalMessage = function (message) {
var messageBox = formatMessage(message);
$rootScope.alerts = [];
$rootScope.MessageBox = messageBox;
$rootScope.alerts.push({ 'type': 'info', 'msg': '' });
}; this.closeAlert = function (index) {
$rootScope.alerts.splice(index, 1);
}; function formatMessage(message) {
var messageBox = "";
if (angular.isArray(message) == true) {
for (var i = 0; i < message.length; i++) {
messageBox = messageBox + message[i];
}
}
else {
messageBox = message;
}
return messageBox;
}
}]);
});

当新增一个客户记录出错时,下面的代码被执行,同时调用警告服务.  

$scope.createCustomerError = function (response) {
alertsService.RenderErrorMessage(response.ReturnMessage);
$scope.clearValidationErrors();
alertsService.SetValidationErrors($scope, response.ValidationErrors);
}

Datepicker控件 (ui.bootstrap.datepicker)

UI Bootstrap Datepicker控件 是一种清洁、灵活和完全可定制的日期选择器。

把Datepicker相关的参数添加到输入框,然后添加一个按钮,用户可以通过单击日历图标显示Datepicker。

<tr>
<td class="input-label" align="right"><label class="required">Required Ship Date:</label></td>
<td class="input-box" style="height:50px">
<div ng-bind="RequiredDate" ng-show="DisplayMode"></div>
<div ng-show="EditMode">
<div class="row">
<div class="col-md-6">
<p class="input-group"> <input ng-class="{'validation-error': RequiredDateInputError}" type="text" style="width:100px"
datepicker-popup="MM/dd/yyyy"
ng-model="RequiredDate"
is-open="opened"
datepicker-options="dateOptions"
date-disabled="disabled(date, mode)"
ng-required="true"
close-text="Close" /> <button type="button" ng-click="open($event)"><i style="height:10px"
class="glyphicon glyphicon-calendar"></i></button> </p>
</div>
</div>
</div>
</td>
</tr>

Modal (ui.bootstrap.modal)

UI Bootstrap的Modal是一种服务,它可以快速的创建拥有Angular属性的模态对话框.创建定制化的modal是很简单,只需创建部分视图,增加一个控制器,然后在使用服务的时候引用它们.

下面的JavaScript代码为Product Inquiry Modal打开了一个HTML模板,并创建了一个modal实例.当一个产品项目被选中的时候,产品id通过modal实例的结果方法返回.这个modal实例从服务器获取产品信息.产品信息返回到调用页面后,modal消失.

$scope.openModal = function () {

    var modalInstance = $modal.open({
templateUrl: 'productLookupModal.html',
controller: ModalInstanceCtrl,
windowClass: 'app-modal-window'
}); modalInstance.result.then(function (productID) { var getProduct = new Object();
getProduct.ProductID = productID;
productService.getProduct(getProduct,
$scope.getProductCompleted,
$scope.getProductError); }, function () {
// function executed on modal dismissal
});
}; var ModalInstanceCtrl = function ($scope, $modalInstance) { $scope.ProductCode = "";
$scope.ProductDescription = ""; $scope.productSelected = function (productID) {
$modalInstance.close(productID);
}; $scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
};

Typeahead (ui.bootstrap.typeahead)

Typeahead是AngularJS Bootstrap v2版本的typeahead插件.这个指令可以快速创建一个漂亮的基于任意文本框的typeahead控件.Product Inquiry Modal窗口使用了Typeahead指令

<input type="text" ng-model="Description"
typeahead="product for products in getProducts($viewValue)">

在上面例子中的typeahead指令,将把输入框中的输入信息作为参数并执行getProducts函数.然后getProducts函数会调用Products Service来执行一个AJAX请求.这个请求将返回一个基于用户输入信息的产品数据的页面,并设置产品查询数据列表.

$scope.getProducts = function () {
var productInquiry = $scope.createProductInquiryObject();
productService.getProducts(productInquiry,
$scope.productInquiryCompleted, $scope.productInquiryError);
}

Pagination (ui.bootstrap.pagination)

Pagination是一个轻量级的分页指令,它可以提供数据列表分页,显示分页栏以及正确启用和禁用翻页按钮.

<pagination boundary-links="true" total-items="TotalProducts"
items-per-page="PageSize" ng-change="pageChanged()"
ng-model="CurrentPageNumber" class="pagination-lg"
previous-text="Prev" next-text="Next" first-text="First"
last-text="Last"></pagination>

这个应用程序的所有的数据列表都使用了UI Bootstrap分页控件.实际上,有了HTML模板和数据绑定功能,实现多用途的数据列表是很容易的.这个数据列表包含类似于这个应用程序的分页和排序功能.

下面的产品查询数据列表的HTML模板,详细描述了如何使用视图来排序以及分页.在控制器的视图模型中的数据是和表格绑定,其中表格的行是通过AngularJS的ng-repeat指令动态渲染的.这个指令也用于动态创建表头.用户可以通过点击表头来排序.HTML模板和数据绑定功能提供了强大的和简洁的动态生成功能.使用一段时间的HTML模板后,你将不愿再回到使用ASP.NET控件的一团糟的状况了.

<!-- productLookupModal.html -->

<table class="table table-striped table-hover" style="width: 100%;">
<thead>
<tr>
<th colspan="2" style="width: 50%">
<span ng-bind="TotalProducts"></span> Products
</th>
<th colspan="5" style="text-align: right; width: 50%">
Page <span ng-bind="CurrentPageNumber"></span> of
<span ng-bind="TotalPages"></span>
</th>
</tr>
<tr>
<th ng:repeat="tableHeader in tableHeaders" ng:class="setSortIndicator(tableHeader.label)"
ng:click="changeSorting(tableHeader.label)">{{tableHeader.label}}</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="product in products"> <td style="width: 25%; height: 25px"><a ng-click="ok(product.ProductID)"
style=" cursor pointer;
text-decoration underline;
color black">{{product.ProductCode}}</a></td> <td style="width: 50%; white-space: nowrap"><div ng-bind="product.Description"></div></td>
<td style="width: 25%; text-align:left; white-space: nowrap">
<div>{{product.UnitPrice | currency}}</diV></td> </tr> </tbody>
</table>
<pagination boundary-links="true" total-items="TotalProducts" items-per-page="PageSize"
ng-change="pageChanged()" ng-model="CurrentPageNumber" class="pagination-lg"
previous-text="Prev" next-text="Next" first-text="First" last-text="Last">
</pagination>

最后,包装一下产品查询列表,下面的产品查询模态控制器包含了一个自定义数据列表服务引用.它用来在示例应用程序中,为所有的数据列表实现排序功能.这是又一个使用AngularJS Services和Factories的例子.它把代码封装成小的可重复使用的,简洁的,易读的和易于维护的模块.

// productLookupModalController.js

"use strict";
define(['application-configuration', 'productsService', 'alertsService', 'dataGridService'],
function (app) {
app.register.controller('productLookupModalController', ['$scope', '$rootScope',
'productsService', 'alertsService', 'dataGridService', function ($scope, $rootScope, productService, alertsService, dataGridService) { $scope.initializeController = function () { $rootScope.alerts = []; dataGridService.initializeTableHeaders();
dataGridService.addHeader("Product Code", "ProductCode");
dataGridService.addHeader("Product Description", "Description");
dataGridService.addHeader("Unit Price", "UnitPrice"); $scope.tableHeaders = dataGridService.setTableHeaders();
$scope.defaultSort = dataGridService.setDefaultSort("Description"); $scope.changeSorting = function (column) {
dataGridService.changeSorting(
column, $scope.defaultSort, $scope.tableHeaders); $scope.defaultSort = dataGridService.getSort();
$scope.SortDirection = dataGridService.getSortDirection();
$scope.SortExpression = dataGridService.getSortExpression();
$scope.CurrentPageNumber = 1;
$scope.getProducts();
}; $scope.setSortIndicator = function (column) {
return dataGridService.setSortIndicator(column,
$scope.defaultSort); }; $scope.ProductCode = "";
$scope.Description = "";
$scope.PageSize = 5;
$scope.SortDirection = "ASC";
$scope.SortExpression = "Description";
$scope.CurrentPageNumber = 1;
$rootScope.closeAlert = dataGridService.closeAlert;
$scope.products = [];
$scope.getProducts();
} $scope.productInquiryCompleted = function (response, status) {
alertsService.RenderSuccessMessage(response.ReturnMessage);
$scope.products = response.Products;
$scope.TotalProducts = response.TotalRows;
$scope.TotalPages = response.TotalPages;
} $scope.searchProducts = function () {
$scope.CurrentPageNumber = 1;
$scope.getProducts();
} $scope.pageChanged = function () {
$scope.getProducts();
} $scope.getProducts = function () {
var productInquiry = $scope.createProductInquiryObject();
productService.getProducts(productInquiry(
$scope.productInquiryCompleted,
$scope.productInquiryError); } $scope.getProductsTypeAheadProductCode = function (productCode) {
$scope.ProductCode = productCode;
var productInquiry = $scope.createProductInquiryObject(); productService.getProductsWithNoBlock(productInquiry,
$scope.productInquiryCompleted,
$scope.productInquiryError); } $scope.getProductsTypeAheadDescription = function (description) {
$scope.Description = description;
var productInquiry = $scope.createProductInquiryObject(); productService.getProductsWithNoBlock(productInquiry,
$scope.productInquiryCompleted,
$scope.productInquiryError); } $scope.productInquiryError = function (response, status) {
alertsService.RenderErrorMessage(response.Error);
} $scope.resetSearchFields = function () {
$scope.ProductCode = "";
$scope.Description = "";
$scope.getProducts();
} $scope.createProductInquiryObject = function () { var productInquiry = new Object(); productInquiry.ProductCode = $scope.ProductCode;
productInquiry.Description = $scope.Description;
productInquiry.CurrentPageNumber = $scope.CurrentPageNumber;
productInquiry.SortExpression = $scope.SortExpression;
productInquiry.SortDirection = $scope.SortDirection;
productInquiry.PageSize = $scope.PageSize; return productInquiry; }
$scope.setHeaderAlignment = function (label) {
if (label == "Unit Price")
return { 'textAlign': 'right' }
else
return { 'textAlign': 'left' }
}
}]);
});

结论

我敢说jQuery过时了吗?当然,jQuery仍然很流行并广泛使用.但是,过去的一些年见证了结构化设计模式的框架和库,如MVC和MVVM(Model-View-ViewModel)的崛起.这些框架和库包括Backbone.js, Ember.js和AngularJS等.

AngularJS是一个MVC/MVVM framework.它由google创建,以开发具有良好体系结构的和可维护的web应用程序.AngularJS定义了大量的概念来合理的组织web应用程序.应用程序由相互依赖的模块来定义.它通过新的属性或者标签和表达式,关联指令到页面来增强HTML,以定义功能强大的模板.它也将应用程序的行为封装到控制器,这些控制器通过依赖注入的方式实例化.这有利于结构化,而且非常容易测试JavaScript代码.是的,这里有你开发大型应用程序前端代码所需的所有东西.AngularJS可能是自jQuery之后,下一个JavaScript大事件.

创建示例应用程序所用到的技术

AngularJS
RequireJS
Visual Studio Express 2013 for Web
Microsoft .NET 4.5.1
Microsoft .NET C#
Microsoft Web API 2
Microsoft Entity Framework 6.0
SQL Server Express

完~~~

[译]用AngularJS构建大型ASP.NET单页应用(三)的更多相关文章

  1. [译]用AngularJS构建大型ASP.NET单页应用(二)

    原文地址:http://www.codeproject.com/Articles/808213/Developing-a-Large-Scale-Application-with-a-Single 客 ...

  2. [译]用AngularJS构建大型ASP.NET单页应用(一)

    原文地址:http://www.codeproject.com/Articles/808213/Developing-a-Large-Scale-Application-with-a-Single 渣 ...

  3. 使用AngularJS构建大型Web应用

    AngularJS是由Google创建的一种JS框架,使用它可以扩展应用程序中的HTML词汇,从而在web应用程序中使用HTML声明动态内容.在该团队工作的软件工程师Brian Ford近日撰写了一篇 ...

  4. AngularJS开发指南16:AngularJS构建大型Web应用详解

    AngularJS是由Google创建的一种JS框架,使用它可以扩展应用程序中的HTML功能,从而在web应用程序中使用HTML声明动态内容.在该团队工作的软件工程师Brian Ford近日撰写了一篇 ...

  5. 基于Vue2.0+Vue-router构建一个简单的单页应用

    爱编程爱分享,原创文章,转载请注明出处,谢谢!http://www.cnblogs.com/fozero/p/6185492.html 一.介绍 vue.js 是 目前 最火的前端框架,vue.js ...

  6. (译) 在AngularJS中使用的表单验证功能【转】

    验证功能是AngularJS里面最酷炫的功能之一,它可以让你写出一个具有良好用户体验的Web应用. 在AngularJS中,有许多用于验证的指令.我们将先学习几个最流行的内置指令,然后再创建一个自定义 ...

  7. (译) 在AngularJS中使用的表单验证功能

    验证功能是AngularJS里面最酷炫的功能之一,它可以让你写出一个具有良好用户体验的Web应用. 在AngularJS中,有许多用于验证的指令.我们将先学习几个最流行的内置指令,然后再创建一个自定义 ...

  8. 使用 AngularJS 开发一个大规模的单页应用(SPA)

      本文的目标是基于单页面应用程序开发出拥有数百页的内容,包括认证,授权,会话状态等功能,可以支持上千个用户的企业级应用. 下载源代码 介绍 (SPA)这样一个名字里面蕴含着什么呢? 如果你是经典的S ...

  9. 快速构建一个简单的单页vue应用

    技术栈 vue-cli webpack vux,vux-loader less,less-loader vue-jsonp vue-scroller ES6 vue-cli:一个vue脚手架工具,利用 ...

随机推荐

  1. python scrapy版 极客学院爬虫V2

    python scrapy版 极客学院爬虫V2 1 基本技术 使用scrapy 2 这个爬虫的难点是 Request中的headers和cookies 尝试过好多次才成功(模拟登录),否则只能抓免费课 ...

  2. iOS 读取相册二维码,兼容ios7(使用CIDetector 和 ZXingObjC)

    ios从相册读取二维码,在ios8以上,苹果提供了自带的识别图片二维码的功能,这种方式效率最好,也是最推荐的,但是如果你的系统需要向下兼容ios7,就必须用其他方式. 这里我选择的是 ZXingObj ...

  3. 解析json格式数据

    实现目标 读取文件中的json格式数据,一行为一条json格式数据.进行解析封装成实体类. 通过google的Gson对象解析json格式数据 我现在解析的json格式数据为: {",&qu ...

  4. 创建基于Bootstrap的下拉菜单的DropDownList的JQuery插件

    Bootstrap是当下流行的前端UI组件库之一.利用Bootstrap,可以很方便的构造美观.统一的页面.把设计师从具体的UI编码中解放出来.   Bootstrap提供了不少的前端UI组件.带下拉 ...

  5. 【2016-10-10】【坚持学习】【Day1】【观察者模式】

    今天学习了观察者模式 定义: 一个实体变化会影响其他实体变化 例子: 红绿灯与汽车 红绿灯是观察目标 汽车是实际观察者 灯的变化会影响车是停止还是前进. 例子: 游戏中,一个战队由若干队员组成,当其中 ...

  6. POJ 3608 Bridge Across Islands --凸包间距离,旋转卡壳

    题意: 给你两个凸包,求其最短距离. 解法: POJ 我真的是弄不懂了,也不说一声点就是按顺时针给出的,不用调整点顺序. 还是说数据水了,没出乱给点或给逆时针点的数据呢..我直接默认顺时针给的点居然A ...

  7. Java虚拟机详解----JVM常见问题总结

    [声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4 ...

  8. 第10章 同步设备I/O和异步设备I/O(2)_同步IO和异步IO基础

    10.3 执行同步设备I/O (1)对设备读写操作的函数 ①ReadFile/WriteFile函数 参数 描述 hFile 文件句柄 pvBuffer 指向要接收文件数据的缓冲区或把缓冲区数据写入设 ...

  9. PHP加载另一个文件类的方法

    加载另一个文件类的方法 当前文件下有a.php 和b.php,想要在class b中引入class a <?php    class a    {        public $name = ' ...

  10. vijos1426兴奋剂检查(多维费用的背包问题+状态压缩+hash)

    背景 北京奥运会开幕了,这是中国人的骄傲和自豪,中国健儿在运动场上已经创造了一个又一个辉煌,super pig也不例外……………… 描述 虽然兴奋剂是奥运会及其他重要比赛的禁药,是禁止服用的.但是运动 ...