import {Injectable} from '@angular/core'; import {BehaviorSubject} from 'rxjs'; const LOAD_MORE = 'LOAD_MORE'; /** Nested node */ export class LoadmoreNode { childrenChange = new BehaviorSubject<LoadmoreNode[]>([]); get children(): LoadmoreNode[] { return this.childrenChange.value; } constructor(public item: string, public hasChildren = false, public loadMoreParentItem: string | null = null) {} } /** Flat node with expandable and level information */ export class LoadmoreFlatNode { constructor(public item: string , public level = 1, public expandable2 = false, public loadMoreParentItem: string | null = null) { } } /** * A database that only load part of the data initially. After user clicks on the `Load more` * button, more data will be loaded. */ @Injectable({providedIn: 'root'}) export class LoadmoreDatabase { batchNumber = 5; dataChange = new BehaviorSubject<LoadmoreNode[]>([]); nodeMap = new Map<string, LoadmoreNode>(); /** The data */ rootLevelNodes: string[] = ['TECH', 'XRP']; dataMap = new Map<string, string[]>([ ['XRP', ['Company Maintenance', 'Details', 'Reports']], ['TECH', ['Company Maintenance', 'Employees', 'Reports']], ['Employees', ['Info', 'Status', 'Work', 'Section', 'Salary', 'Projects', 'performance Leve']], ]); initialize() { const data = this.rootLevelNodes.map(name => this._generateNode(name)); this.dataChange.next(data); } /** Expand a node whose children are not loaded */ loadMore(item: string, onlyFirstTime = false) { if (!this.nodeMap.has(item) || !this.dataMap.has(item)) { return; } const parent = this.nodeMap.get(item)!; const children = this.dataMap.get(item)!; if (onlyFirstTime && parent.children!.length > 0) { return; } const newChildrenNumber = parent.children!.length + this.batchNumber; const nodes = children.slice(0, newChildrenNumber) .map(name => this._generateNode(name)); if (newChildrenNumber < children.length) { // Need a new load more node nodes.push(new LoadmoreNode(LOAD_MORE, false, item)); } parent.childrenChange.next(nodes); this.dataChange.next(this.dataChange.value); } private _generateNode(item: string): LoadmoreNode { if (this.nodeMap.has(item)) { return this.nodeMap.get(item)!; } const result = new LoadmoreNode(item, this.dataMap.has(item)); this.nodeMap.set(item, result); return result; } }