Skip to content

Commit a8ffe8c

Browse files
authored
Merge pull request #1742 from iamfaran/feat/1585-table-events
[Feat]: #1585 Add Event Handlers for more Table Column Types
2 parents 248262a + 6a3ce06 commit a8ffe8c

File tree

5 files changed

+108
-45
lines changed

5 files changed

+108
-45
lines changed

client/packages/lowcoder/src/comps/comps/tableComp/column/columnTypeComps/columnDropdownComp.tsx

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { ButtonStyle } from "comps/controls/styleControlConstants";
1515
import { Button100 } from "comps/comps/buttonComp/buttonCompConstants";
1616
import styled from "styled-components";
1717
import { ButtonType } from "antd/es/button";
18+
import { clickEvent, eventHandlerControl } from "comps/controls/eventHandlerControl";
1819

1920
const StyledButton = styled(Button100)`
2021
display: flex;
@@ -28,18 +29,21 @@ const StyledIconWrapper = styled(IconWrapper)`
2829
margin: 0;
2930
`;
3031

32+
const DropdownEventOptions = [clickEvent] as const;
33+
3134
const childrenMap = {
3235
buttonType: dropdownControl(ButtonTypeOptions, "primary"),
3336
label: withDefault(StringControl, 'Menu'),
3437
prefixIcon: IconControl,
3538
suffixIcon: IconControl,
3639
options: DropdownOptionControl,
40+
onEvent: eventHandlerControl(DropdownEventOptions),
3741
};
3842

3943
const getBaseValue: ColumnTypeViewFn<typeof childrenMap, string, string> = (props) => props.label;
4044

4145
// Memoized dropdown menu component
42-
const DropdownMenu = React.memo(({ items, options }: { items: any[]; options: any[] }) => {
46+
const DropdownMenu = React.memo(({ items, options, onEvent }: { items: any[]; options: any[]; onEvent?: (eventName: string) => void }) => {
4347
const mountedRef = useRef(true);
4448

4549
// Cleanup on unmount
@@ -54,7 +58,9 @@ const DropdownMenu = React.memo(({ items, options }: { items: any[]; options: an
5458
const item = items.find((o) => o.key === key);
5559
const itemIndex = options.findIndex(option => option.label === item?.label);
5660
item && options[itemIndex]?.onEvent("click");
57-
}, [items, options]);
61+
// Also trigger the dropdown's main event handler
62+
onEvent?.("click");
63+
}, [items, options, onEvent]);
5864

5965
const handleMouseDown = useCallback((e: React.MouseEvent) => {
6066
e.stopPropagation();
@@ -78,6 +84,7 @@ const DropdownView = React.memo((props: {
7884
prefixIcon: ReactNode;
7985
suffixIcon: ReactNode;
8086
options: any[];
87+
onEvent?: (eventName: string) => void;
8188
}) => {
8289
const mountedRef = useRef(true);
8390

@@ -120,8 +127,8 @@ const DropdownView = React.memo((props: {
120127
const buttonStyle = useStyle(ButtonStyle);
121128

122129
const menu = useMemo(() => (
123-
<DropdownMenu items={items} options={props.options} />
124-
), [items, props.options]);
130+
<DropdownMenu items={items} options={props.options} onEvent={props.onEvent} />
131+
), [items, props.options, props.onEvent]);
125132

126133
return (
127134
<Dropdown
@@ -183,6 +190,7 @@ export const ColumnDropdownComp = (function () {
183190
{children.options.propertyView({
184191
title: trans("optionsControl.optionList"),
185192
})}
193+
{children.onEvent.propertyView()}
186194
</>
187195
);
188196
})

client/packages/lowcoder/src/comps/comps/tableComp/column/columnTypeComps/columnLinkComp.tsx

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,15 @@ import { disabledPropertyView } from "comps/utils/propertyUtils";
1111
import styled, { css } from "styled-components";
1212
import { styleControl } from "comps/controls/styleControl";
1313
import { TableColumnLinkStyle } from "comps/controls/styleControlConstants";
14+
import { clickEvent, eventHandlerControl } from "comps/controls/eventHandlerControl";
1415

1516
export const ColumnValueTooltip = trans("table.columnValueTooltip");
1617

18+
const LinkEventOptions = [clickEvent] as const;
19+
1720
const childrenMap = {
1821
text: StringControl,
19-
onClick: ActionSelectorControlInContext,
22+
onEvent: eventHandlerControl(LinkEventOptions),
2023
disabled: BoolCodeControl,
2124
style: styleControl(TableColumnLinkStyle),
2225
};
@@ -34,12 +37,12 @@ const StyledLink = styled.a<{ $disabled: boolean }>`
3437
`;
3538

3639
// Memoized link component
37-
export const ColumnLink = React.memo(({ disabled, label, onClick }: { disabled: boolean; label: string; onClick?: () => void }) => {
40+
export const ColumnLink = React.memo(({ disabled, label, onEvent }: { disabled: boolean; label: string; onEvent?: (eventName: string) => void }) => {
3841
const handleClick = useCallback(() => {
39-
if (!disabled && onClick) {
40-
onClick();
42+
if (!disabled && onEvent) {
43+
onEvent("click");
4144
}
42-
}, [disabled, onClick]);
45+
}, [disabled, onEvent]);
4346

4447
return (
4548
<StyledLink
@@ -106,7 +109,7 @@ export const LinkComp = (function () {
106109
childrenMap,
107110
(props, dispatch) => {
108111
const value = props.changeValue ?? getBaseValue(props, dispatch);
109-
return <ColumnLink disabled={props.disabled} label={value} onClick={props.onClick} />;
112+
return <ColumnLink disabled={props.disabled} label={value} onEvent={props.onEvent} />;
110113
},
111114
(nodeValue) => nodeValue.text.value,
112115
getBaseValue
@@ -125,10 +128,7 @@ export const LinkComp = (function () {
125128
tooltip: ColumnValueTooltip,
126129
})}
127130
{disabledPropertyView(children)}
128-
{children.onClick.propertyView({
129-
label: trans("table.action"),
130-
placement: "table",
131-
})}
131+
{children.onEvent.propertyView()}
132132
</>
133133
))
134134
.setStylePropertyViewFn((children) => (

client/packages/lowcoder/src/comps/comps/tableComp/column/columnTypeComps/columnLinksComp.tsx

Lines changed: 31 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { trans } from "i18n";
1010
import styled from "styled-components";
1111
import { ColumnLink } from "comps/comps/tableComp/column/columnTypeComps/columnLinkComp";
1212
import { LightActiveTextColor, PrimaryColor } from "constants/style";
13+
import { clickEvent, eventHandlerControl } from "comps/controls/eventHandlerControl";
1314

1415
const MenuLinkWrapper = styled.div`
1516
> a {
@@ -37,33 +38,16 @@ const MenuWrapper = styled.div`
3738
}
3839
`;
3940

40-
// Memoized menu item component
41-
const MenuItem = React.memo(({ option, index }: { option: any; index: number }) => {
42-
const handleClick = useCallback(() => {
43-
if (!option.disabled && option.onClick) {
44-
option.onClick();
45-
}
46-
}, [option.disabled, option.onClick]);
47-
48-
return (
49-
<MenuLinkWrapper>
50-
<ColumnLink
51-
disabled={option.disabled}
52-
label={option.label}
53-
onClick={handleClick}
54-
/>
55-
</MenuLinkWrapper>
56-
);
57-
});
58-
59-
MenuItem.displayName = 'MenuItem';
41+
const LinksEventOptions = [clickEvent] as const;
6042

43+
// Update OptionItem to include event handlers
6144
const OptionItem = new MultiCompBuilder(
6245
{
6346
label: StringControl,
6447
onClick: ActionSelectorControlInContext,
6548
hidden: BoolCodeControl,
6649
disabled: BoolCodeControl,
50+
onEvent: eventHandlerControl(LinksEventOptions),
6751
},
6852
(props) => {
6953
return props;
@@ -79,11 +63,38 @@ const OptionItem = new MultiCompBuilder(
7963
})}
8064
{hiddenPropertyView(children)}
8165
{disabledPropertyView(children)}
66+
{children.onEvent.propertyView()}
8267
</>
8368
);
8469
})
8570
.build();
8671

72+
// Memoized menu item component
73+
const MenuItem = React.memo(({ option, index }: { option: any; index: number }) => {
74+
const handleClick = useCallback(() => {
75+
if (!option.disabled) {
76+
if (option.onClick) {
77+
option.onClick();
78+
}
79+
if (option.onEvent) {
80+
option.onEvent("click");
81+
}
82+
}
83+
}, [option.disabled, option.onClick, option.onEvent]);
84+
85+
return (
86+
<MenuLinkWrapper>
87+
<ColumnLink
88+
disabled={option.disabled}
89+
label={option.label}
90+
onEvent={handleClick}
91+
/>
92+
</MenuLinkWrapper>
93+
);
94+
});
95+
96+
MenuItem.displayName = 'MenuItem';
97+
8798
// Memoized menu component
8899
const LinksMenu = React.memo(({ options }: { options: any[] }) => {
89100
const mountedRef = useRef(true);

client/packages/lowcoder/src/comps/comps/tableComp/column/columnTypeComps/columnSelectComp.tsx

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
import React, { useState, useRef, useEffect, useCallback, useMemo } from "react";
22

33
import { SelectUIView } from "comps/comps/selectInputComp/selectCompConstants";
4-
import { SelectOptionControl } from "comps/controls/optionsControl";
5-
import { StringControl } from "comps/controls/codeControl";
4+
import { StringControl, BoolCodeControl } from "comps/controls/codeControl";
5+
import { IconControl } from "comps/controls/iconControl";
6+
import { MultiCompBuilder } from "comps/generators";
7+
import { optionsControl } from "comps/controls/optionsControl";
8+
import { disabledPropertyView, hiddenPropertyView } from "comps/utils/propertyUtils";
69

710
import { trans } from "i18n";
811
import { ColumnTypeCompBuilder, ColumnTypeViewFn } from "../columnTypeCompBuilder";
912
import { ColumnValueTooltip } from "../simpleColumnTypeComps";
1013
import { styled } from "styled-components";
14+
import { clickEvent, eventHandlerControl } from "comps/controls/eventHandlerControl";
1115

1216
const Wrapper = styled.div`
1317
display: inline-flex;
@@ -75,9 +79,43 @@ const Wrapper = styled.div`
7579
}
7680
`;
7781

82+
const SelectOptionEventOptions = [clickEvent] as const;
83+
84+
// Create a new option type with event handlers for each option
85+
const SelectOptionWithEvents = new MultiCompBuilder(
86+
{
87+
value: StringControl,
88+
label: StringControl,
89+
prefixIcon: IconControl,
90+
disabled: BoolCodeControl,
91+
hidden: BoolCodeControl,
92+
onEvent: eventHandlerControl(SelectOptionEventOptions),
93+
},
94+
(props) => props
95+
)
96+
.setPropertyViewFn((children) => (
97+
<>
98+
{children.label.propertyView({ label: trans("label") })}
99+
{children.value.propertyView({ label: trans("value") })}
100+
{children.prefixIcon.propertyView({ label: trans("button.prefixIcon") })}
101+
{disabledPropertyView(children)}
102+
{hiddenPropertyView(children)}
103+
{children.onEvent.propertyView()}
104+
</>
105+
))
106+
.build();
107+
108+
const SelectOptionWithEventsControl = optionsControl(SelectOptionWithEvents, {
109+
initOptions: [
110+
{ label: trans("optionsControl.optionI", { i: 1 }), value: "1" },
111+
{ label: trans("optionsControl.optionI", { i: 2 }), value: "2" },
112+
],
113+
uniqField: "value",
114+
});
115+
78116
const childrenMap = {
79117
text: StringControl,
80-
options: SelectOptionControl,
118+
options: SelectOptionWithEventsControl,
81119
};
82120

83121
const getBaseValue: ColumnTypeViewFn<typeof childrenMap, string, string> = (props) => props.text;
@@ -106,7 +144,13 @@ const SelectEdit = React.memo((props: SelectEditProps) => {
106144
if (!mountedRef.current) return;
107145
props.onChange(val);
108146
setCurrentValue(val);
109-
}, [props.onChange]);
147+
148+
// Trigger the specific option's event handler
149+
const selectedOption = props.options.find(option => option.value === val);
150+
if (selectedOption && selectedOption.onEvent) {
151+
selectedOption.onEvent("click");
152+
}
153+
}, [props.onChange, props.options]);
110154

111155
const handleEvent = useCallback(async (eventName: string) => {
112156
if (!mountedRef.current) return [] as unknown[];

client/packages/lowcoder/src/comps/comps/tableComp/column/simpleColumnTypeComps.tsx

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import React, { useCallback, useEffect, useMemo } from "react";
1313
import { CSSProperties } from "react";
1414
import { RecordConstructorToComp } from "lowcoder-core";
1515
import { ToViewReturn } from "@lowcoder-ee/comps/generators/multi";
16+
import { clickEvent, eventHandlerControl } from "comps/controls/eventHandlerControl";
1617

1718
export const ColumnValueTooltip = trans("table.columnValueTooltip");
1819

@@ -31,10 +32,12 @@ export const ButtonTypeOptions = [
3132
},
3233
] as const;
3334

35+
const ButtonEventOptions = [clickEvent] as const;
36+
3437
const childrenMap = {
3538
text: StringControl,
3639
buttonType: dropdownControl(ButtonTypeOptions, "primary"),
37-
onClick: ActionSelectorControlInContext,
40+
onEvent: eventHandlerControl(ButtonEventOptions),
3841
loading: BoolCodeControl,
3942
disabled: BoolCodeControl,
4043
prefixIcon: IconControl,
@@ -49,8 +52,8 @@ const ButtonStyled = React.memo(({ props }: { props: ToViewReturn<RecordConstruc
4952
const iconOnly = !hasText && (hasPrefixIcon || hasSuffixIcon);
5053

5154
const handleClick = useCallback((e: React.MouseEvent) => {
52-
props.onClick?.();
53-
}, [props.onClick]);
55+
props.onEvent("click");
56+
}, [props.onEvent]);
5457

5558
const buttonStyle = useMemo(() => ({
5659
margin: 0,
@@ -100,10 +103,7 @@ export const ButtonComp = (function () {
100103
})}
101104
{loadingPropertyView(children)}
102105
{disabledPropertyView(children)}
103-
{children.onClick.propertyView({
104-
label: trans("table.action"),
105-
placement: "table",
106-
})}
106+
{children.onEvent.propertyView()}
107107
</>
108108
))
109109
.build();

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy