Skip to content

Commit

Permalink
Fix onChange on TreeSelelect (#907)
Browse files Browse the repository at this point in the history
  • Loading branch information
dzonidoo authored Jan 30, 2025
1 parent 9ea0b0b commit ecea699
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 18 deletions.
15 changes: 14 additions & 1 deletion app-typescript/components/TreeSelect/TreeSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,13 @@ export class TreeSelect<T> extends React.Component<IProps<T>, IState<T>> {
private popperInstance: Instance | null;
private zIndex: number = getNextZIndex();

/*
* This variable is used to distinguish changes coming from outside (from props.value)
* from those made by the user through interaction with the component.
* It prevents triggering `onChange` when `props.value` updates externally.
*/
private changesFromOutside: boolean;

constructor(props: IProps<T>) {
super(props);
this.state = {
Expand Down Expand Up @@ -133,6 +140,7 @@ export class TreeSelect<T> extends React.Component<IProps<T>, IState<T>> {
this.treeSelectRef = React.createRef();
this.popperInstance = null;
this.onDragEnd = this.onDragEnd.bind(this);
this.changesFromOutside = false;
}

inputFocus = () => {
Expand Down Expand Up @@ -212,8 +220,13 @@ export class TreeSelect<T> extends React.Component<IProps<T>, IState<T>> {

componentDidUpdate(prevProps: Readonly<IProps<T>>, prevState: Readonly<IState<T>>): void {
if (!isEqual(prevState.value, this.state.value)) {
this.props.onChange(this.state.value);
if (this.changesFromOutside) {
this.changesFromOutside = false;
} else {
this.props.onChange(this.state.value);
}
} else if (!isEqual(prevProps.value, this.props.value)) {
this.changesFromOutside = true;
this.setState({
value: this.props.value ?? [],
});
Expand Down
25 changes: 10 additions & 15 deletions examples/pages/components/TreeSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ interface IState {
arr: any;
}

let options = [
const multiSelectOptions = [
{
value: {name: 'Category1'},
children: [
Expand Down Expand Up @@ -93,7 +93,7 @@ let options = [
},
]

let options2 = [
const singleSelectOptions = [
{
value: {name: 'Category1', border: 'red'},
children: [
Expand Down Expand Up @@ -169,9 +169,6 @@ let options2 = [
},
]

let fetchedArr = [];
fetch('https://nominatim.openstreetmap.org/search/berlin?format=json&addressdetails=1&limit=20').then(response => response.json()).then(data => fetchedArr = data);

type ICancelFn = () => void;

function searchOptions(
Expand All @@ -181,9 +178,7 @@ function searchOptions(
let timeout = setTimeout(() => {

callback(
fetchedArr
.filter((item: any) => item.display_name.toLocaleLowerCase().includes(term.toLocaleLowerCase()))
.map((item) => ({value: item})),
multiSelectOptions.filter((item: any) => item.value.name.toLocaleLowerCase().includes(term.toLocaleLowerCase()))
);
}, 1000);

Expand All @@ -198,8 +193,8 @@ export class TreeSelectDocs extends React.Component<{}, IState> {
this.state = {
value: [],
value2: [],
options: options,
options2: options,
options: multiSelectOptions,
options2: multiSelectOptions,
inputValue: '',
arr: []
}
Expand Down Expand Up @@ -244,7 +239,7 @@ export class TreeSelectDocs extends React.Component<{}, IState> {
<TreeSelect
kind='synchronous'
value={[{name: 'Category1'}]}
getOptions={() => options}
getOptions={() => multiSelectOptions}
getId={(item) => item.name}
getLabel={(item) => item.name}
selectBranchWithChildren
Expand Down Expand Up @@ -300,7 +295,7 @@ export class TreeSelectDocs extends React.Component<{}, IState> {
<TreeSelect
kind='synchronous'
value={[{name: 'Category1'}, {name: 'Category2'}, {name: 'Category3'}]}
getOptions={() => options}
getOptions={() => multiSelectOptions}
getId={(item) => item.name}
getLabel={(item) => item.name}
selectBranchWithChildren
Expand Down Expand Up @@ -358,8 +353,8 @@ export class TreeSelectDocs extends React.Component<{}, IState> {
<TreeSelect
kind="asynchronous"
value={this.state.value}
getLabel={({display_name}) => display_name}
getId={({display_name}) => display_name}
getLabel={({name}) => name}
getId={({name}) => name}
selectBranchWithChildren
allowMultiple
searchOptions={searchOptions}
Expand Down Expand Up @@ -400,7 +395,7 @@ export class TreeSelectDocs extends React.Component<{}, IState> {
<TreeSelect
kind='synchronous'
value={[]}
getOptions={() => options2}
getOptions={() => singleSelectOptions}
getLabel={(item) => item.name}
getId={(item) => item.name}
getBorderColor={(item) => item.border}
Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "superdesk-ui-framework",
"version": "4.0.13",
"version": "4.0.14",
"license": "AGPL-3.0",
"repository": {
"type": "git",
Expand Down

0 comments on commit ecea699

Please sign in to comment.