iT邦幫忙

2021 iThome 鐵人賽

DAY 5
0
Modern Web

使用 Kotlin 快速開發 Web 程式 -- Vaadin系列 第 5

驗證資料/產生測試資料/表格顯示 - day05

儲存前,驗證資料正確性

  • 當使用者輸入資料後需要驗證資料正確性,並提示給使用者。在VoK要做到這點非常的容易。請打開 Student.kt,加上欄位驗證
data class Student(
    override var id: Long? = null,

    @field:NotNull
    @field:Size(min = 2, max = 10)
    var name: String? = null,

    @field:NotNull
    @field:Past
    var birthday: LocalDate? = null,
    var created: Date? = null,

    @field:NotNull
    var gender : Gender? = null,

    @field:NotNull
    @field:DecimalMin(value = "100.0")
    @field:DecimalMax(value = "200.0")
    var height: Double? = null,

    @field:NotNull
    @field:DecimalMin(value = "40.0")
    @field:DecimalMax(value = "150.0")
    var weight: Double? = null,

    var student_id : String? = null
): KEntity<Long>{
    companion object :Dao<Student, Long>(Student::class.java)
}

@Past表示日期需為過去的時間,多半用於生日
*請注意,文字長度不分中英文,若為欄位輸入為中文字請特別留意

  • 接著,儲存資料前驗證資料。請打開 CreateStudentView.kt
            button("Save"){
                onLeftClick {
                    val student = Student()
                    if (binder.validate().isOk && binder.writeBeanIfValid(student)){
                        student.save()
                        StudentView.navigateTo(student.id!!)
                    }
                }
            }

binder.validate() 驗證bean是否正確,若有誤即在 bind 欄位下方出示錯誤原因,isOK方法回傳驗證的 boolan 值

執行結果如下 :
https://ithelp.ithome.com.tw/upload/images/20210920/20138680xNhu2M10DA.png

自訂訊息

上圖中可看到一個很奇怪的訊息 必須大於 or equal to 100.0,一般人不會這麼說話,我們改一下提示訊息,請打開Student.kt,更改身高提示文字

    @field:NotNull
    @field:DecimalMin(value = "100.0", message = "需至少100公分以上")
    @field:DecimalMax(value = "200.0")
    var height: Double? = null,

欄位提示文字

此例中,身高和體重欄位,使用者可能會對單位感到疑惑,到底是公分還是公尺、公斤還是磅,除了可以在身高/體重後面加上文字提示外,以此為例我們直接在欄位上加上提示文字,請打開 CreateStudentView.kt,在欄位上加上 placehoder

            numberField("身高"){
                bind(binder).bind(Student::height)
                placeholder = "公分"
            }
            numberField("體重"){
                bind(binder).bind(Student::weight)
                placeholder = "公斤"
            }

https://ithelp.ithome.com.tw/upload/images/20210920/20138680nIzLaQGV8G.png
這樣就完成了

顯示全部學生資料

  • 新增學生資料後,需要一個能夠顯示所有學生資料的畫面,新增 AllStudentsView.kt
package com.example.vok

import com.github.mvysny.karibudsl.v10.*
import com.github.vokorm.dataloader.dataLoader
import com.vaadin.flow.component.button.Button
import com.vaadin.flow.component.grid.Grid
import com.vaadin.flow.router.AfterNavigationEvent
import com.vaadin.flow.router.AfterNavigationObserver
import com.vaadin.flow.router.Route
import eu.vaadinonkotlin.vaadin10.vokdb.setDataLoader
import java.util.*

@Route("students", layout = MainLayout::class)
class AllStudentsView: KComposite(), AfterNavigationObserver {
    private lateinit var grid: Grid<Student>
    private val root = ui {
        verticalLayout {
            setSizeFull()
            h1("學生資料")
            grid = grid {
                isExpand = true
                setDataLoader(Student.dataLoader)
                addColumnFor(Student::id)
                addColumnFor(Student::name)
                addColumnFor(Student::gender).
                addColumnFor(Student::birthday)
                addColumnFor(Student::height)
                addColumnFor(Student::weight).
            }
        }
    }

    override fun afterNavigation(event: AfterNavigationEvent?) {
        grid.refresh()
    }
}

執行後開啟 http://localhost:8080/students 可顯示所有學生資料。這裡使用 Grid 元件顯示,Grid 支援 paging、lazy-loading,還能夠排序和過濾資料,是個功能強大的元件。

產生測試資料

由於範例使用的 H2 database,重新啟動資料就消失了,確實有點困擾。這裡我們使用 JavaFaker 來產生測試資料。 請在 web/build.gradle.kts 加入依賴

dependencies {
    implementation("com.github.javafaker:javafaker:1.0.2")
}
  • 開啟檔案 AllStucentsView.kt,在 grid 上方加個 button
    button("Generate testing data"){
        onLeftClick {
            val faker = Faker(Locale("zh-TW"))
            (1..20).forEach { i ->
                Student(
                    name = faker.name().fullName(),
                    birthday = LocalDateToDateConverter().convertToPresentation(faker.date().birthday(20, 21), null), 
                    gender = Gender.values().random(),
                    height = faker.number().randomDouble(1, 155, 190),
                    weight = faker.number().randomDouble(1, 45, 80)
                ).save()
            }
            grid.refresh()
        }
    }

第3行,初始化Faker時指定語言,台灣使用之語言代碼為 zh-TW
第4行,產生20筆測試資料
第7行,使用Vaadin提供的方法 LocalDateToDateConverter().convertToPresentation() 做資料型態轉換,將faker 產生的 Date 轉換成 Student 需要的 LocalDate
第8行,性別直接取 Gender enum 隨機值
第9~10行,給予適當區間取小數一位的隨機值
第11行,最後別忘了儲存Student Entity
第13行,待資料產生後,更新grid

資料表格改標題文字

最後,再給資料加上標題。開啟 AllStucentsView.kt,加上setHeader() method chaining,最後會回傳加上標題文字的column。

                addColumnFor(Student::id).setHeader("序號")
                addColumnFor(Student::name).setHeader("姓名")
                addColumnFor(Student::gender).setHeader("性別")
                addColumnFor(Student::birthday).setHeader("生日")
                addColumnFor(Student::height).setHeader("身高")
                addColumnFor(Student::weight).setHeader("體重")

執行結果

執行結果如下。畫面中可看到標題旁有上下三角圖符號,點選符號可用該列資料排序。下圖採身高由高而低排序:
https://ithelp.ithome.com.tw/upload/images/20210920/20138680DNqD2djuVM.png

本日範例程式已上傳 Github


上一篇
開始寫CRUD的 C 吧! - day04
下一篇
CRUD的UD / ICON / confirmDialog - day06
系列文
使用 Kotlin 快速開發 Web 程式 -- Vaadin30

尚未有邦友留言

立即登入留言