各位发现了吗?在写完CRUD後,打开CreateStudentView.kt
和EditStudent.kt
两相对照,新增和编缉的画面几乎一样,能不能共用程序码?怎麽共用?可不可以写成日後可重复使用的组件?
StudentEditorComponent.kt
,将EditStudent.kt
复制进来後,给student
一个set()
方法,让这个component可设定student属性package com.example.vok
import com.github.mvysny.karibudsl.v10.*
import com.vaadin.flow.component.HasComponents
class StudentEditorComponent: KComposite() {
private val binder = beanValidationBinder<Student>()
var student: Student? = null
set(value) {
field = value
value?.let { binder.readBean(value) }
}
private val root = ui {
verticalLayout {
isMargin = false
textField("姓名 : "){
bind(binder).bind(Student::name)
}
comboBox<Gender>("性别 : "){
setItems(*Gender.values())
bind(binder).bind(Student::gender)
}
datePicker("生日 : "){
bind(binder).bind(Student::birthday)
}
numberField("身高"){
bind(binder).bind(Student::height)
}
numberField("体重"){
bind(binder).bind(Student::weight)
}
button("储存"){
onLeftClick {
val student = student!!
if (binder.validate().isOk && binder.writeBeanIfValid(student)){
student.save()
StudentView.navigateTo(student.id!!)
}
}
}
routerLink(null, "返回", AllStudentsView::class)
}
}
}
fun HasComponents.studentEditorComponent(block: StudentEditorComponent.()->Unit = {}) = init(StudentEditorComponent(), block)
最後一行,HasComponents.studentEditorComponent()
Extension function,参数为要加入组件的程序码区段,再将组件回传。
CreateStudentView.kt
,移除重复的程序码,由於此画面是新增学生资料,所以指定 student 属性为 Student(),改好後程序如下 :class CreateStudentView: KComposite() {
private lateinit var editorComponent: StudentEditorComponent
private val root = ui {
verticalLayout {
h1("新增学生资料")
editorComponent = studentEditorComponent {
student = Student()
}
}
}
}
看起来是不是变得很简洁?
EditStudent.kt
,这里也一样移除重复的程序码後加上StudentEditorComponent private lateinit var studentEditorComponent: StudentEditorComponent
private val root = ui {
verticalLayout {
h1("学生资料修改")
studentEditorComponent = studentEditorComponent()
}
}
override fun setParameter(event: BeforeEvent?, studentId: Long?) {
studentEditorComponent.student = Student.getById(studentId!!)
}
这段原本重新取读 bean 让 grid 自动更新的程序码,改为设定组件的student属性值。
执行後的结果和原本一样一样,画面组件化後程序码不但可读性更高,且组件和原本程序码脱勾相互不受影响。
我们先来看看,如果今天想要在grid里使用带clicklistener的图型按键需要做哪些事。开启AllStudentsView.kt
addColumn(ComponentRenderer<Button, Student>{ student: Student ->
val button = Button(VaadinIcon.EYE.create())
button.addThemeVariants(ButtonVariant.LUMO_ICON, ButtonVariant.LUMO_TERTIARY, ButtonVariant.LUMO_SMALL)
button.onLeftClick { StudentView.navigateTo(student.id!!)}
button
}).setWidth("50px").isExpand = false
加上三个带事件的 button column 後,就会变成这样
addColumn(ComponentRenderer<Button, Student>{ student: Student ->
val button = Button(VaadinIcon.EYE.create())
button.addThemeVariants(ButtonVariant.LUMO_ICON, ButtonVariant.LUMO_TERTIARY, ButtonVariant.LUMO_SMALL)
button.onLeftClick { StudentView.navigateTo(student.id!!)}
button
}).setWidth("50px").isExpand = false
addColumn(ComponentRenderer<Button, Student>{ student: Student ->
val button = Button(VaadinIcon.EDIT.create())
button.addThemeVariants(ButtonVariant.LUMO_ICON, ButtonVariant.LUMO_TERTIARY, ButtonVariant.LUMO_SMALL)
button.onLeftClick { EditStudent.navigateTo(student.id!!)}
button
}).setWidth("50px").isExpand = false
addColumn(ComponentRenderer<Button, Student>{ student: Student ->
val button = Button(VaadinIcon.TRASH.create())
button.addThemeVariants(ButtonVariant.LUMO_ICON, ButtonVariant.LUMO_TERTIARY, ButtonVariant.LUMO_SMALL)
button.onLeftClick {
confirmDialog(text = "是否确定删除${student.name}的资料?") {
student.delete()
this.refresh()
}}
button
}).setWidth("50px").isExpand = false
程序码看起来不仅兀长且不易阅读。如果 Grid 能够直接提供一个方法,只要传进icon、column key、clickListener三个参数,就能回给我一个带有listener的图形按键,好像还不错。
fun <T> Grid<T>.addButtonColumn(icon: IconFactory, key: String, clickListener: (T) -> Unit): Grid.Column<T> {
val renderer = ComponentRenderer<Button, T> { data: T ->
val button = Button(icon.create())
button.addThemeVariants(ButtonVariant.LUMO_ICON, ButtonVariant.LUMO_TERTIARY, ButtonVariant.LUMO_SMALL)
button.onLeftClick { clickListener(data) }
button
}
val column: Grid.Column<T> = addColumn(renderer).setKey(key).setWidth("50px")
column.isExpand = false
return column
}
grid{} 加上图形按键 column 的程序码改为
addButtonColumn(VaadinIcon.EYE, "view") { StudentView.navigateTo(it.id!!) }
addButtonColumn(VaadinIcon.EDIT, "edit") { EditStudent.navigateTo(it.id!!) }
addButtonColumn(VaadinIcon.TRASH, "delete"){
confirmDialog(text = "是否确定删除${it.name}的资料?") {
it.delete()
this.refresh()
}
}
执行结果如下:
经过Refactor後,整个程序是不是看起来既乾净又简捷?
明天开始进入第二张资料表,就要讲到资料库关联罗~
本日程序已上传 GitHub
本篇大纲:selection.call( )、drag.on( )、范例 今天要来看另一个d3有趣...
=x= 🌵 建立 News Manager - Content Page 後台页面 。 News M...
今天是要来填之前未补之坑, 那就是建立 VPN 连线, 以小公司来说, 其实能够快速加快产品上市比较...
本系列文章同步发布於笔者网站 上篇介绍了 Open vSwitch with Provider Ne...
由於 Mautic 是一个自动化行销利器,那麽寄发电子邮件便是一个必须的功能。不过在开发时一再的利用...