diff --git a/src/TreeView.tsx b/src/TreeView.tsx index a2338ce..a545ab7 100644 --- a/src/TreeView.tsx +++ b/src/TreeView.tsx @@ -106,14 +106,6 @@ class TreeView extends Component { this.store = new NodeStore(storeOpts); } - // componentDidUpdate(): void { - // if (this.widgetId) { - // const domNode = findDOMNode(this); - // // @ts-ignore - // domNode.setAttribute("widgetId", this.widgetId); - // } - // } - componentWillReceiveProps(nextProps: TreeViewContainerProps): void { if (!this.widgetId && this.ref.current) { try { @@ -129,15 +121,11 @@ class TreeView extends Component { } if (nextProps.experimentalExposeSetSelected && this.store.contextObject) { - const guid = this.store.contextObject.getGuid(); - // @ts-ignore - if (typeof window[`__TreeView_${guid}_select`] !== "undefined") { - // @ts-ignore - delete window[`__TreeView_${guid}_select`]; - } + this.deleteExposedMethod(); } this.store.setContext(nextProps.mxObject); + if (nextProps.mxObject) { this.store.setLoading(true); this.fetchData(nextProps.mxObject); @@ -145,11 +133,17 @@ class TreeView extends Component { if (nextProps.experimentalExposeSetSelected && nextProps.mxObject) { const guid = nextProps.mxObject.getGuid(); + const methodName = `__TreeView_${guid}_select`; // @ts-ignore - window[`__TreeView_${guid}_select`] = this.store.setSelectedFromExternal.bind(this.store); + window[methodName] = this.store.setSelectedFromExternal.bind(this.store); + this.debug(`Expose external select method: window.${methodName}`); } } + componentWillUnmount(): void { + this.deleteExposedMethod(); + } + render(): ReactNode { const { dragIsDraggable, @@ -177,6 +171,17 @@ class TreeView extends Component { ); } + private deleteExposedMethod(): void { + const guid = this.store.contextObject?.getGuid(); + const methodName = `__TreeView_${guid}_select`; + // @ts-ignore + if (guid && typeof window[methodName] !== "undefined") { + // @ts-ignore + delete window[methodName]; + this.debug(`Remove external select method: window.${methodName}`); + } + } + private async _fetchData(object: mendix.lib.MxObject): Promise { this.debug("fetchData", object.getGuid()); const { @@ -397,13 +402,6 @@ class TreeView extends Component { localStoredState.lastUpdate && currentDateTime - localStoredState.lastUpdate < this.props.stateLocalStorageTime * 1000 * 60 ) { - // if ( - // localStoredState.selected && - // localStoredState.selected.length > 0 && - // stateExecuteSelectActionOnRestore - // ) { - // this.onSelectAction(localStoredState.selected); - // } return localStoredState; } diff --git a/src/TreeView.xml b/src/TreeView.xml index d10aab0..16f06cd 100644 --- a/src/TreeView.xml +++ b/src/TreeView.xml @@ -333,7 +333,7 @@ Note: State management (currently) ONLY works when you load a whole tree (see Da When you restore your state, and you have an On Click action defined in Events, you can automatically execute this on the last selected item you clicked. This is only done for Microflow/Nanoflow, not the Open Page action. - + diff --git a/src/components/TreeViewComponent.tsx b/src/components/TreeViewComponent.tsx index 56a9cbe..eff5edc 100644 --- a/src/components/TreeViewComponent.tsx +++ b/src/components/TreeViewComponent.tsx @@ -114,8 +114,6 @@ export class TreeViewComponent extends Component { const expanded = [...expandedKeys]; const treeData = [...this.getTreeNodes(store.entryTree)]; - console.log(expanded, treeData); - return ( Promise = async () => {}; public searchHandler: ((_query: string) => Promise) | null; public debug: (...args: unknown[]) => void; - public findParents = this._findParents.bind(this); - public setSelectedFromExternal = this._setSelectedFromExternal.bind(this); @observable public isLoading: boolean; @observable public contextObject: mendix.lib.MxObject | null; @@ -341,33 +339,36 @@ export class NodeStore { } } - private _setSelectedFromExternal(guid: string): void { + @action + setSelectedFromExternal(guid: string): void { if (!this.holdSelection) { return; } const found = this.entries.find(e => e.guid === guid); + this.debug("setSelectedFromExternal", guid, found); if (found) { - const parents = this.findParents(found).reverse(); - this.collapseAll(); - parents.forEach(p => this.expandKey(p.guid, true)); + const obj = found.obj; + const parentIds = this.getParents(obj).map(obj => obj.guid); + const toCollapse = this.expandedKeys.filter(expanded => !parentIds.find(p => p === expanded)); + toCollapse.forEach(id => this.expandKey(id, false, false)); + parentIds.forEach(p => this.expandKey(p, true, false)); this.selectEntry(found.guid); } } // Expanded - get expandedKeys(): string[] { return this.entries.filter(e => e.isExpanded).map(e => e.guid); } @action - expandKey(guid: string, expanded: boolean): void { + expandKey(guid: string, expanded: boolean, onChange = true): void { const entryObject = this.findEntry(guid); if (entryObject) { if (expanded && !entryObject.isLoaded) { this.childLoader(entryObject, guid); } else { - entryObject.setExpanded(expanded); + entryObject.setExpanded(expanded, onChange); } } } @@ -414,30 +415,48 @@ export class NodeStore { } // Entries + @computed - get entryList(): TreeObject[] { + get treeMapping(): { [key:string]: string } { const needParentMapping = this.entryObjectAttributes.relationType === "nodeChildren"; const treeMapping: { [key: string]: string } = {}; + + if (needParentMapping) { + this.entries.forEach(entry => { + const obj = entry.obj; + if (obj.children) { + obj.children.forEach(child => { + treeMapping[child] = obj.guid; + }) + } + }) + } else { + this.entries.forEach(entry => { + const obj = entry.obj; + if (obj.parent) { + treeMapping[obj.guid] = obj.parent + } + }) + } + + return treeMapping; + } + + + @computed + get entryList(): TreeObject[] { + const needParentMapping = this.entryObjectAttributes.relationType === "nodeChildren"; + const treeMapping = this.treeMapping; + let entries: TreeObject[] = [...this.entries].map(entry => { const obj = entry.obj; obj.highlight = false; - if (needParentMapping && obj.children) { - obj.children.forEach(child => { - treeMapping[child] = obj.guid; - }); + if (needParentMapping && treeMapping[obj.guid]) { + obj.parent = treeMapping[obj.guid]; } return obj; }); - if (this.entryObjectAttributes.relationType === "nodeChildren") { - entries = entries.map(entryObj => { - if (treeMapping[entryObj.guid]) { - entryObj.parent = treeMapping[entryObj.guid]; - } - return entryObj; - }); - } - if (this.searchQuery !== "") { const rawEntries = [...entries] .filter(e => this.filter.indexOf(e.guid) !== -1) @@ -494,21 +513,6 @@ export class NodeStore { return found || null; } - private _findParents(entry: EntryObject): EntryObject[] { - let tree = entry; - const returnArray: EntryObject[] = []; - while (tree._parent) { - const parent = this.findEntry(tree._parent); - if (parent) { - returnArray.push(parent); - tree = parent; - } else { - break; - } - } - return returnArray; - } - private entryHandler( opts: EntryObjectExtraOptions ): (guid: string, removedCB: (removed: boolean) => void) => Promise { @@ -528,13 +532,13 @@ export class NodeStore { } private getParents(treeObject: TreeObject): TreeObject[] { - let tree = treeObject; + let parentGuid = this.treeMapping[treeObject.guid]; const returnArray: TreeObject[] = []; - while (tree.parent) { - const parent = this.findEntry(tree.parent); + while (parentGuid) { + const parent = this.findEntry(parentGuid); if (parent) { returnArray.push(parent.obj); - tree = parent.obj; + parentGuid = this.treeMapping[parent.guid]; } else { break; } @@ -543,7 +547,7 @@ export class NodeStore { } private _onExpandChange(): void { - this.debug("store: onExpandChange", this.expandedKeys); + // this.debug("store: onExpandChange", this.expandedKeys); if (this.contextObject) { this.writeTableState({ context: this.contextObject.getGuid(),