AngularJS 后端解决方案:ng-grid 与简单 REST API





5.00/5 (6投票s)
使用 AngularJS 和 REST 对 ng-grid 进行筛选、排序和分页
引言
任何项目都普遍要求以某种表格形式显示数据。最简单的方法是使用 HTML 表格。但很快,这会变得复杂,因为您需要一种方式来支持分页(客户端和服务器端)、排序(单列和多列)、可调整大小的列、行内编辑、筛选等。本文/代码片段的作用、其有用性、它解决的问题等。
Using the Code
第一个网格解决方案
我们将要看的第一个解决方案是 `ng-grid`,它专为 AngularJS 构建,是 Angular 中最流行的网格解决方案。
从何开始
在这个项目中,我们将使用 Angular 和 `ng-grid` 构建一个网格解决方案,它通过 NodeJS 和 ExpressJS 钩入本地运行的 RESTful 端点。我们将使用 Node 和 Express 的基本功能。在深入探讨之前,您可能希望在 Plunker 上查看工作代码:http://embed.plnkr.co。
假设
- 您已经了解 AngularJS
- 了解 Grunt、Bower 和 Bootstrap 的基础知识
- 对 REST 有基本了解
- 您的开发机器上已经安装了 node、npm、git 和 bower
项目结构
我们将使用以下 Angular 种子项目
https://github.com/libertyleap/angular-grunt-seed
这是一个种子项目,它带有用于 lint、karma、watch、livereload、express 服务器等的默认 bower 和 grunt 构建。
设置和运行种子项目的步骤
- 克隆项目
> git clone https://github.com/backand/ng-grid-rest-simple-demo
- 将项目从 `angular-grunt-seed` 重命名为 `ng-grid-demo`
> mv angular-grunt-seed ng-grid-demo
- 将当前目录更改为 *ng-grid-demo*
> cd ng-grid-demo
- 执行 `npm install`,以便下载所有 Grunt 依赖项,它还会运行 bower install
> npm install
- 执行 `grunt`,这将启动端口 9000 上的本地 Node 服务器
> grunt
- 打开您喜欢的浏览器并访问:https://:9000/
使用 Bower 将 NG-Grid 添加到种子项目
将 `ng-grid` 添加到种子项目最简单的方法是使用 Bower,我们将在本博客中介绍这种方法。如果您不习惯这样做,您可以手动操作,即,访问 `ng-grid` 仓库:http://angular-ui.github.io/ng-grid/ 并复制下面介绍的所需文件。
> bower install ng-grid –save-dev
以上命令更新了 *ng-grid-demo\bower.json* 文件,添加了 `ng-grid` 作为依赖项。
"devDependencies": {
"ng-grid": "~2.0.12"
}
Bower 将在本地下载 `ng-grid`。您可以通过进入 *bower-components* 文件夹进行验证。您将在 *bower-components* 文件夹中看到一个名为 *ng-grid* 的新文件夹。
将 NG-Grid 与视图 RESTful 服务连接
要在我们的种子项目中使用 `ng-grid`,我们需要引用两个 `ng-grid` 文件。第一个是 JavaScript 文件,第二个是用于网格主题的 CSS 文件。第一步是进入您的 *index.html* 文件,并将 JavaScript 和 CSS 文件都添加为依赖项。
打开 *ng-grid-demo/src/index.html* 文件并添加以下条目
- 在 `<head>` 中,添加此 CSS 依赖项 (*bower-components/ng-grid/ng-grid.css*)。
- 在 `<body>` 部分,添加 `ng-grid` 的 js 依赖项 (*bower-components/ng-grid/ng-grid-2.0.12.debug.js*)。
- 我们需要将“`ngGrid`”Angular 模块依赖项添加到 *app.js*,以便我们可以开始使用 `ng-grid` 的指令和其他服务。
NG-Grid 基本示例
在本节中,我们将介绍添加基本 `ng-grid` 示例所需的步骤。我们将在接下来的部分中探索 `ng-grid` 的高级功能。
为了演示网格功能,我们需要某种 REST 端点。对于这篇博客文章,我们将使用本地 JSON 文件作为 REST 端点,它将提供开源贡献者列表。
REST \ JSON
在 *ng-grid-demo\src* 文件夹下创建一个 *json* 文件夹。创建一个名为 *contributors.json* 的新 json 文件。此 JSON 文件将包含以下内容,这些内容将提供给 UI * \ ng-grid*。
ng-grid-demo\src\json\contributor.json
[{
"id": "1",
"firstname": "Misko",
"lastname": "Havery",
"company": "Google",
"project": "AngularJS"
}, {
"id": "2",
"firstname": "Srini",
"lastname": "Kusunam",
"company": "LibertyLeap",
"project": "Backbone.Paginator"
}, {
"id": "3",
"firstname": "Derick",
"lastname": "Bailey",
"company": "Muted Solutions",
"project": "Backbone.Marionette"
}]
更改 Grunt 构建,将此 json 文件包含在 *.build* 目录中。
Angular Factory
让我们创建一个服务 (*gridService.js*),它将使用 REST 的 `GET` 方法返回上述 JSON。这些数据将异步返回,我们将为此使用 Promise (`$q`)。这是服务代码。
angular.module('angularGruntSeed')
.factory('GridService', ['$http', '$q',
function($http, $q) {
var contributorsFile = 'json/contributors.json';
var contributors = [];
function getContributors() {
var deferred = $q.defer();
$http.get(contributorsFile)
.then(function(result) {
contributors = result.data;
deferred.resolve(contributors);
}, function(error) {
deferred.reject(error);
});
return deferred.promise;
}
return {
getContributors: getContributors
};
}
]);
我们将有一个名为 `getContributors` 的方法,它将使用 Angular 的 `$http` (https://docs.angularjs.org/api/ng/service/$http) 从 *json/contributors.json* 文件获取数据。它还使用了 Angular 的 promise 实现 `$q` (https://docs.angularjs.org/api/ng/service/$q)。
这是这里发生的事情
- 当控制器调用此工厂方法“`getContributors`”时,它将获得一个 promise 对象,即 `deferred.promise`。
- 当异步 `$http` 调用返回响应时,我们将解析延迟对象以返回贡献者列表。
- 如果 `$http` 中出现错误,那么我们将拒绝带有原因的延迟对象,以便调用者可以适当地处理它,即向用户显示某种消息。
控制器 (Controller)
我们将“`GridService`”添加为“`HomeController`”的依赖项,并从 `GridService` 调用“`getContributors`”方法。响应被设置为“`myData`”,它将用于在视图中填充 `ng-grid` 数据。
angular.module('angularGruntSeed')
.controller('HomeController', ['$scope', 'GridService',
function($scope, gridService) {
gridService.getContributors().then(function(data) {
$scope.myData = data;
});
$scope.gridOptions = {
data: 'myData'
};
}
]);
上述步骤 `$scope.gridOptions` 是主要设置,它将 `ng-grid` 配置连接到 `ng-grid` 的视图。
视图
在 HTML 文件中设置网格非常简单,只需创建一个 `div`,并向其中添加 `ng-grid` 指令,参数是我们将很快创建的控制器中的函数。我们还将向 `div` 添加一个简单的类以便于样式设置。更改“templates\home.html”以包含以下代码
<div class="gridStyle" ng-grid="gridOptions"></div>
在这里,“`gridOptions`”是控制器中填充的 `$scope` 对象。
这应该能让基本的 `ng-grid` 运行起来。
NG-Grid 功能
在本节中,我们将探讨 `ng-grid` 的不同配置选项。我们只需要更改 `Controller` 中的 `$scope.gridOptions` 即可支持以下功能。
列定义
任何 `Grid` 都普遍要求列名与 JSON 名称不同。上面的一个例子是我们将“`firstname`”命名为“`First Name`”。
$scope.gridOptions = {
data: 'myData',
// Column definition example
columnDefs: [{field:'id'},{field:'firstname', displayName:'First Name'},
{field:'lastname',displayName:'LastName'},{field:'company'},{field:'project'}]
};
单元格模板示例
以下是如何在 `ng-grid` 中使用 `string` 定义单元格模板的示例。在上面的示例中,我们希望将绿色应用于 `id` 大于 1 的 `id` 列。
$scope.gridOptions = {
data: 'myData',
columnDefs: [
{field:'id', cellTemplate: '
<div ng-class="{green: row.getProperty(col.field) > 1}">
<div class="ngCellText">{{row.getProperty(col.field)}}</div>
</div>
'}, {field:'firstname', displayName:'First Name'},
{field:'lastname', displayName:'Last Name'},
{field:'company'},{field:'project'}] };
行内单元格编辑示例
我们将探讨一个选项,能够编辑 `Grid` 单元格并将其保存到 REST 服务。我们将演示代码,以便能够更新 `Grid` 中贡献者的“`company`”单元格。
homeController.js
我们需要将列定义中的 `enableCellEdit` 属性设置为 `TRUE`。
{
field:'company',
enableCellEdit: true
}
设置此项后,如果您重新启动 `node` 服务器,您将看到双击单元格后 `company` 列变为可编辑。
下一步是我们将此更新的单元格信息发送到 REST 后端。为此,我们将使用 `ng-grid` 的一个 `Event` (`ngGridEventEndCellEdit`),它将在单元格编辑后广播。您可以在此处查看所有可用的 `ng-grid` `Event`:https://github.com/angular-ui/ng-grid/wiki/Grid-Events。
我们将更新控制器以包含以下代码
$scope.$on('ngGridEventEndCellEdit', function(evt){
// Detect changes and send entity to REST server
gridService.saveContributor(evt.targetScope.row.entity);
});
从上面的代码中可以看出,我们希望将更新的行信息发送回 REST 服务。我们需要在我们的 *gridService.js* 中定义一个新方法 `saveContributor`。
gridService.js
function saveContributor(contributor) {
$http.post('/save', contributor).success(function() {
console.log("SAVE success !!!!");
}).error(function() {
console.log("SAVE Error !!!!");
});
}
我们没有真正的 REST 服务,而且由于我们需要某种持久存储,因此不可能演示这一点。您可以打开浏览器的开发人员工具并验证上述 `$http post` 方法是否已使用正确的数据调用。