Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions packages/pluggableWidgets/tree-node-web/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),

## [Unreleased]

### Changed

- We changed `hasChildren` configuration from boolean to expression.

### Fixed

- We fixed an issue where Tree Nodes showing loading spinner when children can't be found while `hasChildren` property configured to `true`.

## [3.6.0] - 2025-10-01

### Changed
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { parseStyle } from "@mendix/widget-plugin-platform/preview/parse-style";
import { mapPreviewIconToWebIcon } from "@mendix/widget-plugin-platform/preview/map-icon";
import { parseStyle } from "@mendix/widget-plugin-platform/preview/parse-style";
import { GUID } from "mendix";
import { ReactElement } from "react";
import { TreeNodePreviewProps } from "../typings/TreeNodeProps";
Expand Down Expand Up @@ -32,10 +32,10 @@ export function preview(props: TreeNodePreviewProps): ReactElement | null {
<props.children.renderer caption="Place other tree nodes here.">
<div />
</props.children.renderer>
)
),
isUserDefinedLeafNode: !props.hasChildren
}
]}
isUserDefinedLeafNode={!props.hasChildren}
startExpanded
showCustomIcon={Boolean(props.expandedIcon) || Boolean(props.collapsedIcon)}
iconPlacement={props.showIcon}
Expand Down
4 changes: 2 additions & 2 deletions packages/pluggableWidgets/tree-node-web/src/TreeNode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
id: item.id,
headerContent:
props.headerType === "text" ? props.headerCaption?.get(item).value : props.headerContent?.get(item),
bodyContent: props.children?.get(item)
bodyContent: props.children?.get(item),
isUserDefinedLeafNode: props.hasChildren?.get(item).value === false
};
}

Expand All @@ -27,7 +28,7 @@
setTreeNodeItems([]);
}
}
}, [datasource.status, datasource.items]);

Check warning on line 31 in packages/pluggableWidgets/tree-node-web/src/TreeNode.tsx

View workflow job for this annotation

GitHub Actions / Run code quality check

React Hook useEffect has a missing dependency: 'props'. Either include it or remove the dependency array. If 'setTreeNodeItems' needs the current value of 'props', you can also switch to useReducer instead of useState and read 'props' in the reducer
const expandedIcon = props.expandedIcon?.status === ValueStatus.Available ? props.expandedIcon.value : undefined;
const collapsedIcon = props.collapsedIcon?.status === ValueStatus.Available ? props.collapsedIcon.value : undefined;

Expand All @@ -36,7 +37,6 @@
class={props.class}
style={props.style}
items={treeNodeItems}
isUserDefinedLeafNode={!props.hasChildren}
startExpanded={props.startExpanded}
showCustomIcon={Boolean(props.expandedIcon) || Boolean(props.collapsedIcon)}
iconPlacement={props.showIcon}
Expand Down
3 changes: 2 additions & 1 deletion packages/pluggableWidgets/tree-node-web/src/TreeNode.xml
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,10 @@
<caption>Header caption</caption>
<description />
</property>
<property key="hasChildren" type="boolean" defaultValue="true">
<property key="hasChildren" type="expression" dataSource="datasource">
<caption>Has children</caption>
<description>Indicate whether the node has children or is an end node. When set to yes, a composable region becomes available to define the child nodes.</description>
<returnType type="Boolean" />
</property>
<property key="startExpanded" type="boolean" defaultValue="false">
<caption>Start expanded</caption>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ import { TreeNodeBranchContext, useInformParentContextOfChildNodes } from "./Tre
export interface TreeNodeItem extends ObjectItem {
headerContent: ReactNode;
bodyContent: ReactNode;
isUserDefinedLeafNode: boolean;
}

export interface TreeNodeProps extends Pick<TreeNodeContainerProps, "tabIndex"> {
class: string;
style?: CSSProperties;
items: TreeNodeItem[] | null;
isUserDefinedLeafNode: TreeNodeBranchProps["isUserDefinedLeafNode"];
startExpanded: TreeNodeBranchProps["startExpanded"];
showCustomIcon: boolean;
iconPlacement: TreeNodeBranchProps["iconPlacement"];
Expand All @@ -34,7 +34,6 @@ export function TreeNode({
class: className,
items,
style,
isUserDefinedLeafNode,
showCustomIcon,
startExpanded,
iconPlacement,
Expand Down Expand Up @@ -79,22 +78,25 @@ export function TreeNode({
data-focusindex={tabIndex || 0}
role={level === 0 ? "tree" : "group"}
>
{items.map(({ id, headerContent, bodyContent }) => (
<TreeNodeBranch
key={id}
id={id}
headerContent={headerContent}
isUserDefinedLeafNode={isUserDefinedLeafNode}
startExpanded={startExpanded}
iconPlacement={iconPlacement}
renderHeaderIcon={renderHeaderIconCallback}
changeFocus={changeTreeNodeBranchHeaderFocus}
animateTreeNodeContent={animateTreeNodeContent}
openNodeOn={openNodeOn}
>
{bodyContent}
</TreeNodeBranch>
))}
{items.map(item => {
const { id, headerContent, bodyContent, isUserDefinedLeafNode } = item;
return (
<TreeNodeBranch
key={id}
id={id}
headerContent={headerContent}
isUserDefinedLeafNode={isUserDefinedLeafNode}
startExpanded={startExpanded}
iconPlacement={iconPlacement}
renderHeaderIcon={renderHeaderIconCallback}
changeFocus={changeTreeNodeBranchHeaderFocus}
animateTreeNodeContent={animateTreeNodeContent}
openNodeOn={openNodeOn}
>
{bodyContent}
</TreeNodeBranch>
);
})}
</ul>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
hasNestedTreeNode: () => boolean;
} => {
const hasNestedTreeNode = useCallback(
() => treeNodeBranchBody.current?.lastElementChild?.className.includes("widget-tree-node") ?? true,
() => treeNodeBranchBody.current?.lastElementChild?.className.includes("widget-tree-node") ?? false,
[]

Check warning on line 14 in packages/pluggableWidgets/tree-node-web/src/components/hooks/lazyLoading.ts

View workflow job for this annotation

GitHub Actions / Run code quality check

React Hook useCallback has a missing dependency: 'treeNodeBranchBody'. Either include it or remove the dependency array
);

return { hasNestedTreeNode };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export interface TreeNodeContainerProps {
openNodeOn: OpenNodeOnEnum;
headerContent?: ListWidgetValue;
headerCaption?: ListExpressionValue<string>;
hasChildren: boolean;
hasChildren: ListExpressionValue<boolean>;
startExpanded: boolean;
children?: ListWidgetValue;
animate: boolean;
Expand All @@ -50,7 +50,7 @@ export interface TreeNodePreviewProps {
openNodeOn: OpenNodeOnEnum;
headerContent: { widgetCount: number; renderer: ComponentType<{ children: ReactNode; caption?: string }> };
headerCaption: string;
hasChildren: boolean;
hasChildren: string;
startExpanded: boolean;
children: { widgetCount: number; renderer: ComponentType<{ children: ReactNode; caption?: string }> };
animate: boolean;
Expand Down
Loading