Table of Contents
以下用例展示了哪些工作由应用开发者负责(在图中表示为 controller 角色),哪些工作由框架自动完成(浅蓝色矩形框)。
显示表单并保存对象
此流程涉及两个动作(action)和 2 个服务:
Figure 1. 渲染表单与处理对象的时序图
代码示例:表单 + 保存工作流
def userForm(User user) { (1)
user ?= new User() (2)
UiFormSpecifier f = new UiFormSpecifier() (3)
f.ui user, {
hiddenField user.subsidiary_
hiddenField user.origin_
section "User", {
field user.username_
field user.firstName_
field user.lastName_
ajaxField user.manager_, this.&selectUserM2O as MC
field user.trigram_
field user.password_
}
section "Coords", {
field user.businessUnit_
field user.job_
field user.directPhone_
field user.additionalPhone_
field user.mail_
field user.mainSubsidiary_
field user.allowedSubsidiaries_
}
// [. . .]
formAction this.&saveUser as MC, user.id (4)
}
taackUiService.show new UiBlockSpecifier().ui { (5)
modal {
form "User Form", f, BlockSpec.Width.MAX
}
}
}
@Transactional
@Secured("ROLE_ADMIN") (6)
def saveUser() { (7)
taackSaveService.saveThenRedirectOrRenderErrors(User, this.&listUser) (8)
}
| 1 | 显示表单的动作 |
| 2 | 若对象为 null 则新建对象实例 |
| 3 | 创建表单定义器 |
| 4 | 表单提交按钮,将表单数据发送到 saveUser 动作 |
| 5 | 显示表单 |
| 6 | 为保存动作添加权限保护 |
| 7 | 保存对象的动作 |
| 8 | 调用 taackSaveService,如果对象校验通过,用户将被重定向到 listUsers 动作。 |
显示支持列排序、行内操作及筛选器的表格
只需一个动作即可统一处理分页、筛选和排序:
Figure 2. 在表格上管理动作以处理对象列表的时序图
筛选器与表格代码示例
def index() { (1)
User cu = authenticatedUser as User
UiFilterSpecifier f = buildUserTableFilter cu (2)
UiTableSpecifier t = buildUserTable f (3)
UiBlockSpecifier b = new UiBlockSpecifier().ui { (4)
tableFilter(f, t) {
menuIcon ActionIcon.ADD, this.&userForm as MC (5)
}
}
taackUiService.show(b, buildMenu()) (6)
}
| 1 | 显示对象列表的动作 |
| 2 | 构建筛选器,此处筛选器接收当前登录用户作为参数,以便列出该用户所属团队 |
| 3 | 构建表格 |
| 4 | 构建包含表格和筛选器的块(Block) |
| 5 | 添加创建新用户的操作图标 |
| 6 | 显示该块 |
此处我们特地将筛选器传递给 buildTable 以构建查询,从而防止 筛选器篡改(filter hacking)。
|
显示模态窗口,随后关闭它并刷新当前页面的部分内容
Figure 3. 在表格上管理动作以处理对象列表的时序图
关闭模态窗口并刷新当前页面的代码示例
taackSaveService.saveThenDisplayBlockOrRenderErrors(EngineeringChangeRequest, (1)
new UiBlockSpecifier().ui { (2)
closeModalAndUpdateBlock { (3)
show buildShowProjects(ecr), {
menuIcon
ActionIcon.ADD,
Ecr2Controller.&projectsForm as MC, ecr.id
}
}
})
| 1 | 在模态窗口中触发保存对象的动作后,可以在同一个动作中关闭模态窗口并刷新页面元素 |
| 2 | saveThenDisplayBlockOrRenderErrors 接收一个 UiBlockSpecifier 作为参数 |
| 3 | closeModalAndUpdateBlock 会先关闭最近打开的模态窗口,然后应用页面更新 |
| 4 | 此处,名称包含在 ajaxBlockId 中的块将被更新 |
使用 ajaxBlock 时
待办事项(TODO)
-
局部更新页面
-
显示带有可编辑字段的对象
-
显示图表
-
将表格导出为 CSV
-
将块渲染为 PDF
-
将块渲染到邮件中
-
…