{"id":13480794,"url":"https://github.com/valor-software/ng2-tree","last_synced_at":"2025-04-08T12:09:04.257Z","repository":{"id":54920569,"uuid":"47972012","full_name":"valor-software/ng2-tree","owner":"valor-software","description":"Angular tree component","archived":false,"fork":false,"pushed_at":"2024-01-30T23:04:24.000Z","size":27499,"stargazers_count":349,"open_issues_count":142,"forks_count":188,"subscribers_count":30,"default_branch":"master","last_synced_at":"2025-04-01T10:17:20.677Z","etag":null,"topics":["angular","angular-tree","async","branch","children","ng2-tree","tree","treeview"],"latest_commit_sha":null,"homepage":"http://valor-software.com/ng2-tree/index.html","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/valor-software.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2015-12-14T11:48:36.000Z","updated_at":"2025-03-05T20:40:33.000Z","dependencies_parsed_at":"2024-06-18T12:35:47.951Z","dependency_job_id":"f1c4c180-852f-4b7e-8321-f78cd11c4de6","html_url":"https://github.com/valor-software/ng2-tree","commit_stats":{"total_commits":216,"total_committers":15,"mean_commits":14.4,"dds":0.4120370370370371,"last_synced_commit":"1aca43dc182c0edbc790753686aff063eedd52b6"},"previous_names":[],"tags_count":21,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/valor-software%2Fng2-tree","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/valor-software%2Fng2-tree/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/valor-software%2Fng2-tree/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/valor-software%2Fng2-tree/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/valor-software","download_url":"https://codeload.github.com/valor-software/ng2-tree/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247339149,"owners_count":20923014,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["angular","angular-tree","async","branch","children","ng2-tree","tree","treeview"],"created_at":"2024-07-31T17:00:45.088Z","updated_at":"2025-04-08T12:09:04.234Z","avatar_url":"https://github.com/valor-software.png","language":"TypeScript","readme":"# :herb: ng2-tree\n\n[![npm](https://img.shields.io/npm/v/ng2-tree.svg?style=flat-square)](https://www.npmjs.com/package/ng2-tree)\n[![Travis](https://img.shields.io/travis/valor-software/ng2-tree.svg?style=flat-square)](https://travis-ci.org/valor-software/ng2-tree)\n[![Codecov](https://img.shields.io/codecov/c/github/valor-software/ng2-tree.svg?style=flat-square)](https://codecov.io/github/valor-software/ng2-tree)\n\n\u003c!-- TOC --\u003e\n\n* [:clapper: Usage](#clapper-usage)\n* [:eyes: Demo](#eyes-demo)\n* [:wrench: API](#wrench-api)\n  * [tree](#tree)\n  * [[tree]](#tree)\n    * [Load children asynchronously](#load-children-asynchronously)\n    * [Load children using ngrx (or any redux-like library)](#load-children-using-ngrx-or-any-redux-like-library)\n    * [Configure node via TreeModelSettings](#configure-node-via-treemodelsettings)\n  * [[settings]](#settings)\n  * [`Tree` class](#tree-class)\n  * [events (nodeMoved, nodeSelected, nodeRenamed, nodeRemoved, nodeCreated, nodeExpanded, nodeCollapsed)](#events-nodemoved-nodeselected-noderenamed-noderemoved-nodecreated-nodeexpanded-nodecollapsed)\n    * [NodeSelectedEvent](#nodeselectedevent)\n    * [NodeMovedEvent](#nodemovedevent)\n    * [NodeRemovedEvent](#noderemovedevent)\n    * [NodeCreatedEvent](#nodecreatedevent)\n    * [NodeRenamedEvent](#noderenamedevent)\n    * [NodeExpandedEvent](#nodeexpandedevent)\n    * [NodeCollapsedEvent](#nodecollapsedevent)\n    * [LoadNextLevelEvent](#loadnextlevelevent)\n* [:gun: Controller](#gun-controller)\n  * [select - selects a node](#select---selects-a-node)\n  * [isSelected - checks whether a node is selected](#isselected---checks-whether-a-node-is-selected)\n  * [collapse - collapses a node](#collapse---collapses-a-node)\n  * [isCollapsed - check whether a node is collapsed](#iscollapsed---check-whether-a-node-is-collapsed)\n  * [expand - expands a node](#expand---expands-a-node)\n  * [isExpanded - checks whether a node is expanded](#isexpanded---checks-whether-a-node-is-expanded)\n  * [toTreeModel - converts a tree to a TreeModel instance](#totreemodel---converts-a-tree-to-a-treemodel-instance)\n  * [rename - renames a node (changes its value underneath)](#rename---renames-a-node-changes-its-value-underneath)\n  * [startRenaming - changes the node template so that text input appears and lets a user type a new name](#startrenaming---changes-the-node-template-so-that-text-input-appears-and-lets-a-user-type-a-new-name)\n  * [remove - removes a node from the tree](#remove---removes-a-node-from-the-tree)\n  * [addChild - creates a new child node](#addchild---creates-a-new-child-node)\n  * [changeNodeId - changes node's id](#changenodeid---changes-nodes-id)\n  * [reloadChildren - loads async children once more](#reloadchildren---loads-async-children-once-more)\n  * [setChildren - changes children of a node;](#setchildren---changes-children-of-a-node)\n* [SystemJS](#systemjs)\n* [Changes that should be taken into account in order to migrate from **ng2-tree V1** to **ng2-tree V2**](#changes-that-should-be-taken-into-account-in-order-to-migrate-from-__ng2-tree-v1__-to-__ng2-tree-v2__)\n* [:bulb: Want to help?](#bulb-want-to-help)\n\n\u003c!-- /TOC --\u003e\n\n## :clapper: Usage\n\nOk, let's start with an installation - all you need to do is:\n\n`npm install --save ng2-tree`\n\nNow when you have `ng2-tree` installed, you are in a few steps from having tree in your application:\n\n1. Add the `TreeModule` to your application's module `imports` section:\n\n```typescript\nimport { NgModule } from '@angular/core';\nimport { AppComponent } from './app.component';\nimport { BrowserModule } from '@angular/platform-browser';\nimport { TreeModule } from 'ng2-tree';\n\n@NgModule({\n  declarations: [MyComponent],\n  imports: [BrowserModule, TreeModule],\n  bootstrap: [MyComponent]\n})\nexport class MyModule {}\n```\n\n2. As soon as the previous step is done we need to give ng2-tree a model to render - this can be accomplished by populating its `[tree]` attribute with an object that conforms to the `TreeModel` interface (see [API](#wrench-api)):\n\n```typescript\n// 1 - import required classes and interfaces\nimport { TreeModel } from 'ng2-tree';\n\n@Component({\n  selector: 'myComp',\n  // 2 - set [tree] attribute to tree object\n  template: `\u003ctree [tree]=\"tree\"\u003e\u003c/tree\u003e`\n})\nclass MyComponent {\n  // 3 - make sure that tree object conforms to the TreeModel interface\n  public tree: TreeModel = {\n    value: 'Programming languages by programming paradigm',\n    children: [\n      {\n        value: 'Object-oriented programming',\n        children: [{ value: 'Java' }, { value: 'C++' }, { value: 'C#' }]\n      },\n      {\n        value: 'Prototype-based programming',\n        children: [{ value: 'JavaScript' }, { value: 'CoffeeScript' }, { value: 'Lua' }]\n      }\n    ]\n  };\n}\n```\n\n3. Apart from that, in order to have usable tree in the browser, you need to add **ng2-tree styles** which you can find in your `node_modules/ng2-tree/styles.css`\n\nIn Angular 2/4 cli projects, modify **.angular-cli.json** as below:\n\n```typescript\n      \"styles\": [\n        \"styles.css\",\n        \"../node_modules/ng2-tree/styles.css\"\n      ],\n```\n\n4. And finally, I suppose, you'd want to listen to events generated by ng2-tree (for a full list of supported events look at the [API](#wrench-api)). No problem, this is also easy to do - for example let's add a listener for `node was selected` kind of events:\n\n```typescript\n// 1 - import required classes and interfaces\nimport { TreeModel, NodeEvent } from 'ng2-tree';\n\n@Component({\n  selector: 'myComp',\n  // 2 - listent for nodeSelected events and handle them\n  template: `\u003ctree [tree]=\"tree\" (nodeSelected)=\"logEvent($event)\"\u003e\u003c/tree\u003e`\n})\nclass MyComponent {\n  public tree: TreeModel = { ... };\n\n  // 3 - print caught event to the console\n  public logEvent(e: NodeEvent): void {\n    console.log(e);\n  }\n}\n```\n\nVoila! That's pretty much it - enjoy :blush:\n\n## :eyes: Demo\n\nFeel free to examine the [demo](https://valor-software.github.io/ng2-tree/index.html) and its [sources](src/demo) to find out how things are wired.\nAlso, there is [another demo built with Angular CLI](https://github.com/rychkog/ng2-tree-demo).\n\n## :wrench: API\n\nHere is the fully stuffed _tree_ tag that you can use in your templates:\n\n```html\n    \u003ctree\n      [tree]=\"tree\"\n      [settings]=\"settings\"\n      (nodeRemoved)=\"handleRemoved($event)\"\n      (nodeRenamed)=\"handleRenamed($event)\"\n      (nodeSelected)=\"handleSelected($event)\"\n      (nodeMoved)=\"handleMoved($event)\"\n      (nodeCreated)=\"handleCreated($event)\"\n      (nodeExpanded)=\"handleExpanded($event)\"\n      (nodeCollapsed)=\"handleCollapsed($event)\"\n      (loadNextLevel)=\"handleNextLevel($event)\"\u003e\n    \u003c/tree\u003e\n```\n\nLet's go through every element of this structure one by one.\n\n### tree\n\n`tree` is the selector for `TreeComponent` which is bundled into `TreeModule`:\n\n### [tree]\n\n`tree` has a `[tree]` attribute which needs to be populated with an object implementing `TreeModel` interface. You can import this interface like below:\n\n```typescript\nimport { TreeModel } from 'ng2-tree';\n```\n\nHere is the definition of the `TreeModel` interface:\n\n```typescript\ninterface TreeModel {\n  value: string | RenamableNode;\n  id: string | number;\n  children?: Array\u003cTreeModel\u003e;\n  loadChildren?: ChildrenLoadingFunction;\n  settings?: TreeModelSettings;\n}\n```\n\nAs you can see - an object that conforms to this interface has a recursive nature, an example can be seen below:\n\n```typescript\n{\n    value: 'Programming languages by programming paradigm',\n    children: [\n      {\n        value: 'Object-oriented programming',\n        children: [\n          {value: 'Java'},\n          {value: 'C++'},\n          {value: 'C#'}\n        ]\n      },\n      {\n        value: 'Prototype-based programming',\n        children: [\n          {value: 'JavaScript'},\n          {value: 'CoffeeScript'},\n          {value: 'Lua'}\n        ]\n      }\n    ]\n  }\n```\n\nProperty `value` can be of type `string` or `RenamableNode`.\n`RenamableNode` gives you an additional control over the way node is renamed and rendered (by rendered I mean its text representation). Here is the definition of the `RenamableNode` interface:\n\n```typescript\ninterface RenamableNode {\n  // This method will be invoked in order to apply new value to this kind of node\n  setName(name: string): void;\n\n  // This method will be invoked in order to get a text for rendering as a node value\n  toString(): string;\n}\n```\n\nHere is an example of such a node in the `TreeModel` object:\n\n```typescript\n{\n    value: 'Programming languages by programming paradigm',\n    children: [\n      {\n        value: 'Object-oriented programming',\n        children: [\n          {\n            // I am a RenamableNode. Yeah, that's me :)\n            value: \u003cRenamableNode\u003e{\n              name: 'Java',\n              setName(name: string): void {\n                this.name = name;\n              },\n              toString(): string {\n                return this.name;\n              }\n            }\n          },\n          {value: 'C++'},\n          {value: 'C#'}\n        ]\n      },\n      {\n        value: 'Prototype-based programming',\n        loadChildren: (callback) =\u003e {\n          setTimeout(() =\u003e {\n            callback([\n              {value: 'JavaScript'},\n              {value: 'CoffeeScript'},\n              {value: 'TypeScript'}\n            ]);\n          }, 5000);\n        }\n      }\n    ]\n  };\n```\n\n#### Load children asynchronously\n\nAnother worth noting thing is `loadChildren`. This function on `TreeModel` allows you to load its **children asynchronously**.\n\n```typescript\n{\n  value: 'Prototype-based programming',\n  loadChildren: (callback) =\u003e {\n    setTimeout(() =\u003e {\n      callback([\n        {value: 'JavaScript'},\n        {value: 'CoffeeScript'},\n        {value: 'TypeScript'}\n      ]);\n    }, 5000);\n  }\n}\n```\n\nNode that defines this function is collapsed by default. At the moment of clicking 'Expand' arrow, it starts loading its children by calling given function.\nIf `loadChildren` function is given to the node - `children` property is ignored. For more details - have a look at the [Demo](#eyes-demo).\n\n#### Load children using ngrx (or any redux-like library)\n\nYou can also load children by changing the tree state using ngrx.\nThe tree can emit an appropriate event notifying you to dispatch a new action in order to load the branch's children.\n\nTo enable this feature you should set the `TreeModel.emitLoadNextLevel` property to true:\n\n```typscript\nconst model: TreeModel = {\nemitLoadNextLevel : true\n}\n```\n\nNow on the first time the node is expanded a **LoadNextLevelEvent** will be fired (via the **loadNextLevel** EventEmitter in the tree) containing the node that requested a next level (its children) loading.\n\nIn your code make sure you change the tree state and add the children to the model.\n\nIn addition the regular **NodeExpanded** event will be fired.\n\n**NOTICE**: if both `emitLoadNextLevel` and `loadChildren` are provided, the tree will ignore the `emitLoadNextLevel` and the `LoadNextLevelEvent` won't be fired.\n\n#### Configure node via TreeModelSettings\n\nApart from that `TreeModel` interface has an optional field called `settings` of type `TreeModelSettings`.\n\nHere is an example of its usage:\n\n```typescript\n{\n  value: 'Prototype-based programming',\n  settings: {\n    'static': true,\n    'rightMenu': true,\n    'leftMenu': true,\n    'cssClasses': {\n      'expanded': 'fa fa-caret-down fa-lg',\n      'collapsed': 'fa fa-caret-right fa-lg',\n      'leaf': 'fa fa-lg',\n      'empty': 'fa fa-caret-right disabled'\n    },\n    'templates': {\n      'node': '\u003ci class=\"fa fa-folder-o fa-lg\"\u003e\u003c/i\u003e',\n      'leaf': '\u003ci class=\"fa fa-file-o fa-lg\"\u003e\u003c/i\u003e',\n      'leftMenu': '\u003ci class=\"fa fa-navicon fa-lg\"\u003e\u003c/i\u003e'\n    },\n    'menuItems': [\n        { action: NodeMenuItemAction.Custom, name: 'Foo', cssClass: 'fa fa-arrow-right' },\n        { action: NodeMenuItemAction.Custom, name: 'Bar', cssClass: 'fa fa-arrow-right' },\n        { action: NodeMenuItemAction.Custom, name: 'Baz', cssClass: 'fa fa-arrow-right'}\n      ]\n    }\n  },\n  children: [\n    {value: 'JavaScript'},\n    {value: 'CoffeeScript'},\n    {value: 'Lua'}\n  ]\n}\n```\n\n* `static` - Boolean - This option makes it impossible to drag a tree or modify it in a some way, though you still can select nodes in the static tree and appropriate events will be generated.\n* `isCollapsedOnInit` - Boolean - This option makes a tree to be collapsed on first load (this option cascades to its children).\n* `rightMenu` - Boolean - This option allows you to activate (true, by default) or deactivate (false) right menu when clicking with right button of a mouse.\n* `leftMenu` - Boolean - This option allows you to activate (true) or deactivate (false, by default) left menu.\n* `cssClasses` - Object:\n  * `expanded` - String - It specifies a css class (or classes) for an item which represents expanded state of a node. The item is clickable and it transitions the node to the collapsed state\n  * `collapsed` - String - It specifies a css class (or classes) for an item which represents collapsed state of a node. The item is clickable and it transitions the node to the expanded state\n  * `leaf` - String - It specifies a css class (or classes) for an item which represents a node without an option to expand or collapse - in other words: a leaf node.\n  * `empty` - String - Node is considered empty when it has no children. Once this condition is satisfied - appropriate css class will be applied to the node.\n* `templates` - Object:\n  * `node` - String - It specifies a html template which will be included to the left of the node's value.\n  * `leaf` - String - It specifies a html template which will be included to the left of the leaf's value.\n  * `leftMenu` - String - It specifies a html template to the right of the node's value. This template becomes clickable and shows a menu on node's click.\n* `menuItems` - here you can specify your custom menu items. You should feed an array of NodeMenuItem instances to this setting. Once done - setup a subscription to `MenuItemSelectedEvent`s by listening to `(menuItemSelected)=\"onMenuItemSelected($event)\"` on the tree.\n\nAll options that are defined on a `parent` are automatically applied to children. If you want you can override them by `settings` of the child node.\n\n### [settings]\n\nObject that should be passed to `[settings]` must be of type [`Ng2TreeSettings`](src/tree.types.ts). This attribute is **optional**. Right now only one setting is available in there - `rootIsVisible`. This setting allows you to make a root node of the tree _invisible_:\n\n```typescript\nconst treeSettings: Ng2TreeSettings = {\n  rootIsVisible: false\n};\n```\n\nBy default `rootIsVisible` equals to `true`\n\n### `Tree` class\n\nAlso in the next section, you'll be reading about events generated by the `ng2-tree`. And here [Tree](src/tree.ts) class comes in handy for us, because its instances propagated with event objects. Under the hood, `ng2-tree` wraps a `TreeModel` provided by the user in `Tree`. And `Tree` in turn has lots of useful methods and properties (like `parent`, `hasChild()`, `isRoot()` etc.)\n\n### events (nodeMoved, nodeSelected, nodeRenamed, nodeRemoved, nodeCreated, nodeExpanded, nodeCollapsed)\n\n`NodeEvent` is the root of the tree events' hierarchy. It defines property `node` that contains a receiver of the event action (`node` is an instance of the `Tree` class).\n\n`NodeDestructiveEvent` is the parent for all events that cause changes to the structure of the tree or to the node's value.\n\n#### NodeSelectedEvent\n\nYou can subscribe to the `NodeSelectedEvent` by attaching listener to the `(nodeSelected)` attribute\n\n```html\n    \u003ctree\n      [tree]=\"tree\"\n      (nodeSelected)=\"handleSelected($event)\"\u003e\n    \u003c/tree\u003e\n```\n\n`NodeSelectedEvent` has just one property `node` which contains a `Tree` object representing selected node.\n\n```typescript\n{node: \u003cTree\u003e{...}}\n```\n\n#### NodeMovedEvent\n\nYou can subscribe to `NodeMovedEvent` by attaching listener to `(nodeMoved)` attribute\n\n```html\n    \u003ctree\n      [tree]=\"tree\"\n      (nodeMoved)=\"handleMoved($event)\"\u003e\n    \u003c/tree\u003e\n```\n\n`NodeMovedEvent` has two properties `node` and `previousParent` both of which contain `Tree` objects:\n\n* `node` contains a moved node;\n* `previousParent` contains a previous parent of the moved node;\n\n```typescript\n{node: \u003cTree\u003e{...}, previousParent: \u003cTree\u003e{...}}\n```\n\n#### NodeRemovedEvent\n\nYou can subscribe to `NodeRemovedEvent` by attaching listener to `(nodeRemoved)` attribute\n\n```html\n    \u003ctree\n      [tree]=\"tree\"\n      (nodeRemoved)=\"handleRemoved($event)\"\u003e\n    \u003c/tree\u003e\n```\n\n`NodeRemovedEvent` has a `node` property, which contains removed node (of type `Tree`).\n\n```typescript\n{node: \u003cTree\u003e{...}}\n```\n\n#### NodeCreatedEvent\n\nYou can subscribe to `NodeCreatedEvent` by attaching listener to `(nodeCreated)` attribute\n\n```html\n    \u003ctree\n      [tree]=\"tree\"\n      (nodeCreated)=\"handleCreated($event)\"\u003e\n    \u003c/tree\u003e\n```\n\n`NodeCreatedEvent` has a `node` property of type `Tree`, which contains a created node and a `controller` property, which will give you access to node's controller.\n\n```typescript\n{node: \u003cTree\u003e{...}}\n```\n\n#### NodeRenamedEvent\n\nYou can subscribe to `NodeRenamedEvent` by attaching listener to `(nodeRenamed)` attribute\n\n```html\n    \u003ctree\n      [tree]=\"tree\"\n      (nodeRenamed)=\"handleRenamed($event)\"\u003e\n    \u003c/tree\u003e\n```\n\n`NodeRenamedEvent` has three properties:\n\n* `node` contains a node that was renamed ( an instance of `Tree`).\n* `oldValue` contains a value, that node used to have (it might be `string` or `RenamableNode`)\n* `newValue` contains a new value of the node (it might be `string` or `RenamableNode`)\n\n```typescript\n{\n  node: \u003cTree\u003e{...},\n  oldValue: \u003cstring|RenamableNode\u003e{...},\n  newValue: \u003cstring|RenamableNode\u003e{...}\n}\n```\n\n#### NodeExpandedEvent\n\nYou can subscribe to `NodeExpandedEvent` by attaching listener to `(nodeExpanded)` attribute, this event wont fire on initial expansion\n\n```html\n    \u003ctree\n      [tree]=\"tree\"\n      (nodeExpanded)=\"handleExpanded($event)\"\u003e\n    \u003c/tree\u003e\n```\n\n`NodeExpandedEvent` has a `node` property of type `Tree`, which contains an expanded node.\n\n```typescript\n{node: \u003cTree\u003e{...}}\n```\n\n#### NodeCollapsedEvent\n\nYou can subscribe to `NodeCollapsedEvent` by attaching listener to `(nodeCollapsed)` attribute\n\n```html\n    \u003ctree\n      [tree]=\"tree\"\n      (nodeCollapsed)=\"handleCollapsed($event)\"\u003e\n    \u003c/tree\u003e\n```\n\n`NodeCollapsedEvent` has a `node` property of type `Tree`, which contains a collapsed node.\n\n```typescript\n{node: \u003cTree\u003e{...}}\n```\n\n#### LoadNextLevelEvent\n\nYou can subscribe to `LoadNextLevelEvent` by attaching a listener to `(loadNextLevel)` attribute.\nRelevant for loading children via ngrx (or any redux-inspired library).\n\n```html\n    \u003ctree\n      [tree]=\"tree\"\n      (loadNextLevel)=\"handleNextLevel($event)\"\u003e\n    \u003c/tree\u003e\n```\n\n`LoadNextLevelEvent` has a `node` property of the type `Tree`, which contains a node for which next level (its children) should be loaded.\n\n```typescript\n{node: \u003cTree\u003e{...}}\n```\n\n## :gun: Controller\n\nFirst of all you should know how to get a controller of a particular node. You can get a controller of a node only if you set an id property of a node.\n\n\u003e TIP: Ids for nodes created via the context menu or using a TreeController instance get populated automatically unless nodes had ids before there were added to the tree\n\nFor example, your tree structure should look like:\n\n```typescript\npublic tree: TreeModel = {\n    value: 'Programming languages by programming paradigm',\n    id: 1,\n    children: [\n      {\n        value: 'Object-oriented programming',\n        id: 2,\n        children: [\n          {value: 'Java', id: 3},\n          {value: 'C++', id: 4},\n          {value: 'C#', id 5},\n        ]\n      },\n      {\n        value: 'Prototype-based programming',\n        id: 6,\n        children: [\n          {value: 'JavaScript', id: 7},\n          {value: 'CoffeeScript', id: 8},\n          {value: 'Lua', id: 9},\n        ]\n      }\n    ]\n  };\n```\n\nIds must be unique within a one tree, otherwise, some controllers will be overwritten and you won't be able to acquire them.\nIn order to get a node's controller you need to create an Angular local variable out of tree component via hash binding in the template:\n\n```typescript\n@Component({\n  template: '\u003ctree [tree]=\"tree\" #treeComponent\u003e\u003c/tree\u003e'\n})\nclass TheComponent implements AfterViewInit {\n  tree: TreeModel = {\n    value: 'Programming languages by programming paradigm',\n    id: 1,\n    children: [\n      {\n        value: 'Object-oriented programming',\n        id: 2,\n        children: [\n          {value: 'Java', id: 3},\n          {value: 'C++', id: 4},\n          {value: 'C#', id 5},\n        ]\n      },\n      {\n        value: 'Prototype-based programming',\n        id: 6,\n        children: [\n          {value: 'JavaScript', id: 7},\n          {value: 'CoffeeScript', id: 8},\n          {value: 'Lua', id: 9},\n        ]\n      }\n    ]\n  };\n\n  @ViewChild('treeComponent') treeComponent;\n\n  ngAfterViewInit(): void {\n    // ... make use of this.treeComponent ...\n  }\n}\n```\n\nthen by executing `this.treeComponent.getControllerByNodeId(PUT_HERE_YOUR_NODE_ID)` you'll get an instance of a TreeController (another couple steps and the world is yours =) )\n\nBelow are more detailed explanations of the TreeController and its usage. Let's go method by method:\n\n```typescript\nconst oopNodeController = this.treeComponent.getControllerByNodeId(2);\n```\n\n#### select - selects a node\n\n```typescript\noopNodeController.select();\n```\n\nThis method selects the node and unselects all the other nodes, also it fires a select event.\n\n#### isSelected - checks whether a node is selected\n\n```typescript\noopNodeController.isSelected();\n```\n\nThis method returns true if the node is selected and false if it isn't.\n\n#### collapse - collapses a node\n\n```typescript\noopNodeController.collapse();\n```\n\nThis method collapses a node if the node is collapsible (for example we cannot collapse a leaf). If the node gets collapsed successfully - a collapse event gets fired.\n\n#### isCollapsed - check whether a node is collapsed\n\n```typescript\noopNodeController.isCollapsed();\n```\n\nThis method returns true if the node is collapsed and false otherwise.\n\n#### expand - expands a node\n\n```typescript\noopNodeController.expand();\n```\n\nThis method expands the node in case it can be expanded. On successful expanding the expand event is fired.\n\n#### expandToParent - expands a node and its parents up to the root\n\n```typescript\noopNodeController.expandToParent();\n```\n\nThis method expands the node even if it is a leaf. Expand event is fired for every expanded parent up to the root.\n\n**Important:** For this to work - `keepNodesInDOM: true` should be set on the appropriate tree.\n\n#### isExpanded - checks whether a node is expanded\n\n```typescript\noopNodeController.isExpanded();\n```\n\n#### toTreeModel - converts a tree to a TreeModel instance\n\nActually controller makes and returns a clone of tree's underlying model\n\n```typescript\noopNodeController.toTreeModel();\n```\n\nThis method returns true if the node is expanded and false otherwise.\n\n#### rename - renames a node (changes its value underneath)\n\n```typescript\noopNodeController.rename('new value');\n```\n\nThis method accepts a string and sets it as a node's new value, this action also fires rename event.\n\n#### startRenaming - changes the node template so that text input appears and lets a user type a new name\n\n```typescript\noopNodeController.startRenaming();\n```\n\nAfter the user entered the new name a rename event will be fired.\n\n#### remove - removes a node from the tree\n\n```typescript\noopNodeController.remove();\n```\n\nThis method removes the node and its children and fires remove event.\n\n#### addChild - creates a new child node\n\n```typescript\nlet newNode: TreeModel = {\n  value: 'Go',\n  children: []\n};\noopNodeController.addChild(newNode);\n```\n\nThis method accepts a TreeModel and adds it as a child of the parent or as a sibling (depends on which controller this was called - branch controller or a leaf controller).\n\n### changeNodeId - changes node's id\n\n```typescript\noopNodeController.changeNodeId(10);\n```\n\nThis method can change a node's id. When the user creates a node from node's menu you will access the new node after it's created and this method will provide a way to change the node's id.\n\n### reloadChildren - loads async children once more\n\n```typescript\noopNodeController.reloadChildren();\n```\n\n### setChildren - changes children of a node;\n\n```typescript\nlet newChildren: Array\u003cTreeModel\u003e = [\n  { value: 'new children 1' },\n  { value: 'new children 2' },\n  { value: 'new children 3' }\n];\noopNodeController.setChildren(newChildren);\n```\n\nThis method replaces all existing children of the node with new ones.\n\n## SystemJS\n\nIf you are using SystemJS, then you need\n\n```javascript\nSystem.config({\n    // ...\n    map: {\n      // ...\n      'ng2-tree': 'node_modules/ng2-tree/bundles/ng2-tree.umd.min.js',\n      // ...\n    },\n    // ...\n}\n```\n\n## Changes that should be taken into account in order to migrate from **ng2-tree V1** to **ng2-tree V2**\n\n* Events were reworked:\n  * In V1 all events that were inherited from NodeDestructiveEvent used to have property `parent`. It's not the case anymore. If you need a parent you should get it from `node` in event object like `node.parent`;\n  * All events used to have `node` property of type `TreeModel`. Now `node` is of type [Tree](#tree-class) (as well as `node.parent`);\n  * `NodeMovedEvent` now has property `previousParent`, which contains tree in which moved node used to be.\n* CSS styles in **ng2-tree V2** are distributed as separate file which you can find in `node_modules/ng2-tree/styles.css`. That allows you to override ng2-tree styles more easily.\n\n## :bulb: Want to help?\n\nI am very appreciate for your ideas, proposals and found bugs which you can put in [github issues](https://github.com/valor-software/ng2-tree/issues). Thanks in advance!\n\n**P.S.** If you find it hard going through the documentation, please, let me know which parts of it was difficult to grasp and I will improve them.\n","funding_links":[],"categories":["Uncategorized","Table of contents","UI Components","Awesome Angular [![Awesome TipeIO](https://img.shields.io/badge/Awesome%20Angular-@TipeIO-6C6AE7.svg)](https://github.com/gdi2290/awesome-angular) [![Awesome devarchy.com](https://img.shields.io/badge/Awesome%20Angular-@devarchy.com-86BDC1.svg)](https://github.com/brillout/awesome-angular-components)"],"sub_categories":["Uncategorized","Third Party Components","Tree","Angular \u003ca id=\"angular\"\u003e\u003c/a\u003e"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvalor-software%2Fng2-tree","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvalor-software%2Fng2-tree","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvalor-software%2Fng2-tree/lists"}