PRF:20180928 Using Grails with jQuery and DataTables.md

@jrglinux
This commit is contained in:
Xingyu.Wang 2018-11-24 10:25:14 +08:00
parent a4b2a899a2
commit aa3ad7d80b

View File

@ -1,17 +1,17 @@
将 Grails 与 jQuery 和 DataTables 一起使用
在 Grails 中使用 jQuery 和 DataTables
======
本文介绍如何构建一个基于 Grails 的数据浏览器来可视化复杂的表格数据。
> 本文介绍如何构建一个基于 Grails 的数据浏览器来可视化复杂的表格数据。
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/data_container_block.png?itok=S8MbXEYw)
我是 [Grails][1] 的忠实粉丝。当然,我主要是热衷于利用命令行工具来探索和分析数据的数据人。数据人经常需要_查看_数据这也意味着他们通常拥有优秀的数据浏览器。利用 Grails[jQuery][2],以及 [DataTables jQuery 插件][3],我们可以制作出非常友好的表格数据浏览器。
我是 [Grails][1] 的忠实粉丝。当然,我主要是热衷于利用命令行工具来探索和分析数据的数据从业人员。数据从业人员经常需要*查看*数据,这也意味着他们通常拥有优秀的数据浏览器。利用 Grails、[jQuery][2],以及 [DataTables jQuery 插件][3],我们可以制作出非常友好的表格数据浏览器。
[DataTables 网站][3]提供了许多“食谱风格”的教程文档,展示了如何组合一些优秀的示例应用程序,这些程序包含了完成一些非常漂亮的东西所必要的 JavaScriptHTML以及偶尔出现的 [PHP][4]。但对于那些宁愿使用 Grails 作为后端的人来说,有必要进行一些说明示教。此外,样本程序中使用的数据是虚构公司的员工的单个平面表数据,因此处理这些复杂的表关系可以作为读者的一个练习项目。
[DataTables 网站][3]提供了许多“食谱”的教程文档,展示了如何组合一些优秀的示例应用程序,这些程序包含了完成一些非常漂亮的东西所必要的 JavaScriptHTML以及偶尔出现的 [PHP][4]。但对于那些宁愿使用 Grails 作为后端的人来说,有必要进行一些说明示教。此外,样本程序中使用的数据是一个虚构公司的员工的单个平面表数据,因此处理这些复杂的表关系可以作为读者的一个练习项目。
本文中,我们将创建具有略微复杂的数据结构和 DataTables 浏览器的 Grails 应用程序。我们将介绍 Grails 标准 [Groovy][5]-fied Java Hibernate 标准。我已将代码托管在 [GitHub][6] 上方便大家访问,因此本文主要是对代码细节的解读。
本文中,我们将创建具有略微复杂的数据结构和 DataTables 浏览器的 Grails 应用程序。我们将介绍 Grails 标准,它是 [Groovy][5] 式的 Java Hibernate 标准。我已将代码托管在 [GitHub][6] 上方便大家访问,因此本文主要是对代码细节的解读。
首先,你需要配置 JavaGroovyGrails 的使用环境。对于 Grails我倾向于使用终端窗口和 [Vim][7],本文也使用它们。为获得现代 Java建议下载并安装 Linux 发行版提供的 [Open Java Development Kit][8] OpenJDK应该是 Java 8,9,10或11,撰写本文时,我正在使用 Java 8。从我的角度来看获取最新的 Groovy 和 Grails 的最佳方法是使用 [SKDMAN!][9]。
首先,你需要配置 Java、Groovy、Grails 的使用环境。对于 Grails我倾向于使用终端窗口和 [Vim][7],本文也使用它们。为获得现代 Java 环境,建议下载并安装 Linux 发行版提供的 [Open Java Development Kit][8] OpenJDK应该是 Java 8、9、10 或 11 之一,撰写本文时,我正在使用 Java 8。从我的角度来看获取最新的 Groovy 和 Grails 的最佳方法是使用 [SDKMAN!][9]。
从未尝试过 Grails 的读者可能需要做一些背景资料阅读。作为初学者,推荐文章 [创建你的第一个 Grails 应用程序][10]。
@ -34,7 +34,7 @@ grails create-domain-class com.nuevaconsulting.embrow.Employeecd embrowgrails cr
这种方式构建的域类没有属性,因此必须按如下方式编辑它们:
Position 域类:
`Position` 域类:
```
package com.nuevaconsulting.embrow
@ -51,7 +51,7 @@ class Position {
}com.Stringint startingstatic constraintsnullableblankstarting nullable
```
Office 域类:
`Office` 域类:
```
package com.nuevaconsulting.embrow
@ -72,7 +72,7 @@ class Office {
}
```
Enployee 域类:
`Enployee` 域类:
```
package com.nuevaconsulting.embrow
@ -98,7 +98,7 @@ class Employee {
}
```
请注意,虽然 Position 和 Office 域类使用了预定义的 Groovy 类型 String 以及 int但 Employee 域类定义了 Position 和 Office 字段(以及预定义的 Date。这会导致创建数据库表其中存储的 Employee 实例中包含了指向存储 Position 和 Office 实例表的引用或者外键。
请注意,虽然 `Position``Office` 域类使用了预定义的 Groovy 类型 `String` 以及 `int`,但 `Employee` 域类定义了 `Position``Office` 字段(以及预定义的 `Date`)。这会导致创建数据库表,其中存储的 `Employee` 实例中包含了指向存储 `Position``Office` 实例表的引用或者外键。
现在你可以生成控制器,视图,以及其他各种测试组件:
@ -108,7 +108,7 @@ grails generate-all com.nuevaconsulting.embrow.Office
grails generate-all com.nuevaconsulting.embrow.Employeegrails generateall com.grails generateall com.grails generateall com.
```
此时,你已经准备好基本的 create-read-update-deleteCRUD应用程序。我在**grails-app/init/com/nuevaconsulting/BootStrap.groovy**中包含了一些基础数据来填充表格。
此时,你已经准备好了一个基本的增删改查CRUD应用程序。我在 `grails-app/init/com/nuevaconsulting/BootStrap.groovy` 中包含了一些基础数据来填充表格。
如果你用如下命令来启动应用程序:
@ -116,43 +116,44 @@ grails generate-all com.nuevaconsulting.embrow.Employeegrails generateall com.gr
grails run-app
```
在浏览器输入**<http://localhost:8080/:>**,你将会看到如下界面:
在浏览器输入 `http://localhost:8080/`,你将会看到如下界面:
![Embrow home screen][12]
Embrow 应用程序主界面。
*Embrow 应用程序主界面。*
单击 OfficeController会跳转到如下界面
单击 OfficeController” 链接,会跳转到如下界面:
![Office list][14]
Office 列表
*Office 列表*
注意,此表由 **OfficeController index** 生成,并由视图 `office/index.gsp` 显示。
注意,此表由 `OfficeController``index` 方式生成,并由视图 `office/index.gsp` 显示。
同样,单击 **EmployeeController** 跳转到如下界面:
同样,单击 “EmployeeController” 链接 跳转到如下界面:
![Employee controller][16]
employee controller
*employee 控制器*
好吧,这很丑陋: Position 和 Office 链接是什么?
上面的命令 `generate-all` 生成的视图创建了一个叫 **index.gsp** 的文件,它使用 Grails <f:table/> 标签,该标签默认会显示类名(**com.nuevaconsulting.embrow.Position**)和持久化示例标识符(**30**)。这个操作可以自定义用来产生更好看的东西,并且自动生成链接,自动生成分页以及自动生成可序列的一些非常简洁直观的东西。
上面的命令 `generate-all` 生成的视图创建了一个叫 `index.gsp` 的文件,它使用 Grails `<f:table/>` 标签,该标签默认会显示类名(`com.nuevaconsulting.embrow.Position`)和持久化示例标识符(`30`)。这个操作可以自定义用来产生更好看的东西,并且自动生成链接,自动生成分页以及自动生成可序列的一些非常简洁直观的东西。
但该员工信息浏览器功能也是有限的。例如,如果想查找 position 信息中包含 “dev” 的员工该怎么办如果要组合排序以姓氏为主排序关键字office 为辅助排序关键字,该怎么办?或者,你需要将已排序的数据导出到电子表格或 PDF 文档以便通过电子邮件发送给无法访问浏览器的人,该怎么办?
但该员工信息浏览器功能也是有限的。例如,如果想查找 position 信息中包含 “dev” 的员工该怎么办?如果要组合排序,以姓氏为主排序关键字,office 为辅助排序关键字,该怎么办?或者,你需要将已排序的数据导出到电子表格或 PDF 文档以便通过电子邮件发送给无法访问浏览器的人,该怎么办?
jQuery DataTables 插件提供了这些所需的功能。允许你创建一个完成的表格数据浏览器。
### 创建员工信息浏览器视图和控制器的方法
要基于 jQuery DataTables 创建员工信息浏览器,你必须先完成以下两个任务:
1. 创建 Grails 视图,其中包含启用 DataTable 所需的 HTML 和 JavaScript
1. 创建 Grails 视图,其中包含启用 DataTable 所需的 HTML 和 JavaScript
2. 给 Grails 控制器增加一个方法来控制新视图。
#### 员工信息浏览器视图
在目录 **embrow/grails-app/views/employee** 中,首先复制 **index.gsp** 文件,重命名为 **browser.gsp**
在目录 `embrow/grails-app/views/employee` 中,首先复制 `index.gsp` 文件,重命名为 `browser.gsp`
```
cd Projects
@ -160,7 +161,7 @@ cd embrow/grails-app/views/employee
cp gsp browser.gsp
```
此刻,你自定义新的 **browser.gsp** 文件来添加相关的 jQuery DataTables 代码。
此刻,你自定义新的 `browser.gsp` 文件来添加相关的 jQuery DataTables 代码。
通常,在可能的时候,我喜欢从内容提供商处获得 JavaScript 和 CSS在下面这行后面
@ -185,7 +186,7 @@ cp gsp browser.gsp
<script type="text/javascript" charset="utf8" src="https://cdn.datatables.net/buttons/1.5.1/js/buttons.print.min.js "></script>
```
然后删除 **index.gsp** 中提供数据分页的代码:
然后删除 `index.gsp` 中提供数据分页的代码:
```
<div id="list-employee" class="content scaffold-list" role="main">
@ -253,7 +254,7 @@ $(this).html('<input type="text" size="15" placeholder="' + title + '?" />');
});titletitletitletitletitle
```
接下来,定义表模型。 这是提供所有表选项的地方,包括界面的滚动,而不是分页,根据 dom 字符串提供的装饰,将数据导出为 CSV 和其他格式的能力,以及建立与服务器的 Ajax 连接。 请注意,使用 Groovy GString 调用 Grails **createLink()** 的方法创建 URL**EmployeeController** 中指向 **browserLister** 操作。同样有趣的是表格列的定义。此信息将发送到后端,后端查询数据库并返回相应的记录。
接下来,定义表模型。这是提供所有表选项的地方,包括界面的滚动,而不是分页,根据 DOM 字符串提供的装饰,将数据导出为 CSV 和其他格式的能力,以及建立与服务器的 AJAX 连接。 请注意,使用 Groovy GString 调用 Grails `createLink()` 的方法创建 URL`EmployeeController` 中指向 `browserLister` 操作。同样有趣的是表格列的定义。此信息将发送到后端,后端查询数据库并返回相应的记录。
```
var table = $('#employee_dt').DataTable( {
@ -302,7 +303,7 @@ that.search(this.value).draw();
![](https://opensource.com/sites/default/files/uploads/screen_4.png)
这是另一个屏幕截图,显示了过滤和多列排序(寻找 position 包括字符 “dev” 的员工,先按 office 排序,然后按姓氏排序):
这是另一个屏幕截图,显示了过滤和多列排序(寻找 position 包括字符 “dev” 的员工,先按 office 排序,然后按姓氏排序):
![](https://opensource.com/sites/default/files/uploads/screen_5.png)
@ -314,37 +315,37 @@ that.search(this.value).draw();
![](https://opensource.com/sites/default/files/uploads/screen7.png)
好的,视图部分看起来非常简单; 因此,控制器必须做所有繁重的工作,对吧? 让我们来看看…
好的,视图部分看起来非常简单因此,控制器必须做所有繁重的工作,对吧? 让我们来看看…
#### 控制器 browserLister 操作
回想一下,我们看到过这个字符串
回想一下,我们看到过这个字符串
```
"${createLink(controller: 'employee', action: 'browserLister')}"
```
对于从 DataTables 模型中调用 Ajax 的 URL是在 Grails 服务器上动态创建 HTML 链接,其 Grails 标记背后通过调用 [createLink()][17] 的方法实现的。这会最终产生一个指向 **EmployeeController** 的链接,位于:
对于从 DataTables 模型中调用 AJAX 的 URL是在 Grails 服务器上动态创建 HTML 链接,其 Grails 标记背后通过调用 [createLink()][17] 的方法实现的。这会最终产生一个指向 `EmployeeController` 的链接,位于:
```
embrow/grails-app/controllers/com/nuevaconsulting/embrow/EmployeeController.groovy
```
特别是控制器方法 **browserLister()**。我在代码中留了一些 print 语句,以便在运行时能够在终端看到中间结果。
特别是控制器方法 `browserLister()`。我在代码中留了一些 `print` 语句,以便在运行时能够在终端看到中间结果。
```
    def browserLister() {
        // Applies filters and sorting to return a list of desired employees
```
首先,打印出传递给 **browserLister()** 的参数。我通常使用此代码开始构建控制器方法,以便我完全清楚我的控制器正在接收什么。
首先,打印出传递给 `browserLister()` 的参数。我通常使用此代码开始构建控制器方法,以便我完全清楚我的控制器正在接收什么。
```
      println "employee browserLister params $params"
        println()
```
接下来处理这些参数以使它们更加有用。首先jQuery DataTables 参数,一个名为 **jqdtParams**的 Groovy 映射:
接下来处理这些参数以使它们更加有用。首先jQuery DataTables 参数,一个名为 `jqdtParams` 的 Groovy 映射:
```
def jqdtParams = [:]
@ -363,7 +364,7 @@ println "employee dataTableParams $jqdtParams"
println()
```
接下来,列数据,一个名为 **columnMap**的 Groovy 映射:
接下来,列数据,一个名为 `columnMap` 的 Groovy 映射:
```
def columnMap = jqdtParams.columns.collectEntries { k, v ->
@ -386,7 +387,7 @@ println "employee columnMap $columnMap"
println()
```
接下来,从 **columnMap** 中检索的所有列表以及在视图中应如何排序这些列表Groovy 列表分别称为 **allColumnList**和 **orderList**
接下来,从 `columnMap` 中检索的所有列表以及在视图中应如何排序这些列表Groovy 列表分别称为 `allColumnList``orderList`
```
def allColumnList = columnMap.keySet() as List
@ -395,7 +396,7 @@ def orderList = jqdtParams.order.collect { k, v -> [allColumnList[v.column as In
println "employee orderList $orderList"
```
我们将使用 Grails 的 Hibernate 标准实现来实际选择要显示的元素以及它们的排序和分页。标准要求过滤器关闭; 在大多数示例中这是作为标准实例本身的创建的一部分给出的但是在这里我们预先定义过滤器闭包。请注意在这种情况下“date hired” 过滤器的相对复杂的解释被视为一年并应用于建立日期范围,并使用 **createAlias** 以允许我们进入相关类别 Position 和 Office
我们将使用 Grails 的 Hibernate 标准实现来实际选择要显示的元素以及它们的排序和分页。标准要求过滤器关闭在大多数示例中这是作为标准实例本身的创建的一部分给出的但是在这里我们预先定义过滤器闭包。请注意在这种情况下“date hired” 过滤器的相对复杂的解释被视为一年并应用于建立日期范围,并使用 `createAlias` 以允许我们进入相关类别 `Position``Office`
```
def filterer = {
@ -424,14 +425,14 @@ def filterer = {
}
```
是时候应用上述内容了。第一步是获取分页代码所需的所有 Employee 实例的总数:
是时候应用上述内容了。第一步是获取分页代码所需的所有 `Employee` 实例的总数:
```
        def recordsTotal = Employee.count()
        println "employee recordsTotal $recordsTotal"
```
接下来,将过滤器应用于 Employee 实例以获取过滤结果的计数,该结果将始终小于或等于总数(同样,这是针对分页代码):
接下来,将过滤器应用于 `Employee` 实例以获取过滤结果的计数,该结果将始终小于或等于总数(同样,这是针对分页代码):
```
        def c = Employee.createCriteria()
@ -467,7 +468,7 @@ def filterer = {
要完全清楚JTable 中的分页代码管理三个计数:数据集中的记录总数,应用过滤器后得到的数字,以及要在页面上显示的数字(显示是滚动还是分页)。 排序应用于所有过滤的记录,并且分页应用于那些过滤的记录的块以用于显示目的。
接下来,处理命令返回的结果,在每行中创建指向 EmployeePosition 和 Office 实例的链接,以便用户可以单击这些链接以获取相关实例的所有详细信息:
接下来,处理命令返回的结果,在每行中创建指向 `Employee`、`Position` 和 `Office` 实例的链接,以便用户可以单击这些链接以获取相关实例的所有详细信息:
```
        def dollarFormatter = new DecimalFormat('$##,###.##')
@ -490,14 +491,15 @@ def filterer = {
}
```
大功告成
大功告成。
如果你熟悉 Grails这可能看起来比你原先想象的要多但这里没有火箭式的一步到位方法只是很多分散的操作步骤。但是如果你没有太多接触 Grails或 Groovy那么需要了解很多新东西 - 闭包,代理和构建器等等。
在那种情况下,从哪里开始? 最好的地方是了解 Groovy 本身,尤其是 [Groovy closures][18] 和 [Groovy delegates and builders][19]。然后再去阅读上面关于 Grails 和 Hibernate 条件查询的建议阅读文章。
### 结语
jQuery DataTables 为 Grails 制作了很棒的表格数据浏览器。对视图进行编码并不是太棘手但DataTables 文档中提供的 PHP 示例提供的功能仅到此位置。特别是,它们不是用 Grails 程序员编写的,也不包含探索使用引用其他类(实质上是查找表)的元素的更精细的细节。
jQuery DataTables 为 Grails 制作了很棒的表格数据浏览器。对视图进行编码并不是太棘手,但 DataTables 文档中提供的 PHP 示例提供的功能仅到此位置。特别是,它们不是用 Grails 程序员编写的,也不包含探索使用引用其他类(实质上是查找表)的元素的更精细的细节。
我使用这种方法制作了几个数据浏览器,允许用户选择要查看和累积记录计数的列,或者只是浏览数据。即使在相对适度的 VPS 上的百万行表中,性能也很好。
@ -512,7 +514,7 @@ via: https://opensource.com/article/18/9/using-grails-jquery-and-datatables
作者:[Chris Hermansen][a]
选题:[lujun9972](https://github.com/lujun9972)
译者:[jrg](https://github.com/jrglinux)
校对:[校对者ID](https://github.com/校对者ID)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
@ -528,11 +530,11 @@ via: https://opensource.com/article/18/9/using-grails-jquery-and-datatables
[9]: http://sdkman.io/
[10]: http://guides.grails.org/creating-your-first-grails-app/guide/index.html
[11]: https://opensource.com/file/410061
[12]: https://opensource.com/sites/default/files/uploads/screen_1.png "Embrow home screen"
[12]: https://opensource.com/sites/default/files/uploads/screen_1.png
[13]: https://opensource.com/file/410066
[14]: https://opensource.com/sites/default/files/uploads/screen_2.png "Office list screenshot"
[14]: https://opensource.com/sites/default/files/uploads/screen_2.png
[15]: https://opensource.com/file/410071
[16]: https://opensource.com/sites/default/files/uploads/screen3.png "Employee controller screenshot"
[16]: https://opensource.com/sites/default/files/uploads/screen3.png
[17]: https://gsp.grails.org/latest/ref/Tags/createLink.html
[18]: http://groovy-lang.org/closures.html
[19]: http://groovy-lang.org/dsls.html