Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 68 additions & 0 deletions samples/KaraDemo/src/kara/demo/routes/forms/FormsDemo.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package kara.demo.routes.forms

import kara.Get
import kara.Request
import kara.Post
import kara.TextResult
import kara.forms.*
import kara.demo.views

enum class Gender { MAIL FEMAIL }

data class Address(
var city: String? = null,
var street: String? = null
)

data class User(
var firstName: String? = null,
var lastName: String? = null,
var age: Int? = null,
var gender: Gender? = null,
var addr: Address? = null,
var registered: Boolean? = null
)

object FormsDemo {
val UserForm = Form(
mapping(
User::firstName mapTo notEmptyText,
User::lastName mapTo notEmptyText,
User::age mapTo number(min = 18).verifying("21 is restricted age") { it != 21 },
User::gender mapTo enum<Gender>(),
User::registered mapTo boolean,
User::addr toNested mapping (
Address::city mapTo text(min = 5),
Address::street mapTo text(min = 5, max = 10).verifying("Wrong format") {
it!!.endsWith("st.")
}
) { Address() }
.verifying("Street address must be prefixed by city") { it.street!!.startsWith(it.city!!) }
) { User() }
.verifying("first name and last name MUST be different") {
it.firstName != it.lastName
}
)

Get("/user")
class UserFormAction : Request({
val form = UserForm fill User(firstName = "John", age = 21)

views.ShowDemoForm(form)
})

Get("/user/done")
class UserSaveCompleteAction : Request({
TextResult("The user has been saved successfully")
})

Post("/user")
class SaveUserAction : Request({
val form = UserForm bind params._map

when {
form.hasErrors -> views.ShowDemoForm(form)
else -> redirect(UserSaveCompleteAction())
}
})
}
115 changes: 115 additions & 0 deletions samples/KaraDemo/src/kara/demo/views/FormsDemo.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package kara.demo.views

import kara.HtmlTemplateView
import kara.Template
import kotlin.html.*
import kara.forms.Form
import kara.forms.FormField
import kara.demo.routes.forms.User
import kara.demo.routes.forms.FormsDemo
import kara.demo.routes.forms.Address
import kara.demo.routes.forms.Gender

fun ShowDemoForm(form: Form<User>) = HtmlTemplateView(FormTemplate(form), {})

private fun FORM.inputTmpl<T>(field: FormField<T>, label: String, input: HtmlBodyTag.() -> Unit) {
div {
style = "margin: 10px;"

label {
+label

input()
}

if (field.hasErrors()) {
ul {
field.errors.forEach {
li {
+it.message
}
}
}
}
}
}

private fun FORM.inputText<T>(field: FormField<T>, label: String) = inputTmpl(field, label) {
input {
inputType = InputType.text
name = field.fieldName
value = field.value.orEmpty()
}
}

private fun FORM.checkbox(field: FormField<Boolean?>, label: String) = inputTmpl(field, label) {
input {
inputType = InputType.checkbox
name = field.fieldName
value = field.value.orEmpty()

if (field.value != null)
checked = true
}
}

private fun FORM.radio<T: Enum<T>>(field: FormField<T>, values: Array<T>, label: String) = inputTmpl(field, label) {
values.forEach {(radioValue) ->
label {
input {
inputType = InputType.radio
name = field.fieldName
value = radioValue.toString()

if (radioValue.name() == field.value)
checked = true
}
+radioValue.name()
}
}
}

private class FormTemplate(val form: Form<User>) : Template<HTML>() {
override fun HTML.render() {
head {
title {
+"Kara forms binding demo"
}
}

body {
if (form.hasGlobalErrors) {
ul {
form.globalErrors.forEach {
li {
+it.message
}
}
}
}

form {
action = FormsDemo.SaveUserAction()
method = FormMethod.post

inputText(form[User::firstName], "First Name: ")
inputText(form[User::lastName], "Last Name: ")

inputText(form[User::age], "Age: ")

inputText(form[User::addr][Address::city], "City: ")
inputText(form[User::addr][Address::street], "Street: ")

radio(form[User::gender], Gender.values(), "Gender: ")

checkbox(form[User::registered], "Registered: ")

br()

input {
inputType = InputType.submit
}
}
}
}
}
2 changes: 1 addition & 1 deletion src/HTMLBuilder/src/kotlin/html/CssDSL.kt
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ open class CssElement() {
return UnionSelector(selectors)
}

class UnionSelector(val selectors: Array<Selector>) : Selector {
class UnionSelector(val selectors: Array<out Selector>) : Selector {
override fun toExternalForm(): String {
return "(${selectors.map ({ it.toExternalForm() }).makeString(",")})"
}
Expand Down
Loading