diff options
Diffstat (limited to 'src/main/kotlin/pl/treksoft')
-rw-r--r-- | src/main/kotlin/pl/treksoft/kvision/core/Widget.kt | 37 | ||||
-rw-r--r-- | src/main/kotlin/pl/treksoft/kvision/state/StateBinding.kt | 25 |
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) |