{"metadata":{"image":[],"title":"","description":""},"api":{"url":"","auth":"required","results":{"codes":[]},"settings":"","params":[]},"next":{"description":"","pages":[]},"title":"2-way binding to state","type":"basic","slug":"save-restore","excerpt":"","body":"You can control the tree state using 2-way binding.\nThe state includes the following:\n- expandedNodeIds - dictionary of node IDs to booleans\n- selectedLeafNodeIds - dictionary of node IDs to booleans\n- activeNodeIds - dictionary of node IDs to booleans\n- hiddenNodeIds - dictionary of node IDs to booleans\n- focusedNodeId - node ID\n\nYou can change the state reference and the tree will respond automatically, and also access the tree state at any time, as it is always updated via the 2-way binding.\n\nExample:\n[block:code]\n{\n \"codes\": [\n {\n \"code\": \"import { Component } from ':::at:::angular/core';\\nimport { ITreeState } from 'angular-tree-component';\\n\\[email protected]({\\n selector: 'app-saverestore',\\n template: `\\n <tree-root [(state)]=\\\"state\\\" [nodes]=\\\"nodes\\\"></tree-root>\\n <button (click)=\\\"collapseAll()\\\">collapse all</button>\\n <button (click)=\\\"hideFolders()\\\">hide folders</button>\\n `,\\n styles: []\\n})\\nexport class MyComponent {\\n state: ITreeState;\\n nodes = [\\n { id: 1, isFolder: true, name: 'folder1', children: [\\n { id: 2, name: 'file1', isFolder: false },\\n { id: 3, name: 'file2', isFolder: false }\\n ] },\\n { id: 4, isFolder: false, name: 'flatfile1' },\\n { id: 5, isFolder: false, name: 'flatfile2' }\\n ];\\n\\n collapseAll() {\\n this.state = {\\n ...this.state,\\n expandedNodeIds: {}\\n };\\n }\\n\\n hideFolders() {\\n const hiddenNodeIds = {};\\n\\n this.nodes.forEach((node) => {\\n if (node.isFolder) {\\n hiddenNodeIds[node.id] = true;\\n }\\n });\\n\\n this.state = {\\n ...this.state,\\n hiddenNodeIds\\n };\\n }\\n}\",\n \"language\": \"javascript\"\n }\n ]\n}\n[/block]\n\n[block:api-header]\n{\n \"title\": \"!important note\"\n}\n[/block]\nYou must have an 'id' property on the nodes in order for this to work. Otherwise - the tree will automatically generate internal IDs which change every time you change the nodes array.\n[block:api-header]\n{\n \"title\": \"Persist state to localstorage\"\n}\n[/block]\nThis example is using the 2 way binding to tree state to auto save & restore from localstorage:\n[block:code]\n{\n \"codes\": [\n {\n \"code\": \"<tree-root\\n\\t[(state)]=\\\"state\\\"\\n [nodes]=\\\"nodes\\\">\\n</tree-root>\\n\\nclass MyComponent {\\n get state() {\\n return localStorage.treeState && JSON.parse(localStorage.treeState);\\n }\\n set state(state) {\\n localStorage.treeState = JSON.stringify(state);\\n }\\n}\",\n \"language\": \"javascript\"\n }\n ]\n}\n[/block]\nDemo:\n[block:html]\n{\n \"html\": \"<iframe src=\\\"https://angular-tree-component.azurewebsites.net/#/save-restore\\\" width=\\\"100%\\\" height=\\\"300px\\\"></iframe>\\n\"\n}\n[/block]\n\n[block:html]\n{\n \"html\": \"<a href=\\\"https://github.com/CirclonGroup/angular-tree-component/blob/master/projects/example-app/src/app/save-restore/save-restore.component.ts\\\" target=\\\"_blank\\\">Source code for this demo</a>\"\n}\n[/block]\n\n[block:api-header]\n{\n \"title\": \"Using API\"\n}\n[/block]\nAlternatively, you can use `getState`, `setState` and `subscribe` on treeModel API.\n`subscribe` will callback a function every time state changes.\n[block:code]\n{\n \"codes\": [\n {\n \"code\": \"<tree-root\\n\\t#tree\\n (initialize)=\\\"onInit(tree)\\\"\\n [nodes]=\\\"nodes\\\">\\n</tree-root>\\n\\nclass MyComponent {\\n onInit(tree) {\\n if (localStorage.treeState) {\\n \\ttree.treeModel.setState(JSON.parse(localStorage.treeState);\\n }\\n tree.treeModel.subscribe((state) => {\\n localStorage.treeState = JSON.stringify(state);\\n });\\n }\\n}\",\n \"language\": \"javascript\"\n }\n ]\n}\n[/block]","updates":["5b68abe742c3b0000389972e","5dc898582944be00424550fa"],"order":6,"isReference":false,"hidden":false,"sync_unique":"","link_url":"","link_external":false,"_id":"5c27be9e2b75bd0045dc7461","category":{"sync":{"isSync":false,"url":""},"pages":[],"title":"Basic","slug":"getting-started","order":0,"from_sync":false,"reference":false,"_id":"5c27be9e2b75bd0045dc7458","version":"5c27be9e2b75bd0045dc7476","project":"5707c6875309d117006948d4","createdAt":"2017-07-15T07:28:09.870Z","__v":0},"project":"5707c6875309d117006948d4","user":"54d742a80771980d0052f4b5","parentDoc":null,"version":{"version":"8.2.0","version_clean":"8.2.0","codename":"","is_stable":true,"is_beta":false,"is_hidden":false,"is_deprecated":false,"categories":["5c27be9e2b75bd0045dc7458","5c27be9e2b75bd0045dc7459","5c27be9e2b75bd0045dc745a"],"_id":"5c27be9e2b75bd0045dc7476","project":"5707c6875309d117006948d4","__v":0,"forked_from":"5b65b08eb1906e000319f872","createdAt":"2018-03-23T13:06:33.352Z","releaseDate":"2018-03-23T13:06:33.352Z"},"createdAt":"2017-07-28T17:23:09.223Z","githubsync":"","__v":2}