aboutsummaryrefslogtreecommitdiff
path: root/src/main/kotlin/pl/treksoft
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/kotlin/pl/treksoft')
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/core/Widget.kt37
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/state/StateBinding.kt25
2 files changed, 62 insertions, 0 deletions
diff --git a/src/main/kotlin/pl/treksoft/kvision/core/Widget.kt b/src/main/kotlin/pl/treksoft/kvision/core/Widget.kt
index a1d37541..2d2fac29 100644
--- a/src/main/kotlin/pl/treksoft/kvision/core/Widget.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/core/Widget.kt
@@ -33,6 +33,7 @@ import pl.treksoft.kvision.KVManager
import pl.treksoft.kvision.i18n.I18n
import pl.treksoft.kvision.i18n.I18n.trans
import pl.treksoft.kvision.panel.Root
+import pl.treksoft.kvision.state.ObservableState
import pl.treksoft.kvision.utils.SnOn
import pl.treksoft.kvision.utils.emptyOn
import pl.treksoft.kvision.utils.hooks
@@ -70,22 +71,27 @@ open class Widget(classes: Set<String> = setOf()) : StyledComponent(), Component
field = value
if (oldField != field) refresh()
}
+
/**
* A title attribute of generated HTML element.
*/
var title: String? by refreshOnUpdate()
+
/**
* An ID attribute of generated HTML element.
*/
var id: String? by refreshOnUpdate()
+
/**
* A role attribute of generated HTML element.
*/
var role: String? by refreshOnUpdate()
+
/**
* A tabindex attribute of generated HTML element.
*/
var tabindex: Int? by refreshOnUpdate()
+
/**
* Determines if the current widget is draggable.
*/
@@ -111,8 +117,18 @@ open class Widget(classes: Set<String> = setOf()) : StyledComponent(), Component
protected var lastLanguage: String? = null
+ /**
+ * A function called after the widget is inserted to the DOM.
+ */
var afterInsertHook: ((VNode) -> Unit)? = null
+ /**
+ * A function called after the widget is removed from the DOM.
+ */
var afterDestroyHook: (() -> Unit)? = null
+ /**
+ * A function called after the widget is disposed.
+ */
+ var afterDisposeHook: (() -> Unit)? = null
protected fun <T> singleRender(block: () -> T): T {
getRoot()?.renderDisabled = true
@@ -758,6 +774,7 @@ open class Widget(classes: Set<String> = setOf()) : StyledComponent(), Component
}
override fun dispose() {
+ afterDisposeHook?.invoke()
}
protected fun <T> refreshOnUpdate(refreshFunction: ((T) -> Unit) = { this.refresh() }): RefreshDelegateProvider<T> =
@@ -797,6 +814,26 @@ open class Widget(classes: Set<String> = setOf()) : StyledComponent(), Component
companion object {
private var counter: Long = 0
+
+ /**
+ * An extension function which binds the widget to the observable state.
+ * Used by [pl.treksoft.kvision.state.bind]
+ */
+ internal fun <S : Any, W : Widget> W.bindState(
+ observableState: ObservableState<S>,
+ factory: (W.(S) -> Unit)
+ ): W {
+ val unsubscribe = observableState.subscribe {
+ this.singleRender {
+ (this as? Container)?.removeAll()
+ this.factory(it)
+ }
+ }
+ this.afterDisposeHook = {
+ unsubscribe()
+ }
+ return this
+ }
}
}
diff --git a/src/main/kotlin/pl/treksoft/kvision/state/StateBinding.kt b/src/main/kotlin/pl/treksoft/kvision/state/StateBinding.kt
index 20cb2d8e..d330f76d 100644
--- a/src/main/kotlin/pl/treksoft/kvision/state/StateBinding.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/state/StateBinding.kt
@@ -5,6 +5,22 @@ package pl.treksoft.kvision.state
import pl.treksoft.kvision.core.Container
import pl.treksoft.kvision.core.Widget
+import pl.treksoft.kvision.core.Widget.Companion.bindState
+
+/**
+ * An extension function which binds the widget to the observable state.
+ *
+ * @param S the state type
+ * @param W the widget type
+ * @param observableState the state
+ * @param factory a function which re-creates the view based on the given state
+ */
+fun <S : Any, W : Widget> W.bind(
+ observableState: ObservableState<S>,
+ factory: (W.(S) -> Unit)
+): W {
+ return this.bindState(observableState, factory)
+}
/**
* A class which binds the given container to the observable state.
@@ -16,6 +32,7 @@ import pl.treksoft.kvision.core.Widget
* @param container the container
* @param factory a function which re-creates the view based on the given state
*/
+@Deprecated("Use bind function instead.")
class StateBinding<S : Any, CONT : Container, CONTENT>(
observableState: ObservableState<S>,
private val container: CONT,
@@ -64,6 +81,11 @@ class StateBinding<S : Any, CONT : Container, CONTENT>(
*
* It takes the same parameters as the constructor of the built component.
*/
+@Suppress("DEPRECATION")
+@Deprecated(
+ "Use bind function instead.",
+ replaceWith = ReplaceWith("bind(observableState, factory)", "pl.treksoft.kvision.state.bind")
+)
fun <S : Any, CONT : Container> CONT.stateBinding(
observableState: ObservableState<S>,
factory: (CONT.(S) -> Unit)
@@ -76,6 +98,8 @@ fun <S : Any, CONT : Container> CONT.stateBinding(
*
* It takes the same parameters as the constructor of the built component.
*/
+@Suppress("DEPRECATION")
+@Deprecated("Use bind function instead.")
fun <S : Any, CONT : Container, CONTENT> CONT.stateUpdate(
observableState: ObservableState<S>,
factory: (CONT.(S) -> CONTENT)
@@ -86,6 +110,7 @@ fun <S : Any, CONT : Container, CONTENT> CONT.stateUpdate(
/**
* A helper class for updateable content.
*/
+@Deprecated("Use bind function instead.")
class Updateable<S : Any, CONTENT>(private val setUpdateState: ((S, CONTENT) -> Unit) -> Unit) {
infix fun updateWith(updateState: (S, CONTENT) -> Unit) {
setUpdateState(updateState)