前端使用AngularJS的$resource,后端ASP.NET Web API,实现分页、过滤
在上一篇中实现了增删改查,本篇实现分页和过滤。
本系列包括:
1、前端使用AngularJS的$resource,后端ASP.NET Web API,实现增删改查
2、前端使用AngularJS的$resource,后端ASP.NET Web API,实现分页、过滤
后端添加分页、排序逻辑
首先要在后端API中添加分页的逻辑。对于分页来说,一般需要从前端获取页容量和当前页变量,还可以获取有关排序的变量。大致这样:
public IHttpActionResult Get(int pageSize, int pageNumber, string orderBy = ""){}
在StudentsController这个控制器中,增加一个Get重载方法,用于接受分页变量。
[RoutePrefix("api/Students")]
public class StudentsController : ApiController
{
private StudentsReop _reop = new StudentsReop(); //GET api/Students
public HttpResponseMessage Get()
{
var students = _reop.Query().ToList();
return Request.CreateResponse(HttpStatusCode.OK, students);
} //GET api/Students/5
public HttpResponseMessage Get(int id)
{
var student = _reop.Get(id);
return Request.CreateResponse(HttpStatusCode.OK, student);
} //GET api/Students/pageSize/pageNumber/orderBy(optional)
[Route("{pageSize:int}/{pageNumber:int}/{orderBy:alpha?}")]
public IHttpActionResult Get(int pageSize, int pageNumber, string orderBy = "")
{
var totalCount = _reop.Query().ToList().Count();//总数量
var totalPages = Math.Ceiling((double)totalCount/pageSize);//总页数和pageSize有关
var tempResult = _reop.Query(); if (QueryHelper.PropertyExists<StudentVm>(orderBy))
{
var orderByExpression = QueryHelper.GetPropertyExpression<StudentVm>(orderBy);
tempResult = tempResult.AsQueryable().OrderBy(orderByExpression);
}
else
{
tempResult = tempResult.OrderBy(c => c.Id);
} var students = tempResult.Skip((pageNumber - ) * pageSize)
.Take(pageSize)
.ToList(); var result = new
{
TotalCount = totalCount,
TotalPages = totalPages,
Students = students
}; return Ok(result); } //POST api/Students
public void Post([FromBody]StudentVm student)
{
_reop.Post(student);
} //PUT api/Students/5
public void Put(int id, [FromBody]StudentVm student)
{
_reop.Put(id, student);
} //DELETE api/Students
public void Delete(int id)
{
_reop.Delete(id);
}
}
以上,Get(int pageSize, int pageNumber, string orderBy = "")方法中,首先获取排序后的临时数据,再使用skip,take方法获取分页数据,最后返回给前端一个json数据,其中,TotalCount表示总数据量,Students表示当前页下的数据,这2个字段供前端读取。另外,QueryHelper封装了可以根据模型字段获取表达式树的方法。
internal static class QueryHelper
{
public static bool PropertyExists<T>(string propertyName)
{
return typeof(T).GetProperty(propertyName, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance) != null;
} public static Expression<Func<T, string>> GetPropertyExpression<T>(string propertyName)
{
if (typeof(T).GetProperty(propertyName, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance) == null)
{
return null;
} var paramterExpression = Expression.Parameter(typeof(T)); return (Expression<Func<T, string>>)Expression.Lambda(Expression.PropertyOrField(paramterExpression, propertyName), paramterExpression);
} public static Expression<Func<T, int>> GetPropertyExpressionInt<T>(string propertyName)
{
if (typeof(T).GetProperty(propertyName, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance) == null)
{
return null;
} var paramterExpression = Expression.Parameter(typeof(T)); return (Expression<Func<T, int>>)Expression.Lambda(Expression.PropertyOrField(paramterExpression, propertyName), paramterExpression);
}
}
此时,通过浏览器可以获取到分页数据。比如:http://localhost:49621/api/Students/5/2/Name
前端准备
前端需要用到Michael Bromley写的一个分页Directive。 通过如下可安装:
bower install angular-utils-pagination
或
npm install angular-utils-pagination
还需要安装bootstrap和jquery:
npm install bootstrap
npm install jquery
文件结构变为:
app.js 主module,路由都在这里配置
index.html 主视图,引用所有的css,js文件,提供让其它部分视图呈现的一块区域<div ng-view></div>
.....service/ 自定义服务,$resouce的核心就封装在这里
..........studentService.js
.....controller/
..........studentsCtrl.js 列表
..........studentUpdateCtrl.js 更新
..........studentCreateCtrl.js 添加
.....views/
..........Students.html 列表
..........StudentInfo.html 更新
..........StudentCreate.html 添加
vendor/
......diaPagination/ Michael Bromley写的directive
..........dirPagination.css
..........dirPagination.js
..........dirPagination.tpl.html
index.html
相对于上一篇,添加了如下:
<link rel="stylesheet" href="node_modules/bootstrap/dist/css/bootstrap.min.css"/>
<link rel="stylesheet" href="vendor/dirPagination/dirPagination.css"/>
<script src="node_modules/jquery/dist/jquery.min.js"></script>
<script src="node_modules/bootstrap/dist/js/bootstrap.min.js"></script>
<script src="vendor/dirPagination/dirPagination.js"></script>
并使用上了bootstrap。
<!DOCTYPE html>
<html lang="en" ng-app="studentManagement">
<head>
<meta charset="UTF-8">
<title>{{title}}</title>
<link rel="stylesheet" href="node_modules/alertify/themes/alertify.core.css"/>
<link rel="stylesheet" href="node_modules/bootstrap/dist/css/bootstrap.min.css"/>
<link rel="stylesheet" href="vendor/dirPagination/dirPagination.css"/>
</head>
<body>
<div>
<p>
<a href="#/">Students</a>
<a href="#/Create">Create Student</a>
</p>
</div> <div class="container">
<div class="row">
<div class="col-lg-8">
<div ng-view></div>
</div>
</div>
</div> <script src="node_modules/angular/angular.min.js"></script>
<script src="node_modules/angular-route/angular-route.min.js"></script>
<script src="node_modules/angular-resource/angular-resource.min.js"></script>
<script src="node_modules/angular-cookies/angular-cookies.min.js"></script>
<script src="node_modules/alertify/lib/alertify.min.js"></script>
<script src="node_modules/jquery/dist/jquery.min.js"></script>
<script src="node_modules/bootstrap/dist/js/bootstrap.min.js"></script> <script src="app.js"></script> <script src="service/studentService.js"></script>
<script src="controller/studentUpdateCtrl.js"></script>
<script src="controller/studentsCtrl.js"></script>
<script src="controller/studentCreateCtrl.js"></script>
<script src="vendor/dirPagination/dirPagination.js"></script> </body>
</html>
app.js
对比上一篇,这里添加了对angularUtils.directives.dirPagination这个module的依赖,去掉了/这个路由中有关resolve获取数据的机制,因为现在要分页了,每次都要获取数据,而不是把所有数据先从服务端获取到放到路由中。
"use strict"; var studentsManagement = angular.module("studentManagement",["ngResource","ngCookies","ngRoute","angularUtils.directives.dirPagination"])
.run(function($rootScope){
$rootScope.title = "Home";
})
.config(["$routeProvider","$locationProvider", function($routeProvider, $locationProvider){ //在全局配置分页模板 需要注入paginationTemplateProvider
//paginationTemplateProvider.setPath('path/to/dirPagination.tpl.html'); //关于url的基本配置
//$locationProvider.html5Mode({
// enabled: true,
// requireBase: false
//}); //配置路由
$routeProvider.when("/", {
templateUrl: "views/Students.html",
controller: "studentsCtrl"
//resolve: {
// students: function($q,studentDataService){
//
// var queryArgs = {
// pageSize: 3,
// pageNumber: 1,
// orderBy: "id"
// };
//
// //$q异步执行方法
// var deferred = $q.defer();
// studentDataService.query(function(data){
// deferred.resolve(data);
// });
//
// return deferred.promise;
// }
//}
}).when("/Student/:id",{
templateUrl: "views/StudentInfo.html",
controller: "studentUpdateCtrl",
resolve: {
student: function($q, studentDataService, $route){
var defered = $q.defer(); //从路由中获取id的值
var id = $route.current.params.id; studentDataService.get({id: id}, function(data){
defered.resolve(data);
}); return defered.promise;
}
}
}).when("/Create",{
templateUrl: "views/CreateStudent.html",
controller: "studentCreateCtrl"
}); }]);
以上,我们还可以通过paginationTemplateProvider.setPath('path/to/dirPagination.tpl.html');在全局中配置分页模板,但这里没有。
studentService.js
用$resouce封装请求数据这块有变化,因为要带上分页、排序参数。
angular.module('studentManagement').factory("studentDataService",["$resource", function($resource){ var baseUrl = "http://localhost:49621/api/Students";
return $resource("http://localhost:49621/api/Students",{},{
query: {
method: "GET",
url: baseUrl + "/:pageSize/:pageNumber/:orderBy",
params: {pageSize: '@pageSize', pageNumber: '@pageNumber', orderBy: '@orderBy'}
},
//query: {
// method: "GET",
// isArray: true,
//},
create: {method: "POST"},
get: {method: "GET", url: baseUrl + "?id=:id"},
remove: {method: "DELETE", url: baseUrl + "?id=:id"},
update: {method: "PUT", url: baseUrl + "?id=:id"}
})
}]);
studentsControl.js
angular.module('studentManagement').controller("studentsCtrl", ['$scope', '$route', '$rootScope', 'studentDataService', function ($scope, $route, $rootScope, studentDataService) { $scope.students = [];
$scope.total = 0; //总数据条数
$scope.currentPage = 1;
$scope.pageSize = 3; //页容量 //初次加载
getPageStudents(1); $scope.pageChangeHandler = function (num) {
getPageStudents(num);
}; //获取分页数据
function getPageStudents(pageNumber){
var queryArgs = {
pageSize: $scope.pageSize,
pageNumber: pageNumber,
orderBy: 'name'
}; studentDataService.query(queryArgs).$promise.then(function(result){
$scope.students = result.students;
$scope.total = result.totalCount;
}, function(result){ //如果失败
console.log('fail'); });
} $rootScope.title = "Students"; //$scope.students = $route.current.locals.students;//students在路由resolve中定义 //删除
$scope.removeStudent = function (id, student) {
studentDataService.remove({id: id}).$promise.then(function () {
//获取student在当前集合中的索引
var index = $scope.students.indexOf(student);
$scope.students.splice(index, 1);
alertify.log(student.Name + ' is removed');
});
}; }]);
//.controller("OtherController", ["$scope", function ($scope) {
// $scope.pageChangeHandler = function (num) {
// console.log('going to page ' + num);
// };
//}]);
以上,初次加载以及点击分页按钮的时候都触发getPageStudents方法,传入页容量和当前页变量。
Students.html
在dir-paginate中多了一个total-items属性,把从controller中获取到的total变量值赋值给它。
<!--显示内容的控制器-->
<div class="my-controller"> <div class="row">
<div class="col-xs-4">
<h3>当前页: {{ currentPage }}</h3>
</div>
<div class="col-xs-4">
<label for="search">搜索:</label>
<input ng-model="q" id="search" class="form-control" placeholder="Filter text">
</div>
<div class="col-xs-4">
<label for="search">每页条数:</label>
<input type="number" min="1" max="100" class="form-control" ng-model="pageSize">
</div>
</div>
<br>
<div class="panel panel-default">
<div class="panel-body"> <table>
<thead>
<tr>
<th>Name</th><th>Age</th><th>Actions</th>
</tr>
</thead>
<tbody>
<!--itemsPerPage是必须的,要放在所有过滤的最后面,表示页容量-->
<!--dir-paginate的pagination-id属性,可选,和dir-pagination-controls中的pagination-id对应-->
<!--dir-paginate的current-page属性,可选,默认会读取$scope中的_currentPage字段-->
<!--dir-paginate的total-items属性,可选,用来读取服务端数据,先把总页数显示出来-->
<tr dir-paginate="student in students | filter:q | itemsPerPage: pageSize" total-items="total" current-page="currentPage">
<td>{{student.name}}</td>
<td>{{student.age}}</td>
<td>
<a href="#/Student/{{student.Id}}">更新</a>
<a href="javascript:void(0)" ng-click="$parent.removeStudent(student.Id, student)">移除</a>
</td>
</tr>
</tbody>
</table> </div>
</div>
</div> <!--显示分页的控制器-->
<!--<div ng-controller="OtherController" class="other-controller">-->
<div class="other-controller">
<div class="text-center">
<!--其它属性包括:max-size, direction-links,boundary-links,pagination-id,auto-hide-->
<!--max-size:可选,默认为最大是9,最小是5-->
<!--direction-links:可选,默认true,决定是否显示向前向后按钮-->
<!--boundary-links,可选,默认false,决定是否显示首页和最后一页按钮-->
<!--on-page-change,可选,默认为null,声明当点击页数按钮后的回调函数,一旦声明,必须传入newPageNumber形参,必须在$scope中声明回调函数,比如这里的pageCHnageHandler函数-->
<!--pagination-id,可选,与dir-paginate中的pagination-id值对应-->
<!--template-url,可选,默认值是directives/pagination/dirPagination.tpl.html,也可以在全局config中,通过paginationTemplateProvider配置-->
<!--auto-hide,可选,默认是true,决定当没有足够的分页数据时,分页是否显示-->
<!--这里的dir-pagination-controls不能离开dir-paginate而单独存在,否则报错-->
<dir-pagination-controls boundary-links="true" on-page-change="pageChangeHandler(newPageNumber)" template-url="vendor/dirPagination/dirPagination.tpl.html"></dir-pagination-controls>
</div>
</div>
本系列结束☺
参考资料:
有关Web API配合AngularJS分页:
● https://code.msdn.microsoft.com/AngularJS-with-Web-API-43e5de16
有关AngularJS分页的Directive:
● http://www.michaelbromley.co.uk/blog/108/paginate-almost-anything-in-angularjs
● https://github.com/michaelbromley/angularUtils/tree/master/src/directives/pagination#working-with-asynchronous-data
前端使用AngularJS的$resource,后端ASP.NET Web API,实现分页、过滤的更多相关文章
- 前端使用AngularJS的$resource,后端ASP.NET Web API,实现增删改查
AngularJS中的$resource服务相比$http服务更适合与RESTful服务进行交互.本篇后端使用ASP.NET Web API, 前端使用$resource,实现增删改查. 本系列包括: ...
- AngularJS使用OData请求ASP.NET Web API资源的思路
本篇整理AngularJS使用OData请求ASP.NET Web API资源的思路. 首先给ASP.NET Web API插上OData的翅膀,通过NuGet安装OData. 然后,给control ...
- 前端AngularJS后端ASP.NET Web API上传文件
本篇体验使用AngularJS向后端ASP.NET API控制器上传文件. 首先服务端: public class FilesController : ApiController { //usi ...
- ASP.NET Web API教程 分页查询
首先增加支持分页的API方法 public IEnumerable<UserInfo> GetUserInfos(int pageindex, int size) { ...
- ASP.NET Web API 2 external logins with Facebook and Google in AngularJS app
转载:http://bitoftech.net/2014/08/11/asp-net-web-api-2-external-logins-social-logins-facebook-google-a ...
- ASP.NET Web API中把分页信息放Header中返回给前端
谈到ASP.NET Web API的分页,考虑的因素包括: 1.上一页和下一页的uri2.总数和总页数3.当前页和页容量 接着是服务端的数据以怎样的形式返回? 我们通常这样写: { totalC ...
- ASP.NET Web API接受AngualrJS的QueryString的两种方式
ASP.NET Web API如何接受来自AngualrJS的QueryString呢?本篇体验两种方式. 第一种方式:http://localhost:49705/api/products?sear ...
- 购物车Demo,前端使用AngularJS,后端使用ASP.NET Web API(2)--前端,以及前后端Session
原文:购物车Demo,前端使用AngularJS,后端使用ASP.NET Web API(2)--前端,以及前后端Session chsakell分享了前端使用AngularJS,后端使用ASP.NE ...
- 前端angularjs+requirejs+dhtmlx 后端asp.net webapi
享一个前后端分离方案源码-前端angularjs+requirejs+dhtmlx 后端asp.net webapi 一.前言 半年前左右折腾了一个前后端分离的架子,这几天才想起来翻出来分享给大家 ...
随机推荐
- flask基础之请求钩子(十二)
前言 什么是请求钩子?在客户端和服务器交互的过程中,有些准备工作或扫尾工作需要统一处理,为了让每个视图函数避免编写重复功能的代码,flask提供了统一的接口可以添加这些处理函数,即请求钩子. 请求钩子 ...
- VUE之搭建脚手架
原文转自http://blog.csdn.net/Shiyaru1314/article/details/54963027 目录(?)[-] 1 安装之前需要检查是否已经安装NodeJS的环境 安装文 ...
- Java编程的逻辑 (69) - 线程的中断
本系列文章经补充和完善,已修订整理成书<Java编程的逻辑>,由机械工业出版社华章分社出版,于2018年1月上市热销,读者好评如潮!各大网店和书店有售,欢迎购买,京东自营链接:http: ...
- K8S Dashborad登陆认证文档
K8S Dashboard是官方的一个基于WEB的用户界面,专门用来管理K8S集群,并可展示集群的状态.因为我们使用kubeadm搭建的集群会默认开启RABC(角色访问控制机制),所以我们必须要进行额 ...
- JS图形化插件利器组件系列 —— Gojs组件
阅读目录 一.组件效果预览 二.初次接触 1.Gojs简介 2.使用入门 三.综合效果 1.自定义流程的使用 2.工业流程图 四.总结 正文 前言:之前分享过两篇关于流程画图的前端组件,使用的jsPl ...
- [C编码笔记] 空串与NULL是不一样的
int main() { char *str = NULL; printf("%p \n", str); printf("%p \n", &str); ...
- python全栈开发之匿名函数和递归函数
python 匿名函数和递归函数 python全栈开发,匿名函数,递归函数 匿名函数 lambda函数也叫匿名函数,即函数没有具体的名称.是为了解决一些功能很简单需求而设计的一句话函数.如下: #这段 ...
- activiti初学
公司现有的工作流是比较老的JBPM,用起来不太方便,经常性的流程跑一半就停止不前了.闲暇之余学习下activiti的使用,基本配置如下: 1.创建pom.xml文件所依赖的jar包 <proje ...
- mongodb for windows安装
1,下载mongodb for windwos 下载地址:https://www.mongodb.com/download-center#community 2,创建db和log的文件夹 D:\dat ...
- 开发人员如何正确对待BUG?
1.前端开发与后端开发 出了问题,最重要的是先找到方法迅速解决,而不是去互相指责.前端存在这样的思维模式,后端也存在这样的思维模式,这种思维模式不太好.出了问题,最好先检查一下自己,反省是不是自己这 ...