From 7550bcabe74c6adfef702bc9dbb4ed5f0bb178d6 Mon Sep 17 00:00:00 2001 From: Robert Jaros Date: Sat, 11 May 2019 03:15:12 +0200 Subject: Support for custom sorters, editors and validators in the Tabulator component. Support for KVision components in custom formatters and editors. --- .../pl/treksoft/kvision/tabulator/Options.kt | 103 ++++++++++++++++++++- 1 file changed, 98 insertions(+), 5 deletions(-) (limited to 'kvision-modules/kvision-tabulator/src/main/kotlin/pl/treksoft') diff --git a/kvision-modules/kvision-tabulator/src/main/kotlin/pl/treksoft/kvision/tabulator/Options.kt b/kvision-modules/kvision-tabulator/src/main/kotlin/pl/treksoft/kvision/tabulator/Options.kt index dac29ab9..055cd88d 100644 --- a/kvision-modules/kvision-tabulator/src/main/kotlin/pl/treksoft/kvision/tabulator/Options.kt +++ b/kvision-modules/kvision-tabulator/src/main/kotlin/pl/treksoft/kvision/tabulator/Options.kt @@ -22,8 +22,17 @@ package pl.treksoft.kvision.tabulator +import org.w3c.dom.HTMLElement +import pl.treksoft.kvision.core.Component +import pl.treksoft.kvision.form.FormControl +import pl.treksoft.kvision.form.FormInput +import pl.treksoft.kvision.panel.Root +import pl.treksoft.kvision.tabulator.EditorRoot.disposeTimer +import pl.treksoft.kvision.tabulator.EditorRoot.root import pl.treksoft.kvision.tabulator.js.Tabulator import pl.treksoft.kvision.utils.obj +import kotlin.browser.document +import kotlin.browser.window import kotlin.js.Promise /** @@ -265,6 +274,10 @@ data class ColumnDefinition( val rowHandle: Boolean? = null, val hideInHtml: Boolean? = null, val sorter: Sorter? = null, + val sorterFunction: (( + a: dynamic, b: dynamic, aRow: Tabulator.RowComponent, bRow: Tabulator.RowComponent, + column: Tabulator.ColumnComponent, dir: SortingDir, sorterParams: dynamic + ) -> Number)? = null, val sorterParams: dynamic = null, val formatter: Formatter? = null, val formatterFunction: (( @@ -275,8 +288,14 @@ data class ColumnDefinition( val variableHeight: Boolean? = null, val editable: ((cell: Tabulator.CellComponent) -> Boolean)? = null, val editor: Editor? = null, + val editorFunction: (( + cell: Tabulator.CellComponent, + onRendered: (callback: () -> Unit) -> Unit, + success: (value: dynamic) -> Unit, cancel: (value: dynamic) -> Unit, editorParams: dynamic + ) -> dynamic)? = null, val editorParams: dynamic = null, val validator: Validator? = null, + val validatorFunction: dynamic = null, val validatorParams: String? = null, val download: Boolean? = null, val downloadTitle: String? = null, @@ -325,11 +344,77 @@ data class ColumnDefinition( val cellEditCancelled: ((cell: Tabulator.CellComponent) -> Unit)? = null ) +internal object EditorRoot { + internal var root: Root? = null + internal var disposeTimer: Int? = null +} + /** * An extension function to convert column definition class to JS object. */ -@Suppress("UNCHECKED_CAST_TO_EXTERNAL_INTERFACE", "ComplexMethod") +@Suppress("UNCHECKED_CAST_TO_EXTERNAL_INTERFACE", "ComplexMethod", "MagicNumber") fun ColumnDefinition.toJs(i18nTranslator: (String) -> (String)): Tabulator.ColumnDefinition { + val tmpEditorFunction = editorFunction?.let { + { cell: Tabulator.CellComponent, + onRendered: (callback: () -> Unit) -> Unit, + success: (value: dynamic) -> Unit, cancel: (value: dynamic) -> Unit, editorParams: dynamic -> + var onRenderedCallback: (() -> Unit)? = null + val component = it(cell, { callback -> + onRenderedCallback = callback + }, { value -> + success(value) + disposeTimer = window.setTimeout({ + root?.dispose() + disposeTimer = null + root = null + }, 500) + }, cancel, editorParams) + if (component is Component) { + val rootElement = document.createElement("div") as HTMLElement + onRendered { + if (root != null) { + disposeTimer?.let { window.clearTimeout(it) } + root?.dispose() + } + root = Root(element = rootElement) + @Suppress("UnsafeCastFromDynamic") + root?.add(component) + (component as? FormControl)?.focus() + (component as? FormInput)?.focus() + cell.checkHeight() + onRenderedCallback?.invoke() + } + rootElement + } else { + component + } + } + } + + val tmpFormatterFunction = formatterFunction?.let { + { cell: Tabulator.CellComponent, formatterParams: dynamic, + onRendered: (callback: () -> Unit) -> Unit -> + var onRenderedCallback: (() -> Unit)? = null + val component = it(cell, formatterParams) { callback -> + onRenderedCallback = callback + } + if (component is Component) { + val rootElement = document.createElement("div") as HTMLElement + onRendered { + val root = Root(element = rootElement) + console.log("root created") + @Suppress("UnsafeCastFromDynamic") + root.add(component) + cell.checkHeight() + onRenderedCallback?.invoke() + } + rootElement + } else { + component + } + } + } + return obj { this.title = i18nTranslator(title) if (field != null) this.field = field @@ -346,17 +431,25 @@ fun ColumnDefinition.toJs(i18nTranslator: (String) -> (String)): Tabulator.Colum if (cssClass != null) this.cssClass = cssClass if (rowHandle != null) this.rowHandle = rowHandle if (hideInHtml != null) this.hideInHtml = hideInHtml - if (sorter != null) this.sorter = sorter.sorter + if (sorterFunction != null) { + this.sorter = sorterFunction + } else if (sorter != null) { + this.sorter = sorter.sorter + } if (sorterParams != null) this.sorterParams = sorterParams - if (formatterFunction != null) { - this.formatter = formatterFunction + if (tmpFormatterFunction != null) { + this.formatter = tmpFormatterFunction } else if (formatter != null) { this.formatter = formatter.formatter } if (formatterParams != null) this.formatterParams = formatterParams if (variableHeight != null) this.variableHeight = variableHeight if (editable != null) this.editable = editable - if (editor != null) this.editor = editor.editor + if (tmpEditorFunction != null) { + this.editor = tmpEditorFunction + } else if (editor != null) { + this.editor = editor.editor + } if (editorParams != null) this.editorParams = editorParams if (validator != null) this.validator = validator.validator if (validatorParams != null) this.validatorParams = validatorParams -- cgit From 0f854be2619161f997b98aa9ad18459008b93afe Mon Sep 17 00:00:00 2001 From: Robert Jaros Date: Sat, 11 May 2019 03:21:21 +0200 Subject: Remove forgotten debug info from code. --- .../src/main/kotlin/pl/treksoft/kvision/tabulator/Options.kt | 1 - 1 file changed, 1 deletion(-) (limited to 'kvision-modules/kvision-tabulator/src/main/kotlin/pl/treksoft') diff --git a/kvision-modules/kvision-tabulator/src/main/kotlin/pl/treksoft/kvision/tabulator/Options.kt b/kvision-modules/kvision-tabulator/src/main/kotlin/pl/treksoft/kvision/tabulator/Options.kt index 055cd88d..3c2675cc 100644 --- a/kvision-modules/kvision-tabulator/src/main/kotlin/pl/treksoft/kvision/tabulator/Options.kt +++ b/kvision-modules/kvision-tabulator/src/main/kotlin/pl/treksoft/kvision/tabulator/Options.kt @@ -402,7 +402,6 @@ fun ColumnDefinition.toJs(i18nTranslator: (String) -> (String)): Tabulator.Colum val rootElement = document.createElement("div") as HTMLElement onRendered { val root = Root(element = rootElement) - console.log("root created") @Suppress("UnsafeCastFromDynamic") root.add(component) cell.checkHeight() -- cgit From 5902d5c3f24e1cd6ca241e3b9589545480eea373 Mon Sep 17 00:00:00 2001 From: Robert Jaros Date: Sat, 11 May 2019 22:03:02 +0200 Subject: Type safety for custom editors and formatters based on KVision components. --- .../pl/treksoft/kvision/tabulator/Options.kt | 111 +++++++++++++-------- .../pl/treksoft/kvision/tabulator/Tabulator.kt | 18 ++-- 2 files changed, 77 insertions(+), 52 deletions(-) (limited to 'kvision-modules/kvision-tabulator/src/main/kotlin/pl/treksoft') diff --git a/kvision-modules/kvision-tabulator/src/main/kotlin/pl/treksoft/kvision/tabulator/Options.kt b/kvision-modules/kvision-tabulator/src/main/kotlin/pl/treksoft/kvision/tabulator/Options.kt index 3c2675cc..dd3bff5f 100644 --- a/kvision-modules/kvision-tabulator/src/main/kotlin/pl/treksoft/kvision/tabulator/Options.kt +++ b/kvision-modules/kvision-tabulator/src/main/kotlin/pl/treksoft/kvision/tabulator/Options.kt @@ -22,6 +22,7 @@ package pl.treksoft.kvision.tabulator +import kotlinx.serialization.KSerializer import org.w3c.dom.HTMLElement import pl.treksoft.kvision.core.Component import pl.treksoft.kvision.form.FormControl @@ -30,6 +31,7 @@ import pl.treksoft.kvision.panel.Root import pl.treksoft.kvision.tabulator.EditorRoot.disposeTimer import pl.treksoft.kvision.tabulator.EditorRoot.root import pl.treksoft.kvision.tabulator.js.Tabulator +import pl.treksoft.kvision.utils.JSON import pl.treksoft.kvision.utils.obj import kotlin.browser.document import kotlin.browser.window @@ -257,7 +259,7 @@ fun DownloadConfig.toJs(): Tabulator.DownloadConfig { /** * Column definition options. */ -data class ColumnDefinition( +data class ColumnDefinition( val title: String, val field: String? = null, val visible: Boolean? = null, @@ -284,6 +286,9 @@ data class ColumnDefinition( cell: Tabulator.CellComponent, formatterParams: dynamic, onRendered: (callback: () -> Unit) -> Unit ) -> dynamic)? = null, + val formatterComponentFunction: (( + cell: Tabulator.CellComponent, onRendered: (callback: () -> Unit) -> Unit, data: T + ) -> Component)? = null, val formatterParams: dynamic = null, val variableHeight: Boolean? = null, val editable: ((cell: Tabulator.CellComponent) -> Boolean)? = null, @@ -293,6 +298,11 @@ data class ColumnDefinition( onRendered: (callback: () -> Unit) -> Unit, success: (value: dynamic) -> Unit, cancel: (value: dynamic) -> Unit, editorParams: dynamic ) -> dynamic)? = null, + val editorComponentFunction: (( + cell: Tabulator.CellComponent, + onRendered: (callback: () -> Unit) -> Unit, + success: (value: dynamic) -> Unit, cancel: (value: dynamic) -> Unit, data: T + ) -> Component)? = null, val editorParams: dynamic = null, val validator: Validator? = null, val validatorFunction: dynamic = null, @@ -353,12 +363,19 @@ internal object EditorRoot { * An extension function to convert column definition class to JS object. */ @Suppress("UNCHECKED_CAST_TO_EXTERNAL_INTERFACE", "ComplexMethod", "MagicNumber") -fun ColumnDefinition.toJs(i18nTranslator: (String) -> (String)): Tabulator.ColumnDefinition { - val tmpEditorFunction = editorFunction?.let { +fun ColumnDefinition.toJs( + i18nTranslator: (String) -> (String), + dataSerializer: KSerializer? = null +): Tabulator.ColumnDefinition { + val tmpEditorFunction = editorComponentFunction?.let { { cell: Tabulator.CellComponent, onRendered: (callback: () -> Unit) -> Unit, - success: (value: dynamic) -> Unit, cancel: (value: dynamic) -> Unit, editorParams: dynamic -> + success: (value: dynamic) -> Unit, cancel: (value: dynamic) -> Unit, _: dynamic -> var onRenderedCallback: (() -> Unit)? = null + val str = kotlin.js.JSON.stringify(cell.getData()) + @Suppress("UNCHECKED_CAST") val data = dataSerializer?.let { + JSON.plain.parse(it, str) + } ?: cell.getData() as T val component = it(cell, { callback -> onRenderedCallback = callback }, { value -> @@ -368,49 +385,44 @@ fun ColumnDefinition.toJs(i18nTranslator: (String) -> (String)): Tabulator.Colum disposeTimer = null root = null }, 500) - }, cancel, editorParams) - if (component is Component) { - val rootElement = document.createElement("div") as HTMLElement - onRendered { - if (root != null) { - disposeTimer?.let { window.clearTimeout(it) } - root?.dispose() - } - root = Root(element = rootElement) - @Suppress("UnsafeCastFromDynamic") - root?.add(component) - (component as? FormControl)?.focus() - (component as? FormInput)?.focus() - cell.checkHeight() - onRenderedCallback?.invoke() + }, cancel, data) + val rootElement = document.createElement("div") as HTMLElement + onRendered { + if (root != null) { + disposeTimer?.let { window.clearTimeout(it) } + root?.dispose() } - rootElement - } else { - component + root = Root(element = rootElement) + @Suppress("UnsafeCastFromDynamic") + root?.add(component) + (component as? FormControl)?.focus() + (component as? FormInput)?.focus() + cell.checkHeight() + onRenderedCallback?.invoke() } + rootElement } } - val tmpFormatterFunction = formatterFunction?.let { - { cell: Tabulator.CellComponent, formatterParams: dynamic, + val tmpFormatterFunction = formatterComponentFunction?.let { + { cell: Tabulator.CellComponent, _: dynamic, onRendered: (callback: () -> Unit) -> Unit -> var onRenderedCallback: (() -> Unit)? = null - val component = it(cell, formatterParams) { callback -> + val str = kotlin.js.JSON.stringify(cell.getData()) + @Suppress("UNCHECKED_CAST") val data = + dataSerializer?.let { JSON.plain.parse(it, str) } ?: cell.getData() as T + val component = it(cell, { callback -> onRenderedCallback = callback + }, data) + val rootElement = document.createElement("div") as HTMLElement + onRendered { + val root = Root(element = rootElement) + @Suppress("UnsafeCastFromDynamic") + root.add(component) + cell.checkHeight() + onRenderedCallback?.invoke() } - if (component is Component) { - val rootElement = document.createElement("div") as HTMLElement - onRendered { - val root = Root(element = rootElement) - @Suppress("UnsafeCastFromDynamic") - root.add(component) - cell.checkHeight() - onRenderedCallback?.invoke() - } - rootElement - } else { - component - } + rootElement } } @@ -438,6 +450,8 @@ fun ColumnDefinition.toJs(i18nTranslator: (String) -> (String)): Tabulator.Colum if (sorterParams != null) this.sorterParams = sorterParams if (tmpFormatterFunction != null) { this.formatter = tmpFormatterFunction + } else if (formatterFunction != null) { + this.formatter = formatterFunction } else if (formatter != null) { this.formatter = formatter.formatter } @@ -446,6 +460,8 @@ fun ColumnDefinition.toJs(i18nTranslator: (String) -> (String)): Tabulator.Colum if (editable != null) this.editable = editable if (tmpEditorFunction != null) { this.editor = tmpEditorFunction + } else if (editorFunction != null) { + this.editor = editorFunction } else if (editor != null) { this.editor = editor.editor } @@ -496,14 +512,20 @@ fun ColumnDefinition.toJs(i18nTranslator: (String) -> (String)): Tabulator.Colum if (cellMouseMove != null) this.cellMouseMove = cellMouseMove if (cellEditing != null) this.cellEditing = cellEditing if (cellEdited != null) this.cellEdited = cellEdited - if (cellEditCancelled != null) this.cellEditCancelled = cellEditCancelled + if (cellEditCancelled != null) { + this.cellEditCancelled = cellEditCancelled + } else if (tmpEditorFunction != null) { + this.cellEditCancelled = { cell: Tabulator.CellComponent -> + cell.checkHeight() + } + } } as Tabulator.ColumnDefinition } /** * Tabulator options. */ -data class TabulatorOptions( +data class TabulatorOptions( val height: String? = null, val virtualDom: Boolean? = null, val virtualDomBuffer: Int? = null, @@ -517,7 +539,7 @@ data class TabulatorOptions( val downloadConfig: DownloadConfig? = null, val reactiveData: Boolean? = null, val autoResize: Boolean? = null, - val columns: List? = null, + val columns: List>? = null, val autoColumns: Boolean? = null, val layout: Layout? = null, val layoutColumnsOnNewData: Boolean? = null, @@ -664,7 +686,10 @@ data class TabulatorOptions( * An extension function to convert tabulator options class to JS object. */ @Suppress("UNCHECKED_CAST_TO_EXTERNAL_INTERFACE", "ComplexMethod") -fun TabulatorOptions.toJs(i18nTranslator: (String) -> (String)): Tabulator.Options { +fun TabulatorOptions.toJs( + i18nTranslator: (String) -> (String), + dataSerializer: KSerializer? = null +): Tabulator.Options { return obj { if (height != null) this.height = height if (virtualDom != null) this.virtualDom = virtualDom @@ -679,7 +704,7 @@ fun TabulatorOptions.toJs(i18nTranslator: (String) -> (String)): Tabulator.Optio if (downloadConfig != null) this.downloadConfig = downloadConfig.toJs() if (reactiveData != null) this.reactiveData = reactiveData if (autoResize != null) this.autoResize = autoResize - if (columns != null) this.columns = columns.map { it.toJs(i18nTranslator) }.toTypedArray() + if (columns != null) this.columns = columns.map { it.toJs(i18nTranslator, dataSerializer) }.toTypedArray() if (autoColumns != null) { this.autoColumns = autoColumns } else if (columns == null) { diff --git a/kvision-modules/kvision-tabulator/src/main/kotlin/pl/treksoft/kvision/tabulator/Tabulator.kt b/kvision-modules/kvision-tabulator/src/main/kotlin/pl/treksoft/kvision/tabulator/Tabulator.kt index 249c578f..6c7480fc 100644 --- a/kvision-modules/kvision-tabulator/src/main/kotlin/pl/treksoft/kvision/tabulator/Tabulator.kt +++ b/kvision-modules/kvision-tabulator/src/main/kotlin/pl/treksoft/kvision/tabulator/Tabulator.kt @@ -54,7 +54,7 @@ import pl.treksoft.kvision.tabulator.js.Tabulator as JsTabulator @Suppress("LargeClass", "TooManyFunctions") open class Tabulator( protected val data: List? = null, - val options: TabulatorOptions = TabulatorOptions(), + val options: TabulatorOptions = TabulatorOptions(), types: Set = setOf(), classes: Set = setOf(), protected val dataSerializer: KSerializer? = null @@ -228,7 +228,7 @@ open class Tabulator( (this.getElement() as? HTMLElement)?.let { jsTabulator = KVManagerTabulator.getConstructor() - .createInstance(it, options.toJs(this::translate)) + .createInstance(it, options.toJs(this::translate, dataSerializer)) if (currentPage != null) { jsTabulator?.setPageSize(pageSize ?: 0) jsTabulator?.setPage(currentPage) @@ -561,7 +561,7 @@ open class Tabulator( */ inline fun Container.tabulator( data: List? = null, - options: TabulatorOptions = TabulatorOptions(), + options: TabulatorOptions = TabulatorOptions(), types: Set = setOf(), classes: Set = setOf(), noinline init: (Tabulator.() -> Unit)? = null @@ -578,7 +578,7 @@ open class Tabulator( inline fun Container.tabulator( store: ReduxStore, noinline dataFactory: (S) -> List, - options: TabulatorOptions = TabulatorOptions(), + options: TabulatorOptions = TabulatorOptions(), types: Set = setOf(), classes: Set = setOf(), noinline init: (Tabulator.() -> Unit)? = null @@ -594,7 +594,7 @@ open class Tabulator( */ inline fun Container.tabulator( store: ReduxStore, A>, - options: TabulatorOptions = TabulatorOptions(), + options: TabulatorOptions = TabulatorOptions(), types: Set = setOf(), classes: Set = setOf(), noinline init: (Tabulator.() -> Unit)? = null @@ -609,7 +609,7 @@ open class Tabulator( * DSL builder extension function for dynamic data (send within options parameter). */ fun Container.tabulator( - options: TabulatorOptions = TabulatorOptions(), + options: TabulatorOptions = TabulatorOptions(), types: Set = setOf(), classes: Set = setOf(), init: (Tabulator.() -> Unit)? = null @@ -625,7 +625,7 @@ open class Tabulator( */ @UseExperimental(ImplicitReflectionSerializer::class) inline fun create( - data: List? = null, options: TabulatorOptions = TabulatorOptions(), + data: List? = null, options: TabulatorOptions = TabulatorOptions(), types: Set = setOf(), classes: Set = setOf(), noinline init: (Tabulator.() -> Unit)? = null @@ -642,7 +642,7 @@ open class Tabulator( inline fun create( store: ReduxStore, noinline dataFactory: (S) -> List, - options: TabulatorOptions = TabulatorOptions(), + options: TabulatorOptions = TabulatorOptions(), types: Set = setOf(), classes: Set = setOf(), noinline init: (Tabulator.() -> Unit)? = null @@ -662,7 +662,7 @@ open class Tabulator( @UseExperimental(ImplicitReflectionSerializer::class) inline fun create( store: ReduxStore, A>, - options: TabulatorOptions = TabulatorOptions(), + options: TabulatorOptions = TabulatorOptions(), types: Set = setOf(), classes: Set = setOf(), noinline init: (Tabulator.() -> Unit)? = null -- cgit From d5ad6278fbc4184fc3d3a648e2419652a3c29e25 Mon Sep 17 00:00:00 2001 From: Robert Jaros Date: Mon, 13 May 2019 15:24:50 +0200 Subject: Auto update of mutable data model after edit actions. --- .../pl/treksoft/kvision/tabulator/Options.kt | 31 +++++++++++++--------- .../pl/treksoft/kvision/tabulator/Tabulator.kt | 22 ++++++++++----- 2 files changed, 34 insertions(+), 19 deletions(-) (limited to 'kvision-modules/kvision-tabulator/src/main/kotlin/pl/treksoft') diff --git a/kvision-modules/kvision-tabulator/src/main/kotlin/pl/treksoft/kvision/tabulator/Options.kt b/kvision-modules/kvision-tabulator/src/main/kotlin/pl/treksoft/kvision/tabulator/Options.kt index dd3bff5f..08f2603b 100644 --- a/kvision-modules/kvision-tabulator/src/main/kotlin/pl/treksoft/kvision/tabulator/Options.kt +++ b/kvision-modules/kvision-tabulator/src/main/kotlin/pl/treksoft/kvision/tabulator/Options.kt @@ -448,22 +448,18 @@ fun ColumnDefinition.toJs( this.sorter = sorter.sorter } if (sorterParams != null) this.sorterParams = sorterParams - if (tmpFormatterFunction != null) { - this.formatter = tmpFormatterFunction - } else if (formatterFunction != null) { - this.formatter = formatterFunction - } else if (formatter != null) { - this.formatter = formatter.formatter + when { + tmpFormatterFunction != null -> this.formatter = tmpFormatterFunction + formatterFunction != null -> this.formatter = formatterFunction + formatter != null -> this.formatter = formatter.formatter } if (formatterParams != null) this.formatterParams = formatterParams if (variableHeight != null) this.variableHeight = variableHeight if (editable != null) this.editable = editable - if (tmpEditorFunction != null) { - this.editor = tmpEditorFunction - } else if (editorFunction != null) { - this.editor = editorFunction - } else if (editor != null) { - this.editor = editor.editor + when { + tmpEditorFunction != null -> this.editor = tmpEditorFunction + editorFunction != null -> this.editor = editorFunction + editor != null -> this.editor = editor.editor } if (editorParams != null) this.editorParams = editorParams if (validator != null) this.validator = validator.validator @@ -690,6 +686,13 @@ fun TabulatorOptions.toJs( i18nTranslator: (String) -> (String), dataSerializer: KSerializer? = null ): Tabulator.Options { + val tmpCellEditCancelled = this.columns?.find { it.editorComponentFunction != null }?.let { + { cell: Tabulator.CellComponent -> + cellEditCancelled?.invoke(cell) + cell.getTable().redraw(true) + } + } ?: cellEditCancelled + return obj { if (height != null) this.height = height if (virtualDom != null) this.virtualDom = virtualDom @@ -817,7 +820,9 @@ fun TabulatorOptions.toJs( if (cellMouseMove != null) this.cellMouseMove = cellMouseMove if (cellEditing != null) this.cellEditing = cellEditing if (cellEdited != null) this.cellEdited = cellEdited - if (cellEditCancelled != null) this.cellEditCancelled = cellEditCancelled + if (tmpCellEditCancelled != null) { + this.cellEditCancelled = tmpCellEditCancelled + } if (columnMoved != null) this.columnMoved = columnMoved if (columnResized != null) this.columnResized = columnResized if (columnVisibilityChanged != null) this.columnVisibilityChanged = columnVisibilityChanged diff --git a/kvision-modules/kvision-tabulator/src/main/kotlin/pl/treksoft/kvision/tabulator/Tabulator.kt b/kvision-modules/kvision-tabulator/src/main/kotlin/pl/treksoft/kvision/tabulator/Tabulator.kt index 6c7480fc..72a2809a 100644 --- a/kvision-modules/kvision-tabulator/src/main/kotlin/pl/treksoft/kvision/tabulator/Tabulator.kt +++ b/kvision-modules/kvision-tabulator/src/main/kotlin/pl/treksoft/kvision/tabulator/Tabulator.kt @@ -38,6 +38,7 @@ import pl.treksoft.kvision.table.TableType import pl.treksoft.kvision.utils.JSON import pl.treksoft.kvision.utils.createInstance import pl.treksoft.kvision.utils.obj +import pl.treksoft.kvision.utils.syncWithList import redux.RAction import pl.treksoft.kvision.tabulator.js.Tabulator as JsTabulator @@ -47,13 +48,16 @@ import pl.treksoft.kvision.tabulator.js.Tabulator as JsTabulator * @constructor * @param T serializable type * @param data a list of serializable objects + * @param dataUpdateOnEdit determines if the data model is automatically updated after tabulator edit action * @param options tabulator options + * @param types a set of table types * @param classes a set of CSS class names * @param dataSerializer a serializer for class T */ @Suppress("LargeClass", "TooManyFunctions") open class Tabulator( protected val data: List? = null, + protected val dataUpdateOnEdit: Boolean = true, val options: TabulatorOptions = TabulatorOptions(), types: Set = setOf(), classes: Set = setOf(), @@ -191,6 +195,9 @@ open class Tabulator( val d = nativeToData(data, dataSerializer) @Suppress("UnsafeCastFromDynamic") this.dispatchEvent("tabulatorDataEdited", obj { detail = d }) + if (dataUpdateOnEdit && this.data is MutableList) { + this.data.syncWithList(d) + } } } counter++ @@ -561,12 +568,13 @@ open class Tabulator( */ inline fun Container.tabulator( data: List? = null, + dataUpdateOnEdit: Boolean = true, options: TabulatorOptions = TabulatorOptions(), types: Set = setOf(), classes: Set = setOf(), noinline init: (Tabulator.() -> Unit)? = null ): Tabulator { - val tabulator = create(data, options, types, classes) + val tabulator = create(data, dataUpdateOnEdit, options, types, classes) init?.invoke(tabulator) this.add(tabulator) return tabulator @@ -614,7 +622,7 @@ open class Tabulator( classes: Set = setOf(), init: (Tabulator.() -> Unit)? = null ): Tabulator { - val tabulator = Tabulator(options = options, types = types, classes = classes) + val tabulator = Tabulator(dataUpdateOnEdit = false, options = options, types = types, classes = classes) init?.invoke(tabulator) this.add(tabulator) return tabulator @@ -625,12 +633,14 @@ open class Tabulator( */ @UseExperimental(ImplicitReflectionSerializer::class) inline fun create( - data: List? = null, options: TabulatorOptions = TabulatorOptions(), + data: List? = null, + dataUpdateOnEdit: Boolean = true, + options: TabulatorOptions = TabulatorOptions(), types: Set = setOf(), classes: Set = setOf(), noinline init: (Tabulator.() -> Unit)? = null ): Tabulator { - val tabulator = Tabulator(data, options, types, classes, T::class.serializer()) + val tabulator = Tabulator(data, dataUpdateOnEdit, options, types, classes, T::class.serializer()) init?.invoke(tabulator) return tabulator } @@ -648,7 +658,7 @@ open class Tabulator( noinline init: (Tabulator.() -> Unit)? = null ): Tabulator { val data = dataFactory(store.getState()) - val tabulator = Tabulator(data, options, types, classes, T::class.serializer()) + val tabulator = Tabulator(data, false, options, types, classes, T::class.serializer()) init?.invoke(tabulator) store.subscribe { s -> tabulator.replaceData(dataFactory(s)) @@ -668,7 +678,7 @@ open class Tabulator( noinline init: (Tabulator.() -> Unit)? = null ): Tabulator { val data = store.getState() - val tabulator = Tabulator(data, options, types, classes, T::class.serializer()) + val tabulator = Tabulator(data, false, options, types, classes, T::class.serializer()) init?.invoke(tabulator) store.subscribe { s -> tabulator.replaceData(s) -- cgit