aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRobert Jaros <rjaros@finn.pl>2018-03-07 00:07:07 +0100
committerRobert Jaros <rjaros@finn.pl>2018-03-07 00:07:07 +0100
commitc87e1851919c60d57aeb77809a94f589d537f827 (patch)
tree4c1ba89595d7710711c35829baf149740e0cbf90 /src
parent35a6bc496500d77a9f76fc9806713ed378cfbb68 (diff)
downloadkvision-c87e1851919c60d57aeb77809a94f589d537f827.tar.gz
kvision-c87e1851919c60d57aeb77809a94f589d537f827.tar.bz2
kvision-c87e1851919c60d57aeb77809a94f589d537f827.zip
More type-safe forms implementation.
Diffstat (limited to 'src')
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/form/Form.kt84
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/form/FormPanel.kt91
-rw-r--r--src/test/kotlin/test/pl/treksoft/kvision/form/FormPanelSpec.kt28
-rw-r--r--src/test/kotlin/test/pl/treksoft/kvision/form/FormSpec.kt28
4 files changed, 176 insertions, 55 deletions
diff --git a/src/main/kotlin/pl/treksoft/kvision/form/Form.kt b/src/main/kotlin/pl/treksoft/kvision/form/Form.kt
index e91002e9..1b06156e 100644
--- a/src/main/kotlin/pl/treksoft/kvision/form/Form.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/form/Form.kt
@@ -23,6 +23,7 @@ package pl.treksoft.kvision.form
import kotlin.js.Date
import kotlin.js.Json
+import kotlin.reflect.KProperty1
/**
* Internal data class containing form field parameters.
@@ -48,23 +49,82 @@ class Form<K>(private val panel: FormPanel<K>? = null, private val modelFactory:
internal var validatorMessage: ((Form<K>) -> String?)? = null
internal var validator: ((Form<K>) -> Boolean?)? = null
+ internal fun <C : FormControl> addInternal(
+ key: KProperty1<K, *>, control: C, required: Boolean = false,
+ validatorMessage: ((C) -> String?)? = null,
+ validator: ((C) -> Boolean?)? = null
+ ): Form<K> {
+ this.fields[key.name] = control
+ this.fieldsParams[key.name] = FieldParams(required, validatorMessage, validator)
+ return this
+ }
+
/**
- * Adds a control to the form.
+ * Adds a string control to the form.
* @param key key identifier of the control
- * @param control the form control
+ * @param control the string form control
* @param required determines if the control is required
* @param validatorMessage optional function returning validation message
* @param validator optional validation function
* @return current form
*/
- fun <C : FormControl> add(
- key: String, control: C, required: Boolean = false,
+ fun <C : StringFormControl> add(
+ key: KProperty1<K, String?>, control: C, required: Boolean = false,
validatorMessage: ((C) -> String?)? = null,
validator: ((C) -> Boolean?)? = null
): Form<K> {
- this.fields[key] = control
- this.fieldsParams[key] = FieldParams(required, validatorMessage, validator)
- return this
+ return addInternal(key, control, required, validatorMessage, validator)
+ }
+
+ /**
+ * Adds a boolean control to the form.
+ * @param key key identifier of the control
+ * @param control the boolean form control
+ * @param required determines if the control is required
+ * @param validatorMessage optional function returning validation message
+ * @param validator optional validation function
+ * @return current form
+ */
+ fun <C : BoolFormControl> add(
+ key: KProperty1<K, Boolean?>, control: C, required: Boolean = false,
+ validatorMessage: ((C) -> String?)? = null,
+ validator: ((C) -> Boolean?)? = null
+ ): Form<K> {
+ return addInternal(key, control, required, validatorMessage, validator)
+ }
+
+ /**
+ * Adds a number control to the form.
+ * @param key key identifier of the control
+ * @param control the number form control
+ * @param required determines if the control is required
+ * @param validatorMessage optional function returning validation message
+ * @param validator optional validation function
+ * @return current form
+ */
+ fun <C : NumberFormControl> add(
+ key: KProperty1<K, Number?>, control: C, required: Boolean = false,
+ validatorMessage: ((C) -> String?)? = null,
+ validator: ((C) -> Boolean?)? = null
+ ): Form<K> {
+ return addInternal(key, control, required, validatorMessage, validator)
+ }
+
+ /**
+ * Adds a date control to the form.
+ * @param key key identifier of the control
+ * @param control the date form control
+ * @param required determines if the control is required
+ * @param validatorMessage optional function returning validation message
+ * @param validator optional validation function
+ * @return current form
+ */
+ fun <C : DateFormControl> add(
+ key: KProperty1<K, Date?>, control: C, required: Boolean = false,
+ validatorMessage: ((C) -> String?)? = null,
+ validator: ((C) -> Boolean?)? = null
+ ): Form<K> {
+ return addInternal(key, control, required, validatorMessage, validator)
}
/**
@@ -72,8 +132,8 @@ class Form<K>(private val panel: FormPanel<K>? = null, private val modelFactory:
* @param key key identifier of the control
* @return current form
*/
- fun remove(key: String): Form<K> {
- this.fields.remove(key)
+ fun remove(key: KProperty1<K, *>): Form<K> {
+ this.fields.remove(key.name)
return this
}
@@ -91,8 +151,8 @@ class Form<K>(private val panel: FormPanel<K>? = null, private val modelFactory:
* @param key key identifier of the control
* @return selected control
*/
- fun getControl(key: String): FormControl? {
- return this.fields[key]
+ fun getControl(key: KProperty1<K, *>): FormControl? {
+ return this.fields[key.name]
}
/**
@@ -100,7 +160,7 @@ class Form<K>(private val panel: FormPanel<K>? = null, private val modelFactory:
* @param key key identifier of the control
* @return value of the control
*/
- operator fun get(key: String): Any? {
+ operator fun get(key: KProperty1<K, *>): Any? {
return getControl(key)?.getValue()
}
diff --git a/src/main/kotlin/pl/treksoft/kvision/form/FormPanel.kt b/src/main/kotlin/pl/treksoft/kvision/form/FormPanel.kt
index c13fe9f1..5df2d299 100644
--- a/src/main/kotlin/pl/treksoft/kvision/form/FormPanel.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/form/FormPanel.kt
@@ -29,7 +29,9 @@ import pl.treksoft.kvision.form.check.Radio
import pl.treksoft.kvision.html.TAG
import pl.treksoft.kvision.html.Tag
import pl.treksoft.kvision.panel.SimplePanel
+import kotlin.js.Date
import kotlin.js.Json
+import kotlin.reflect.KProperty1
/**
* Bootstrap form layout options.
@@ -109,17 +111,8 @@ open class FormPanel<K>(
return cl
}
- /**
- * Adds a control to the form panel.
- * @param key key identifier of the control
- * @param control the form control
- * @param required determines if the control is required
- * @param validatorMessage optional function returning validation message
- * @param validator optional validation function
- * @return current form panel
- */
- open fun <C : FormControl> add(
- key: String, control: C, required: Boolean = false,
+ protected fun <C : FormControl> addInternal(
+ key: KProperty1<K, *>, control: C, required: Boolean = false,
validatorMessage: ((C) -> String?)? = null,
validator: ((C) -> Boolean?)? = null
): FormPanel<K> {
@@ -135,16 +128,84 @@ open class FormPanel<K>(
}
}
super.add(control)
- form.add(key, control, required, validatorMessage, validator)
+ form.addInternal(key, control, required, validatorMessage, validator)
return this
}
/**
+ * Adds a string control to the form panel.
+ * @param key key identifier of the control
+ * @param control the string form control
+ * @param required determines if the control is required
+ * @param validatorMessage optional function returning validation message
+ * @param validator optional validation function
+ * @return current form panel
+ */
+ open fun <C : StringFormControl> add(
+ key: KProperty1<K, String?>, control: C, required: Boolean = false,
+ validatorMessage: ((C) -> String?)? = null,
+ validator: ((C) -> Boolean?)? = null
+ ): FormPanel<K> {
+ return addInternal(key, control, required, validatorMessage, validator)
+ }
+
+ /**
+ * Adds a boolean control to the form panel.
+ * @param key key identifier of the control
+ * @param control the boolean form control
+ * @param required determines if the control is required
+ * @param validatorMessage optional function returning validation message
+ * @param validator optional validation function
+ * @return current form panel
+ */
+ open fun <C : BoolFormControl> add(
+ key: KProperty1<K, Boolean?>, control: C, required: Boolean = false,
+ validatorMessage: ((C) -> String?)? = null,
+ validator: ((C) -> Boolean?)? = null
+ ): FormPanel<K> {
+ return addInternal(key, control, required, validatorMessage, validator)
+ }
+
+ /**
+ * Adds a number control to the form panel.
+ * @param key key identifier of the control
+ * @param control the number form control
+ * @param required determines if the control is required
+ * @param validatorMessage optional function returning validation message
+ * @param validator optional validation function
+ * @return current form panel
+ */
+ open fun <C : NumberFormControl> add(
+ key: KProperty1<K, Number?>, control: C, required: Boolean = false,
+ validatorMessage: ((C) -> String?)? = null,
+ validator: ((C) -> Boolean?)? = null
+ ): FormPanel<K> {
+ return addInternal(key, control, required, validatorMessage, validator)
+ }
+
+ /**
+ * Adds a date control to the form panel.
+ * @param key key identifier of the control
+ * @param control the date form control
+ * @param required determines if the control is required
+ * @param validatorMessage optional function returning validation message
+ * @param validator optional validation function
+ * @return current form panel
+ */
+ open fun <C : DateFormControl> add(
+ key: KProperty1<K, Date?>, control: C, required: Boolean = false,
+ validatorMessage: ((C) -> String?)? = null,
+ validator: ((C) -> Boolean?)? = null
+ ): FormPanel<K> {
+ return addInternal(key, control, required, validatorMessage, validator)
+ }
+
+ /**
* Removes a control from the form panel.
* @param key key identifier of the control
* @return current form panel
*/
- open fun remove(key: String): FormPanel<K> {
+ open fun remove(key: KProperty1<K, *>): FormPanel<K> {
form.getControl(key)?.let {
super.remove(it)
}
@@ -164,7 +225,7 @@ open class FormPanel<K>(
* @param key key identifier of the control
* @return selected control
*/
- open fun getControl(key: String): FormControl? {
+ open fun getControl(key: KProperty1<K, *>): FormControl? {
return form.getControl(key)
}
@@ -173,7 +234,7 @@ open class FormPanel<K>(
* @param key key identifier of the control
* @return value of the control
*/
- operator fun get(key: String): Any? {
+ operator fun get(key: KProperty1<K, *>): Any? {
return getControl(key)?.getValue()
}
diff --git a/src/test/kotlin/test/pl/treksoft/kvision/form/FormPanelSpec.kt b/src/test/kotlin/test/pl/treksoft/kvision/form/FormPanelSpec.kt
index 88695366..33b439a5 100644
--- a/src/test/kotlin/test/pl/treksoft/kvision/form/FormPanelSpec.kt
+++ b/src/test/kotlin/test/pl/treksoft/kvision/form/FormPanelSpec.kt
@@ -51,7 +51,7 @@ class FormPanelSpec : SimpleSpec {
val result = formPanel.getData()
assertNull(result.a, "FormPanel should return null without adding any control")
val textField = Text()
- formPanel.add("a", textField)
+ formPanel.add(DataForm::a, textField)
formPanel.setData(data)
val result2 = formPanel.getData()
assertEquals("Test value", result2.a, "FormPanel should return initial value")
@@ -71,9 +71,9 @@ class FormPanelSpec : SimpleSpec {
DataForm(it)
}
val data = DataForm(mapOf("a" to "Test value"))
- formPanel.add("a", Text())
+ formPanel.add(DataForm::a, Text())
formPanel.setData(data)
- formPanel.remove("a")
+ formPanel.remove(DataForm::a)
val result = formPanel.getData()
assertNull(result.a, "FormPanel should return null after removing control")
}
@@ -92,7 +92,7 @@ class FormPanelSpec : SimpleSpec {
DataForm(it)
}
val data = DataForm(mapOf("a" to "Test value"))
- formPanel.add("a", Text())
+ formPanel.add(DataForm::a, Text())
formPanel.setData(data)
formPanel.removeAll()
val result = formPanel.getData()
@@ -112,10 +112,10 @@ class FormPanelSpec : SimpleSpec {
val formPanel = FormPanel {
DataForm(it)
}
- formPanel.add("a", Text())
- val control = formPanel.getControl("b")
+ formPanel.add(DataForm::a, Text())
+ val control = formPanel.getControl(DataForm::b)
assertNull(control, "Should return null when there is no such control")
- val control2 = formPanel.getControl("a")
+ val control2 = formPanel.getControl(DataForm::a)
assertNotNull(control2, "Should return correct control")
}
}
@@ -133,13 +133,13 @@ class FormPanelSpec : SimpleSpec {
DataForm(it)
}
val data = DataForm(mapOf("a" to "Test value"))
- formPanel.add("a", Text())
- val b = formPanel["b"]
+ formPanel.add(DataForm::a, Text())
+ val b = formPanel[DataForm::b]
assertNull(b, "Should return null value when there is no added control")
- val a = formPanel["a"]
+ val a = formPanel[DataForm::a]
assertNull(a, "Should return null value when control is empty")
formPanel.setData(data)
- val a2 = formPanel["a"]
+ val a2 = formPanel[DataForm::a]
assertEquals("Test value", a2, "Should return correct value")
}
}
@@ -158,7 +158,7 @@ class FormPanelSpec : SimpleSpec {
}
val data = DataForm(mapOf("a" to "Test value"))
val textField = Text()
- formPanel.add("a", textField)
+ formPanel.add(DataForm::a, textField)
formPanel.setData(data)
textField.value = "New value"
val result = formPanel.getData()
@@ -177,10 +177,10 @@ class FormPanelSpec : SimpleSpec {
val formPanel = FormPanel {
DataForm(it)
}
- formPanel.add("s", Text()) {
+ formPanel.add(DataForm::s, Text()) {
it.getValue()?.length ?: 0 > 4
}
- formPanel.add("d", DateTime(), required = true)
+ formPanel.add(DataForm::d, DateTime(), required = true)
formPanel.setData(DataForm(mapOf("s" to "123")))
val valid = formPanel.validate()
assertEquals(false, valid, "Should be invalid with initial data")
diff --git a/src/test/kotlin/test/pl/treksoft/kvision/form/FormSpec.kt b/src/test/kotlin/test/pl/treksoft/kvision/form/FormSpec.kt
index 128b96b1..ee3cd2af 100644
--- a/src/test/kotlin/test/pl/treksoft/kvision/form/FormSpec.kt
+++ b/src/test/kotlin/test/pl/treksoft/kvision/form/FormSpec.kt
@@ -51,7 +51,7 @@ class FormSpec : SimpleSpec {
val result = form.getData()
assertNull(result.a, "Form should return null without adding any control")
val textField = Text()
- form.add("a", textField)
+ form.add(DataForm::a, textField)
form.setData(data)
val result2 = form.getData()
assertEquals("Test value", result2.a, "Form should return initial value")
@@ -71,9 +71,9 @@ class FormSpec : SimpleSpec {
DataForm(it)
}
val data = DataForm(mapOf("a" to "Test value"))
- form.add("a", Text())
+ form.add(DataForm::a, Text())
form.setData(data)
- form.remove("a")
+ form.remove(DataForm::a)
val result = form.getData()
assertNull(result.a, "Form should return null after removing control")
}
@@ -92,7 +92,7 @@ class FormSpec : SimpleSpec {
DataForm(it)
}
val data = DataForm(mapOf("a" to "Test value"))
- form.add("a", Text())
+ form.add(DataForm::a, Text())
form.setData(data)
form.removeAll()
val result = form.getData()
@@ -112,10 +112,10 @@ class FormSpec : SimpleSpec {
val form = Form {
DataForm(it)
}
- form.add("a", Text())
- val control = form.getControl("b")
+ form.add(DataForm::a, Text())
+ val control = form.getControl(DataForm::b)
assertNull(control, "Should return null when there is no such control")
- val control2 = form.getControl("a")
+ val control2 = form.getControl(DataForm::a)
assertNotNull(control2, "Should return correct control")
}
}
@@ -133,13 +133,13 @@ class FormSpec : SimpleSpec {
DataForm(it)
}
val data = DataForm(mapOf("a" to "Test value"))
- form.add("a", Text())
- val b = form["b"]
+ form.add(DataForm::a, Text())
+ val b = form[DataForm::b]
assertNull(b, "Should return null value when there is no added control")
- val a = form["a"]
+ val a = form[DataForm::a]
assertNull(a, "Should return null value when control is empty")
form.setData(data)
- val a2 = form["a"]
+ val a2 = form[DataForm::a]
assertEquals("Test value", a2, "Should return correct value")
}
}
@@ -158,7 +158,7 @@ class FormSpec : SimpleSpec {
}
val data = DataForm(mapOf("a" to "Test value"))
val textField = Text()
- form.add("a", textField)
+ form.add(DataForm::a, textField)
form.setData(data)
textField.value = "New value"
val result = form.getData()
@@ -177,10 +177,10 @@ class FormSpec : SimpleSpec {
val form = Form {
DataForm(it)
}
- form.add("s", Text()) {
+ form.add(DataForm::s, Text()) {
it.getValue()?.length ?: 0 > 4
}
- form.add("d", DateTime(), required = true)
+ form.add(DataForm::d, DateTime(), required = true)
form.setData(DataForm(mapOf("s" to "123")))
val valid = form.validate()
assertEquals(false, valid, "Should be invalid with initial data")