diff --git a/client/packages/lowcoder/src/comps/comps/buttonComp/dropdownComp.tsx b/client/packages/lowcoder/src/comps/comps/buttonComp/dropdownComp.tsx index f58b39bd6..5b15445df 100644 --- a/client/packages/lowcoder/src/comps/comps/buttonComp/dropdownComp.tsx +++ b/client/packages/lowcoder/src/comps/comps/buttonComp/dropdownComp.tsx @@ -83,13 +83,16 @@ const DropdownTmpComp = (function () { key: option.label + " - " + index, disabled: option.disabled, icon: hasIcon && {option.prefixIcon}, - onEvent: option.onEvent, + index, })); const menu = ( items.find((o) => o.key === key)?.onEvent("click")} + onClick={({ key }) => { + const item = items.find((o) => o.key === key); + item && props.options[item.index]?.onEvent("click"); + }} /> ); diff --git a/client/packages/lowcoder/src/comps/comps/listViewComp/listView.tsx b/client/packages/lowcoder/src/comps/comps/listViewComp/listView.tsx index 97319c64e..b45bc755b 100644 --- a/client/packages/lowcoder/src/comps/comps/listViewComp/listView.tsx +++ b/client/packages/lowcoder/src/comps/comps/listViewComp/listView.tsx @@ -176,7 +176,10 @@ export function ListView(props: Props) { return
; } const containerProps = containerFn( - { [itemIndexName]: itemIdx, [itemDataName]: getCurrentItemParams(data, itemIdx) }, + { + [itemIndexName]: itemIdx, + [itemDataName]: getCurrentItemParams(data, itemIdx) + }, String(itemIdx) ).getView(); const unMountFn = () => { diff --git a/client/packages/lowcoder/src/comps/comps/listViewComp/listViewComp.tsx b/client/packages/lowcoder/src/comps/comps/listViewComp/listViewComp.tsx index 5df6f33f7..dd1dc85e9 100644 --- a/client/packages/lowcoder/src/comps/comps/listViewComp/listViewComp.tsx +++ b/client/packages/lowcoder/src/comps/comps/listViewComp/listViewComp.tsx @@ -7,7 +7,7 @@ import { } from "comps/controls/codeControl"; import { styleControl } from "comps/controls/styleControl"; import { ListViewStyle } from "comps/controls/styleControlConstants"; -import { UICompBuilder, withDefault, withPropertyViewFn, withViewFn } from "comps/generators"; +import { UICompBuilder, stateComp, valueComp, withDefault, withPropertyViewFn, withViewFn } from "comps/generators"; import { CompDepsConfig, depsConfig, @@ -37,6 +37,7 @@ import { ContextContainerComp } from "./contextContainerComp"; import { ListView } from "./listView"; import { listPropertyView } from "./listViewPropertyView"; import { getData } from "./listViewUtils"; +import { withMethodExposing } from "comps/generators/withMethodExposing"; const childrenMap = { noOfRows: withIsLoadingMethod(NumberOrJSONObjectArrayControl), // FIXME: migrate "noOfRows" to "data" @@ -80,10 +81,10 @@ export class ListViewImplComp extends ListViewTmpComp implements IContainer { } override reduce(action: CompAction): this { // console.info("listView reduce. action: ", action); - let comp = reduceInContext({ inEventContext: true }, () => super.reduce(action)); + if (action.type === CompActionTypes.UPDATE_NODES_V2) { - const { itemCount } = getData(comp.children.noOfRows.getView()); + const { itemCount} = getData(comp.children.noOfRows.getView()); const pagination = comp.children.pagination.getView(); const total = pagination.total || itemCount; const offset = (pagination.current - 1) * pagination.pageSize; @@ -151,11 +152,11 @@ export class ListViewImplComp extends ListViewTmpComp implements IContainer { const ListViewRenderComp = withViewFn(ListViewImplComp, (comp) => ); const ListPropertyView = listPropertyView("listView"); -const ListViewPropertyComp = withPropertyViewFn(ListViewRenderComp, (comp) => { +let ListViewPropertyComp = withPropertyViewFn(ListViewRenderComp, (comp) => { return ; }); -export const ListViewComp = withExposingConfigs(ListViewPropertyComp, [ +ListViewPropertyComp = withExposingConfigs(ListViewPropertyComp, [ new CompDepsConfig( "items", (comp) => ({ data: comp.itemsNode() }), @@ -171,9 +172,31 @@ export const ListViewComp = withExposingConfigs(ListViewPropertyComp, [ return data; }, }), + // new CompDepsConfig( + // "index", + // (comp) => ({index: comp.children.itemIndexName.node() }), + // (input) => input.index.value, + // "index", // trans("listView.itemsDesc") + // ), NameConfigHidden, ]); +export const ListViewComp = withMethodExposing(ListViewPropertyComp, [ + { + method: { + name: "setPage", + description: "", + params: [{ name: "page", type: "number" }], + }, + execute: (comp, values) => { + const page = values[0] as number; + if (page && page > 0) { + comp.children.pagination.children.pageNo.dispatchChangeValueAction(page); + } + }, + }, +]) + export function defaultListViewData(compName: string, nameGenerator: NameGenerator) { return { noOfRows: @@ -232,7 +255,7 @@ export function defaultListViewData(compName: string, nameGenerator: NameGenerat compType: "rating", name: nameGenerator.genItemName("rating"), comp: { - value: "{{currentItem.rate / 2}}", + defaultValue: "{{currentItem.rate / 2}}", max: "5", label: { text: "", diff --git a/client/packages/lowcoder/src/comps/comps/numberInputComp/numberInputComp.tsx b/client/packages/lowcoder/src/comps/comps/numberInputComp/numberInputComp.tsx index f1c917521..4baacf4d1 100644 --- a/client/packages/lowcoder/src/comps/comps/numberInputComp/numberInputComp.tsx +++ b/client/packages/lowcoder/src/comps/comps/numberInputComp/numberInputComp.tsx @@ -10,7 +10,7 @@ import { import { BoolControl } from "comps/controls/boolControl"; import { dropdownControl } from "comps/controls/dropdownControl"; import { LabelControl } from "comps/controls/labelControl"; -import { numberExposingStateControl } from "comps/controls/codeStateControl"; +import { numberExposingStateControl, stringExposingStateControl } from "comps/controls/codeStateControl"; import NP from "number-precision"; import { @@ -234,6 +234,7 @@ const UndefinedNumberControl = codeControl((value: any) => { }); const childrenMap = { + defaultValue: stringExposingStateControl("defaultValue"), // It is more convenient for string to handle various states, save raw input here value: numberExposingStateControl("value"), // It is more convenient for string to handle various states, save raw input here placeholder: StringControl, disabled: BoolCodeControl, @@ -261,6 +262,17 @@ const childrenMap = { const CustomInputNumber = (props: RecordConstructorToView) => { const ref = useRef(null); + const defaultValue = props.defaultValue.value; + + useEffect(() => { + let value = 0; + if (defaultValue === 'null' && props.allowNull) { + value = NaN; + } else if (!isNaN(Number(defaultValue))) { + value = Number(defaultValue); + } + props.value.onChange(value); + }, [defaultValue]); const formatFn = (value: number) => format(value, props.allowNull, props.formatter, props.precision, props.thousandsSeparator); @@ -271,7 +283,9 @@ const CustomInputNumber = (props: RecordConstructorToView) = const oldValue = props.value.value; const newValue = parseNumber(tmpValue, props.allowNull); props.value.onChange(newValue); - oldValue !== newValue && props.onEvent("change"); + if((oldValue !== newValue)) { + props.onEvent("change"); + } }; useEffect(() => { @@ -363,7 +377,7 @@ const NumberInputTmpComp = (function () { .setPropertyViewFn((children) => ( <>
- {children.value.propertyView({ label: trans("prop.defaultValue") })} + {children.defaultValue.propertyView({ label: trans("prop.defaultValue") })} {placeholderPropertyView(children)} {children.formatter.propertyView({ label: trans("numberInput.formatter") })}
diff --git a/client/packages/lowcoder/src/comps/comps/ratingComp.tsx b/client/packages/lowcoder/src/comps/comps/ratingComp.tsx index 992c45f74..40db580ab 100644 --- a/client/packages/lowcoder/src/comps/comps/ratingComp.tsx +++ b/client/packages/lowcoder/src/comps/comps/ratingComp.tsx @@ -15,7 +15,7 @@ import { migrateOldData } from "comps/generators/simpleGenerators"; import { disabledPropertyView, hiddenPropertyView } from "comps/utils/propertyUtils"; import { trans } from "i18n"; -import { useContext } from "react"; +import { useContext, useEffect, useRef } from "react"; import { EditorContext } from "comps/editorState"; const EventOptions = [changeEvent] as const; @@ -36,6 +36,7 @@ function fixOldData(oldData: any) { const RatingBasicComp = (function () { const childrenMap = { + defaultValue: numberExposingStateControl("defaultValue"), value: numberExposingStateControl("value"), max: withDefault(NumberControl, "5"), label: LabelControl, @@ -46,6 +47,21 @@ const RatingBasicComp = (function () { ...formDataChildren, }; return new UICompBuilder(childrenMap, (props) => { + const defaultValue = { ...props.defaultValue }.value; + const value = { ...props.value }.value; + const changeRef = useRef(false) + + useEffect(() => { + props.value.onChange(defaultValue); + }, [defaultValue]); + + useEffect(() => { + if (!changeRef.current) return; + + props.onEvent("change"); + changeRef.current = false; + }, [value]); + return props.label({ style: props.style, children: ( @@ -54,7 +70,7 @@ const RatingBasicComp = (function () { value={props.value.value} onChange={(e) => { props.value.onChange(e); - props.onEvent("change"); + changeRef.current = true; }} allowHalf={props.allowHalf} disabled={props.disabled} @@ -67,7 +83,7 @@ const RatingBasicComp = (function () { return ( <>
- {children.value.propertyView({ label: trans("prop.defaultValue") })} + {children.defaultValue.propertyView({ label: trans("prop.defaultValue") })} {children.max.propertyView({ label: trans("rating.max"), })} diff --git a/client/packages/lowcoder/src/comps/comps/selectInputComp/checkboxComp.tsx b/client/packages/lowcoder/src/comps/comps/selectInputComp/checkboxComp.tsx index 8152980d5..f30b92c45 100644 --- a/client/packages/lowcoder/src/comps/comps/selectInputComp/checkboxComp.tsx +++ b/client/packages/lowcoder/src/comps/comps/selectInputComp/checkboxComp.tsx @@ -102,7 +102,8 @@ const CheckboxGroup = styled(AntdCheckboxGroup)<{ const CheckboxBasicComp = (function () { const childrenMap = { - value: arrayStringExposingStateControl("value", ["1"]), + defaultValue: arrayStringExposingStateControl("defaultValue"), + value: arrayStringExposingStateControl("value"), label: LabelControl, disabled: BoolCodeControl, onEvent: ChangeEventHandlerControl, @@ -115,7 +116,10 @@ const CheckboxBasicComp = (function () { ...formDataChildren, }; return new UICompBuilder(childrenMap, (props) => { - const [validateState, handleValidate] = useSelectInputValidate(props); + const [ + validateState, + handleChange, + ] = useSelectInputValidate(props); return props.label({ required: props.required, style: props.style, @@ -134,9 +138,7 @@ const CheckboxBasicComp = (function () { disabled: option.disabled, }))} onChange={(values) => { - handleValidate(values as string[]); - props.value.onChange(values as string[]); - props.onEvent("change"); + handleChange(values as string[]); }} /> ), diff --git a/client/packages/lowcoder/src/comps/comps/selectInputComp/multiSelectComp.tsx b/client/packages/lowcoder/src/comps/comps/selectInputComp/multiSelectComp.tsx index c052f89fb..a8c2c0dc1 100644 --- a/client/packages/lowcoder/src/comps/comps/selectInputComp/multiSelectComp.tsx +++ b/client/packages/lowcoder/src/comps/comps/selectInputComp/multiSelectComp.tsx @@ -14,18 +14,24 @@ import { SelectInputInvalidConfig, useSelectInputValidate } from "./selectInputC import { PaddingControl } from "../../controls/paddingControl"; import { MarginControl } from "../../controls/marginControl"; +import { useEffect, useRef } from "react"; const MultiSelectBasicComp = (function () { const childrenMap = { ...SelectChildrenMap, - value: arrayStringExposingStateControl("value", ["1", "2"]), + defaultValue: arrayStringExposingStateControl("defaultValue", ["1", "2"]), + value: arrayStringExposingStateControl("value"), style: styleControl(MultiSelectStyle), margin: MarginControl, padding: PaddingControl, }; return new UICompBuilder(childrenMap, (props, dispatch) => { const valueSet = new Set(props.options.map((o) => o.value)); // Filter illegal default values entered by the user - const [validateState, handleValidate] = useSelectInputValidate(props); + const [ + validateState, + handleChange, + ] = useSelectInputValidate(props); + return props.label({ required: props.required, style: props.style, @@ -34,11 +40,7 @@ const MultiSelectBasicComp = (function () { {...props} mode={"multiple"} value={props.value.value.filter?.((v) => valueSet.has(v))} - onChange={(value) => { - handleValidate(value); - props.value.onChange(value); - props.onEvent("change"); - }} + onChange={handleChange} dispatch={dispatch} /> ), diff --git a/client/packages/lowcoder/src/comps/comps/selectInputComp/radioComp.tsx b/client/packages/lowcoder/src/comps/comps/selectInputComp/radioComp.tsx index e1bc7033c..494a3b24f 100644 --- a/client/packages/lowcoder/src/comps/comps/selectInputComp/radioComp.tsx +++ b/client/packages/lowcoder/src/comps/comps/selectInputComp/radioComp.tsx @@ -83,7 +83,10 @@ const Radio = styled(AntdRadioGroup)<{ const RadioBasicComp = (function () { return new UICompBuilder(RadioChildrenMap, (props) => { - const [validateState, handleValidate] = useSelectInputValidate(props); + const [ + validateState, + handleChange, + ] = useSelectInputValidate(props); return props.label({ required: props.required, style: props.style, @@ -95,9 +98,7 @@ const RadioBasicComp = (function () { $style={props.style} $layout={props.layout} onChange={(e) => { - handleValidate(e.target.value); - props.value.onChange(e.target.value); - props.onEvent("change"); + handleChange(e.target.value); }} options={props.options .filter((option) => option.value !== undefined && !option.hidden) diff --git a/client/packages/lowcoder/src/comps/comps/selectInputComp/radioCompConstants.tsx b/client/packages/lowcoder/src/comps/comps/selectInputComp/radioCompConstants.tsx index f84180dd0..56cf0c8c0 100644 --- a/client/packages/lowcoder/src/comps/comps/selectInputComp/radioCompConstants.tsx +++ b/client/packages/lowcoder/src/comps/comps/selectInputComp/radioCompConstants.tsx @@ -30,6 +30,7 @@ export const RadioLayoutOptions = [ ] as const; export const RadioChildrenMap = { + defaultValue: stringExposingStateControl("value"), value: stringExposingStateControl("value"), label: LabelControl, disabled: BoolCodeControl, @@ -46,6 +47,9 @@ export const RadioChildrenMap = { export const RadioPropertyView = ( children: RecordConstructorToComp< typeof RadioChildrenMap & { hidden: typeof BoolCodeControl } & { + defaultValue: + | ReturnType + | ReturnType; value: | ReturnType | ReturnType; @@ -55,7 +59,7 @@ export const RadioPropertyView = ( <>
{children.options.propertyView({})} - {children.value.propertyView({ label: trans("prop.defaultValue") })} + {children.defaultValue.propertyView({ label: trans("prop.defaultValue") })}
{["logic", "both"].includes(useContext(EditorContext).editorModeStatus) && ( diff --git a/client/packages/lowcoder/src/comps/comps/selectInputComp/segmentedControl.tsx b/client/packages/lowcoder/src/comps/comps/selectInputComp/segmentedControl.tsx index bf105982a..6c82fd62b 100644 --- a/client/packages/lowcoder/src/comps/comps/selectInputComp/segmentedControl.tsx +++ b/client/packages/lowcoder/src/comps/comps/selectInputComp/segmentedControl.tsx @@ -62,6 +62,7 @@ const Segmented = styled(AntdSegmented)<{ $style: SegmentStyleType }>` `; const SegmentChildrenMap = { + defaultValue: stringExposingStateControl("value"), value: stringExposingStateControl("value"), label: LabelControl, disabled: BoolCodeControl, @@ -76,7 +77,11 @@ const SegmentChildrenMap = { const SegmentedControlBasicComp = (function () { return new UICompBuilder(SegmentChildrenMap, (props) => { - const [validateState, handleValidate] = useSelectInputValidate(props); + const [ + validateState, + handleValidate, + handleChange, + ] = useSelectInputValidate(props); return props.label({ required: props.required, style: props.style, @@ -88,9 +93,7 @@ const SegmentedControlBasicComp = (function () { value={props.value.value} $style={props.style} onChange={(value) => { - handleValidate(value.toString()); - props.value.onChange(value.toString()); - props.onEvent("change"); + handleChange(value.toString()); }} options={props.options .filter((option) => option.value !== undefined && !option.hidden) @@ -109,7 +112,7 @@ const SegmentedControlBasicComp = (function () { <>
{children.options.propertyView({})} - {children.value.propertyView({ label: trans("prop.defaultValue") })} + {children.defaultValue.propertyView({ label: trans("prop.defaultValue") })}
{["logic", "both"].includes(useContext(EditorContext).editorModeStatus) && ( diff --git a/client/packages/lowcoder/src/comps/comps/selectInputComp/selectComp.tsx b/client/packages/lowcoder/src/comps/comps/selectInputComp/selectComp.tsx index 98c5b8bc8..1a30f2522 100644 --- a/client/packages/lowcoder/src/comps/comps/selectInputComp/selectComp.tsx +++ b/client/packages/lowcoder/src/comps/comps/selectInputComp/selectComp.tsx @@ -21,16 +21,21 @@ import { RecordConstructorToView } from "lowcoder-core"; const SelectBasicComp = (function () { const childrenMap = { ...SelectChildrenMap, + defaultValue: stringExposingStateControl("defaultValue"), value: stringExposingStateControl("value"), style: styleControl(SelectStyle), }; return new UICompBuilder(childrenMap, (props, dispatch) => { - const [validateState, handleValidate] = useSelectInputValidate(props); + const [ + validateState, + handleChange, + ] = useSelectInputValidate(props); const propsRef = useRef>(props); propsRef.current = props; const valueSet = new Set(props.options.map((o) => o.value)); // Filter illegal default values entered by the user + return props.label({ required: props.required, style: props.style, @@ -38,12 +43,7 @@ const SelectBasicComp = (function () { { - props.value.onChange(value ?? "").then(() => { - propsRef.current.onEvent("change"); - handleValidate(value ?? ""); - }); - }} + onChange={handleChange} dispatch={dispatch} /> ), diff --git a/client/packages/lowcoder/src/comps/comps/selectInputComp/selectCompConstants.tsx b/client/packages/lowcoder/src/comps/comps/selectInputComp/selectCompConstants.tsx index 86493bf76..4f5a0ba18 100644 --- a/client/packages/lowcoder/src/comps/comps/selectInputComp/selectCompConstants.tsx +++ b/client/packages/lowcoder/src/comps/comps/selectInputComp/selectCompConstants.tsx @@ -265,6 +265,7 @@ export const SelectPropertyView = ( hidden: typeof BoolCodeControl; } > & { + defaultValue: { propertyView: (params: ControlParams) => ControlNode }; value: { propertyView: (params: ControlParams) => ControlNode }; style: { getPropertyView: () => ControlNode }; } @@ -272,7 +273,7 @@ export const SelectPropertyView = ( <>
{children.options.propertyView({})} - {children.value.propertyView({ label: trans("prop.defaultValue") })} + {children.defaultValue.propertyView({ label: trans("prop.defaultValue") })} {placeholderPropertyView(children)}
diff --git a/client/packages/lowcoder/src/comps/comps/selectInputComp/selectInputConstants.tsx b/client/packages/lowcoder/src/comps/comps/selectInputComp/selectInputConstants.tsx index 8476a372c..7c4fdc126 100644 --- a/client/packages/lowcoder/src/comps/comps/selectInputComp/selectInputConstants.tsx +++ b/client/packages/lowcoder/src/comps/comps/selectInputComp/selectInputConstants.tsx @@ -11,7 +11,7 @@ import { } from "../../controls/codeStateControl"; import { requiredPropertyView } from "comps/utils/propertyUtils"; import { trans } from "i18n"; -import { useRef, useState } from "react"; +import { useEffect, useRef, useState } from "react"; import { SelectInputOptionControl } from "../../controls/optionsControl"; import { refMethods } from "comps/generators/withMethodExposing"; import { blurMethod, focusWithOptions } from "comps/utils/methodUtils"; @@ -22,10 +22,18 @@ export const SelectInputValidationChildren = { }; type ValidationComp = RecordConstructorToComp; +type SelectValue = string | (string | number)[]; type ValidationParams = { - value: { value: string | (string | number)[] }; + defaultValue?: { + value: SelectValue, + }; + value: { + value: SelectValue, + onChange?: (value: any) => Promise, + }; required: boolean; customRule: string; + onEvent?: (eventName: string) => Promise, }; export const selectInputValidate = ( @@ -45,10 +53,14 @@ export const selectInputValidate = ( }; export const useSelectInputValidate = (props: ValidationParams) => { + const [validateState, setValidateState] = useState({}); + const changeRef = useRef(false) const propsRef = useRef(props); propsRef.current = props; - const [validateState, setValidateState] = useState({}); + const selectValue = props.value.value; + const defaultValue = props.defaultValue?.value; + const handleValidate = (value: string | (string | number)[]) => { setValidateState( selectInputValidate({ @@ -59,7 +71,29 @@ export const useSelectInputValidate = (props: ValidationParams) => { }) ); }; - return [validateState, handleValidate] as const; + + useEffect(() => { + props.value.onChange?.(defaultValue) + }, [defaultValue]); + + useEffect(() => { + if (!changeRef.current) return; + + handleValidate(selectValue); + props.onEvent?.("change"); + changeRef.current = false; + }, [selectValue]); + + const handleChange = (value: any) => { + props.value.onChange?.(value); + changeRef.current = true; + }; + + return [ + validateState, + handleValidate, + handleChange, + ] as const; }; type ValidationCompWithValue = ValidationComp & { diff --git a/client/packages/lowcoder/src/comps/comps/tableComp/column/columnTypeComps/columnSelectComp.tsx b/client/packages/lowcoder/src/comps/comps/tableComp/column/columnTypeComps/columnSelectComp.tsx index d4305a928..e9c5ebaa1 100644 --- a/client/packages/lowcoder/src/comps/comps/tableComp/column/columnTypeComps/columnSelectComp.tsx +++ b/client/packages/lowcoder/src/comps/comps/tableComp/column/columnTypeComps/columnSelectComp.tsx @@ -23,13 +23,14 @@ type SelectEditProps = { options: any[]; }; -const SelectEdit = (props: SelectEditProps) => { +const SelectEdit = ( + props: SelectEditProps, +) => { const [currentValue, setCurrentValue] = useState(props.initialValue); - return ( { props.onChange(val); setCurrentValue(val) diff --git a/client/packages/lowcoder/src/comps/comps/tableComp/column/tableColumnComp.tsx b/client/packages/lowcoder/src/comps/comps/tableComp/column/tableColumnComp.tsx index 0d5e2ac2b..cb19414b9 100644 --- a/client/packages/lowcoder/src/comps/comps/tableComp/column/tableColumnComp.tsx +++ b/client/packages/lowcoder/src/comps/comps/tableComp/column/tableColumnComp.tsx @@ -90,7 +90,6 @@ export const columnChildrenMap = { isCustom: valueComp(false), // If it is a data column, it must be the name of the column and cannot be duplicated as a react key dataIndex: valueComp(""), - columnsList: valueComp>([]), hide: BoolControl, sortable: BoolControl, width: NumberControl, @@ -207,7 +206,7 @@ export class ColumnComp extends ColumnInitComp { })} { diff --git a/client/packages/lowcoder/src/comps/comps/tableComp/tableUtils.tsx b/client/packages/lowcoder/src/comps/comps/tableComp/tableUtils.tsx index 9508af8ce..f3a74123f 100644 --- a/client/packages/lowcoder/src/comps/comps/tableComp/tableUtils.tsx +++ b/client/packages/lowcoder/src/comps/comps/tableComp/tableUtils.tsx @@ -250,13 +250,20 @@ function renderTitle(props: { title: string; editable: boolean }) { ); } -function getInitialColumns(columnsAggrData: ColumnsAggrData) { - const initialColumns = Object.keys(columnsAggrData).map(column => ({ - label: {column}, - value: `{{currentRow.${column}}}` - })) +function getInitialColumns( + columnsAggrData: ColumnsAggrData, + customColumns: string[], +) { + let initialColumns = []; + Object.keys(columnsAggrData).forEach(column => { + if(customColumns.includes(column)) return; + initialColumns.push({ + label: column, + value: `{{currentRow.${column}}}` + }); + }); initialColumns.push({ - label: Select with handlebars, + label: 'Select with handlebars', value: '{{currentCell}}', }) return initialColumns; @@ -283,7 +290,8 @@ export function columnsToAntdFormat( columnsAggrData: ColumnsAggrData, onTableEvent: (eventName: any) => void, ): Array> { - const initialColumns = getInitialColumns(columnsAggrData); + const customColumns = columns.filter(col => col.isCustom).map(col => col.dataIndex); + const initialColumns = getInitialColumns(columnsAggrData, customColumns); const sortMap: Map = new Map( sort.map((s) => [s.column, s.desc ? "descend" : "ascend"]) ); diff --git a/client/packages/lowcoder/src/comps/comps/textInputComp/textInputConstants.tsx b/client/packages/lowcoder/src/comps/comps/textInputComp/textInputConstants.tsx index 291c04077..66b7e4cdb 100644 --- a/client/packages/lowcoder/src/comps/comps/textInputComp/textInputConstants.tsx +++ b/client/packages/lowcoder/src/comps/comps/textInputComp/textInputConstants.tsx @@ -32,7 +32,7 @@ import { requiredPropertyView, } from "comps/utils/propertyUtils"; import { trans } from "i18n"; -import { ChangeEvent, useRef, useState } from "react"; +import { ChangeEvent, useEffect, useRef, useState } from "react"; import { refMethods } from "comps/generators/withMethodExposing"; import { InputRef } from "antd/es/input"; import { @@ -134,6 +134,7 @@ const TextInputInvalidConfig = depsConfig props.onEvent("focus"), onBlur: () => props.onEvent("blur"), @@ -164,22 +166,38 @@ export const textInputProps = (props: RecordConstructorToView) => { const [validateState, setValidateState] = useState({}); + const changeRef = useRef(false) const propsRef = useRef>(props); propsRef.current = props; - const handleChange = (e: ChangeEvent) => { - props.value.onChange(e.target.value); - propsRef.current.onEvent("change"); + const defaultValue = { ...props.defaultValue }.value; + const inputValue = { ...props.value }.value; + + useEffect(() => { + props.value.onChange(defaultValue) + }, [defaultValue]); + + useEffect(() => { + if (!changeRef.current) return; + setValidateState( textInputValidate({ ...propsRef.current, value: { - value: e.target.value, + value: inputValue, }, }) ); + propsRef.current.onEvent("change"); + changeRef.current = false; + }, [inputValue]); + + const handleChange = (e: ChangeEvent) => { + props.value.onChange(e.target.value); + changeRef.current = true; }; + return [ { ...textInputProps(props), @@ -193,7 +211,7 @@ type TextInputComp = RecordConstructorToComp; export const TextInputBasicSection = (children: TextInputComp) => (
- {children.value.propertyView({ label: trans("prop.defaultValue") })} + {children.defaultValue.propertyView({ label: trans("prop.defaultValue") })} {placeholderPropertyView(children)}
); diff --git a/client/packages/lowcoder/src/comps/comps/treeComp/treeSelectComp.tsx b/client/packages/lowcoder/src/comps/comps/treeComp/treeSelectComp.tsx index 993113e97..ea31712a3 100644 --- a/client/packages/lowcoder/src/comps/comps/treeComp/treeSelectComp.tsx +++ b/client/packages/lowcoder/src/comps/comps/treeComp/treeSelectComp.tsx @@ -85,7 +85,11 @@ const TreeCompView = ( ) => { const { treeData, selectType, value, expanded, style, inputValue } = props; const isSingle = selectType === "single"; - const [validateState, handleValidate] = useSelectInputValidate(props); + const [ + validateState, + handleChange, + ] = useSelectInputValidate(props); + useEffect(() => { if (isSingle && value.value.length > 1) { value.onChange(value.value.slice(0, 1)); @@ -119,9 +123,7 @@ const TreeCompView = ( }} onChange={(keys) => { const nextValue = Array.isArray(keys) ? keys : keys !== undefined ? [keys] : []; - handleValidate(nextValue); - value.onChange(nextValue); - props.onEvent("change"); + handleChange(nextValue); }} showSearch={props.showSearch} // search label diff --git a/client/packages/lowcoder/src/comps/comps/treeComp/treeUtils.tsx b/client/packages/lowcoder/src/comps/comps/treeComp/treeUtils.tsx index 1ad7ce909..2e6fb61d6 100644 --- a/client/packages/lowcoder/src/comps/comps/treeComp/treeUtils.tsx +++ b/client/packages/lowcoder/src/comps/comps/treeComp/treeUtils.tsx @@ -68,6 +68,7 @@ function expandAll(data: TreeDataNode[]) { export const treeCommonChildren = { // TODO: support loading mode treeData: jsonControl(convertTreeData, defaultTreeData), + defaultValue: jsonExposingStateControl("value", checkNodeValues, []), value: jsonExposingStateControl("value", checkNodeValues, []), expanded: jsonStateControl(checkNodeValues, []), defaultExpandAll: BoolControl, @@ -94,8 +95,9 @@ type TreeCommonComp = NewChildren children.treeData.propertyView({ label: trans("tree.treeData"), tooltip: treeDataTooltip }); -export const valuePropertyView = (children: TreeCommonComp) => - children.value.propertyView({ label: trans("tree.value") }); +export const valuePropertyView = (children: TreeCommonComp) => { + return children.defaultValue.propertyView({ label: trans("tree.value") }); +} export const formSection = (children: TreeCommonComp) => ; diff --git a/client/packages/lowcoder/src/comps/controls/dropdownControl.tsx b/client/packages/lowcoder/src/comps/controls/dropdownControl.tsx index 1492a97a4..01b7b832c 100644 --- a/client/packages/lowcoder/src/comps/controls/dropdownControl.tsx +++ b/client/packages/lowcoder/src/comps/controls/dropdownControl.tsx @@ -96,7 +96,6 @@ export function dropdownAbstractControl( value={this.value} options={finalOptions} onChange={(value) => { - console.log(value); if (!params.disableDispatchValueChange) { this.dispatchChangeValueAction(value); } diff --git a/client/packages/lowcoder/src/comps/controls/optionsControl.tsx b/client/packages/lowcoder/src/comps/controls/optionsControl.tsx index 24dd5f42f..1230a195e 100644 --- a/client/packages/lowcoder/src/comps/controls/optionsControl.tsx +++ b/client/packages/lowcoder/src/comps/controls/optionsControl.tsx @@ -33,11 +33,12 @@ import { import styled from "styled-components"; import { lastValueIfEqual } from "util/objectUtils"; import { getNextEntityName } from "util/stringUtils"; -import { JSONValue } from "util/jsonTypes"; +import { JSONObject, JSONValue } from "util/jsonTypes"; import { ButtonEventHandlerControl } from "./eventHandlerControl"; import { ControlItemCompBuilder } from "comps/generators/controlCompBuilder"; import { ColorControl } from "./colorControl"; import { StringStateControl } from "./codeStateControl"; +import { reduceInContext } from "../utils/reduceContext"; const OptionTypes = [ { @@ -312,8 +313,16 @@ export function mapOptionsControl( } override reduce(action: CompAction) { - const comp = super.reduce(action); + // TODO: temporary solution condition to fix context issue in dropdown option's events + if ( + action.type === CompActionTypes.CUSTOM + && (action.value as JSONObject).type === 'actionTriggered' + ) { + const comp = reduceInContext({ inEventContext: true }, () => super.reduce(action)); + return comp; + } else if (action.type === CompActionTypes.UPDATE_NODES_V2) { + const comp = super.reduce(action) if (comp.children.data !== this.children.data) { const sourceArray = comp.children.data.getView(); const dataExample = sourceArray ? sourceArray[0] : undefined; @@ -322,8 +331,9 @@ export function mapOptionsControl( return comp.updateContext(dataExample); } } + return comp; } - return comp; + return super.reduce(action); } updateContext(dataExample: JSONValue) { diff --git a/client/packages/lowcoder/src/comps/generators/withParams.tsx b/client/packages/lowcoder/src/comps/generators/withParams.tsx index a29f63cb3..4a72c3ae6 100644 --- a/client/packages/lowcoder/src/comps/generators/withParams.tsx +++ b/client/packages/lowcoder/src/comps/generators/withParams.tsx @@ -34,7 +34,7 @@ export const paramsEqual = ( params1: Record | undefined, params2: Record | undefined ) => { - return depthEqual(params1, params2, 3); + return depthEqual(params1, params2, 4); }; export function withParams(