Files
tp-tree-nav/mixins/tree-load-children.js
2025-12-28 23:06:37 +01:00

63 lines
2.2 KiB
JavaScript

export const TreeLoadChildrenMixin = (superClass) => class TreeLoadChildrenMixin extends superClass {
async _loadChildrenForExpanded(key, source, originalEvent, nodeHint = null, pathHint = null) {
if (typeof this.loadChildren !== 'function') return;
const node = nodeHint ?? this._findNodeByKey(key);
if (!node) return;
const controller = new AbortController();
const seq = ++this._childLoadSeq;
const previous = this._childLoadControllers.get(key);
if (previous) {
try { previous.abort(); } catch (e) { }
}
this._childLoadControllers.set(key, controller);
this._updateNodeStatesByKey(key, (n) => {
const states = Array.isArray(n.states) ? n.states : [];
const next = states.filter((s) => s !== 'loaded');
if (!next.includes('loading')) next.push('loading');
return { ...n, states: next };
});
try {
const ctx = {
node,
key,
path: Array.isArray(pathHint) ? pathHint : key.split('/').filter(Boolean),
signal: controller.signal,
source,
originalEvent,
};
await Promise.resolve(this.loadChildren(ctx));
if (controller.signal.aborted) return;
if (this._childLoadControllers.get(key) !== controller) return;
if (seq !== this._childLoadSeq) return;
this._updateNodeStatesByKey(key, (n) => {
const states = Array.isArray(n.states) ? n.states : [];
const next = states.filter((s) => s !== 'loading');
if (!next.includes('loaded')) next.push('loaded');
return { ...n, states: next };
});
} catch (err) {
if (controller.signal.aborted) return;
this._updateNodeStatesByKey(key, (n) => {
const states = Array.isArray(n.states) ? n.states : [];
const next = states.filter((s) => s !== 'loading');
return { ...n, states: next };
});
this.dispatchEvent(new CustomEvent('node-children-error', {
detail: { key, node, error: err, source, originalEvent },
bubbles: true,
composed: true,
}));
} finally {
if (this._childLoadControllers.get(key) === controller) {
this._childLoadControllers.delete(key);
}
}
}
};