{"id":275926,"date":"2016-03-11T13:15:03","date_gmt":"2016-03-11T10:15:03","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=275926"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=275926","title":{"rendered":"\u041f\u0438\u0448\u0443 TreeView \u043d\u0430 Angular 2"},"content":{"rendered":"<p>       \u0412\u0434\u043e\u0445\u043d\u043e\u0432\u0438\u0432\u0448\u0438\u0441\u044c \u0441\u0442\u0430\u0442\u044c\u0435\u0439 <a href=\"https:\/\/habrahabr.ru\/post\/278523\/\">\u00ab\u041f\u043e\u0440\u043e\u0433 \u0432\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f \u0432 Angular 2 \u2014 \u0442\u0435\u043e\u0440\u0438\u044f \u0438 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0430\u00bb<\/a>, \u0440\u0435\u0448\u0438\u043b \u0442\u043e\u0436\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0441\u0442\u0430\u0442\u044c\u044e \u043f\u0440\u043e \u0441\u0432\u043e\u0438 \u043c\u0443\u043a\u0438 \u0442\u0432\u043e\u0440\u0447\u0435\u0441\u0442\u0432\u0430.<\/p>\n<p>  \u0423 \u043c\u0435\u043d\u044f \u0435\u0441\u0442\u044c \u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u043f\u0440\u043e\u0435\u043a\u0442, \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0439 \u043d\u0430 ASP.NET WebForms. \u0412 \u043d\u0435\u043c \u043d\u0430\u043c\u0435\u0448\u0430\u043d\u043e \u043c\u043d\u043e\u0433\u043e \u0432\u0441\u044f\u043a\u043e\u0433\u043e, \u0438 \u043f\u043e\u0441\u0442\u0435\u043f\u0435\u043d\u043d\u043e \u043c\u043d\u0435 \u044d\u0442\u043e \u0432\u0441\u0451 \u043f\u0435\u0440\u0435\u0441\u0442\u0430\u043b\u043e \u043d\u0440\u0430\u0432\u0438\u0442\u044c\u0441\u044f. \u0420\u0435\u0448\u0438\u043b \u044f \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u043f\u0435\u0440\u0435\u043f\u0438\u0441\u0430\u0442\u044c \u0432\u0441\u0451 \u043d\u0430 \u0447\u0435\u043c-\u043d\u0438\u0431\u0443\u0434\u044c \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u043c. Angular 2 \u043c\u043d\u0435 \u043f\u0440\u0438\u0433\u043b\u044f\u043d\u0443\u043b\u0441\u044f \u0441\u0440\u0430\u0437\u0443, \u0438 \u044f \u0440\u0435\u0448\u0438\u043b \u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e. \u0417\u0430\u0434\u0430\u0447\u0430 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043b\u0430\u0441\u044c \u0442\u0430\u043a\u0430\u044f: \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043d\u043e\u0432\u044b\u0439 frontend, \u043f\u0440\u0438\u043a\u0440\u0443\u0442\u0438\u0432 \u0435\u0433\u043e \u043a \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u043c\u0443 backend, \u0441 \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u043c\u0438 \u043f\u0435\u0440\u0435\u0434\u0435\u043b\u043a\u0430\u043c\u0438 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0433\u043e. \u041d\u043e\u0432\u044b\u0439 frontend \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c UI-\u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u044b\u043c \u0441\u043e \u0441\u0442\u0430\u0440\u044b\u043c, \u0447\u0442\u043e\u0431\u044b \u043a\u043e\u043d\u0435\u0447\u043d\u044b\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0437\u0430\u043c\u0435\u0442\u0438\u043b.<\/p>\n<p>  \u0418\u0442\u043e\u0433\u043e \u0438\u043c\u0435\u0435\u043c \u0442\u0430\u043a\u043e\u0439 \u0441\u0442\u044d\u043a: backend \u2014 ASP.NET Web API, Entity Framework, MS SQL; frontend \u2014 Angular 2; \u0442\u0435\u043c\u0430 Bootstrap 3.<\/p>\n<p>  \u0421\u0440\u0430\u0437\u0443 \u043f\u043e\u043a\u0430\u0436\u0443 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 TreeView:<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/files\/be5\/0c0\/675\/be50c067579a40c1a99cda75f0c7c80e.png\" alt=\"image\"\/><br \/>  <a name=\"habracut\"><\/a><br \/>  \u041f\u0440\u043e\u0446\u0435\u0441\u0441 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 Angular 2 \u0432 Visual Studio \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u043d\u0435 \u0431\u0443\u0434\u0443, \u043d\u0430 \u043f\u0440\u043e\u0441\u0442\u043e\u0440\u0430\u0445 \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u043b\u043d\u043e. \u0415\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0435, \u0447\u0442\u043e \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c, \u044d\u0442\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0443 \u0432 web.config \u0434\u043b\u044f \u0440\u0435\u0434\u0438\u0440\u0435\u043a\u0442\u0430 route-\u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043d\u0430 index.html:<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u043a\u0443\u0441\u043e\u043a web.config<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"xml\">&lt;system.webServer&gt; \t  &lt;modules runAllManagedModulesForAllRequests=&quot;true&quot;\/&gt; \t  &lt;rewrite&gt; \t\t  &lt;rules&gt; \t\t\t  &lt;rule name=&quot;IndexRule&quot; stopProcessing=&quot;true&quot;&gt; \t\t\t\t  &lt;match url=&quot;.*&quot;\/&gt; \t\t\t\t  &lt;conditions logicalGrouping=&quot;MatchAll&quot;&gt; \t\t\t\t\t  &lt;add input=&quot;{REQUEST_FILENAME}&quot; matchType=&quot;IsFile&quot; negate=&quot;true&quot;\/&gt; \t\t\t\t\t  &lt;add input=&quot;{REQUEST_URI}&quot; matchType=&quot;Pattern&quot; pattern=&quot;^\/api\/&quot; negate=&quot;true&quot;\/&gt; \t\t\t\t  &lt;\/conditions&gt; \t\t\t\t  &lt;action type=&quot;Rewrite&quot; url=&quot;\/index.html&quot;\/&gt; \t\t\t  &lt;\/rule&gt; \t\t  &lt;\/rules&gt; \t  &lt;\/rewrite&gt; &lt;\/system.webServer&gt; <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0412\u0441\u0435 \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0432\u0437\u043b\u0435\u0442\u0435\u043b\u043e. \u0421\u0442\u0430\u0442\u0438\u043a \u0444\u0430\u0439\u043b\u044b \u0433\u0440\u0443\u0437\u044f\u0442\u0441\u044f \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e, api \u043e\u0442\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u044e\u0442 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u044b web api, \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u044b \u0432\u0441\u0435\u0433\u0434\u0430 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 index.html.<\/p>\n<p>  \u041f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u043d\u0430\u0447\u0438\u043d\u0430\u0442\u044c \u043f\u0438\u0441\u0430\u0442\u044c \u043a\u043e\u043d\u0435\u0447\u043d\u044b\u0435 \u0442\u043e\u0447\u043a\u0438, \u0440\u0435\u0448\u0438\u043b \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044b-\u0430\u043d\u0430\u043b\u043e\u0433\u0438 WebForm&#8217;s. \u0427\u0430\u0449\u0435 \u0432\u0441\u0435\u0433\u043e \u043a\u043e\u043d\u0435\u0447\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f ListView \u0438 FormView. \u041d\u043e \u043d\u0430\u0447\u0430\u0442\u044c \u044f \u0440\u0435\u0448\u0438\u043b \u0441 \u043f\u0440\u043e\u0441\u0442\u0435\u043d\u044c\u043a\u043e\u0433\u043e TreeView, \u043e\u043d \u0442\u043e\u0436\u0435 \u043d\u0443\u0436\u0435\u043d \u0432 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0444\u043e\u0440\u043c\u0430\u0445.<\/p>\n<p>  \u0414\u043b\u044f \u0443\u043c\u0435\u043d\u044c\u0448\u0435\u043d\u0438\u044f \u0442\u0440\u0430\u0444\u0438\u043a\u0430 \u0440\u0435\u0448\u0438\u043b \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0445 \u0443\u0437\u043b\u043e\u0432 \u0434\u0435\u0440\u0435\u0432\u0430. \u041f\u0440\u0438 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u044e \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u0435\u0440\u0445\u043d\u0438\u0439 \u0443\u0440\u043e\u0432\u0435\u043d\u044c. <\/p>\n<p>  \u041f\u0440\u0438 \u0440\u0430\u0441\u043a\u0440\u044b\u0442\u0438\u0438 \u0443\u0437\u043b\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u043f\u043e\u0442\u043e\u043c\u043a\u043e\u0432, \u043f\u0440\u0438 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0438 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c \u0441\u043e\u0431\u044b\u0442\u0438\u0435 onRequestNodes. \u041f\u0440\u0438 \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u0438\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u043c \u0443\u0437\u043b\u0430 \u2014 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c \u0441\u043e\u0431\u044b\u0442\u0438\u0435 onSelectedChanged. \u0418\u043a\u043e\u043d\u043a\u0438 fontawesome.<\/p>\n<p>  \u041a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0438\u043c\u0435\u0435\u0442 \u0434\u0432\u0430 \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0445 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430: Nodes \u2014 \u0441\u043f\u0438\u0441\u043e\u043a \u0443\u0437\u043b\u043e\u0432 \u043d\u0430 \u0434\u0430\u043d\u043d\u043e\u043c \u0443\u0440\u043e\u0432\u043d\u0435, SelectedNode \u2014 \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u043c \u0443\u0437\u0435\u043b. \u0414\u0432\u0430 \u0441\u043e\u0431\u044b\u0442\u0438\u044f: onSelectedChanged \u2014 \u0441\u043c\u0435\u043d\u0430 \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u043c \u0443\u0437\u043b\u0430, onRequestNodes \u2014 \u0437\u0430\u043f\u0440\u043e\u0441 \u0443\u0437\u043b\u043e\u0432, \u043f\u0440\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438.  @Input \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u044f\u044e\u0442\u0441\u044f \u043e\u0442 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044f \u043a \u043f\u043e\u0442\u043e\u043c\u043a\u0430\u043c (\u0432\u0433\u043b\u0443\u0431\u044c \u0438\u0435\u0440\u0430\u0440\u0445\u0438\u0438).  @Output() \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0430\u043d\u044f\u044e\u0442\u0441\u044f \u043e\u0442 \u043f\u043e\u0442\u043e\u043c\u043a\u043e\u0432 \u043a \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044f\u043c (\u043d\u0430\u0440\u0443\u0436\u0443 \u0438\u0435\u0440\u0430\u0440\u0445\u0438\u0438). \u041a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u044b\u0439 \u2014 \u043a\u0430\u0436\u0434\u044b\u0439 \u043d\u043e\u0432\u044b\u0439 \u0443\u0440\u043e\u0432\u0435\u043d\u044c \u0438\u0435\u0440\u0430\u0440\u0445\u0438\u0438 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u0441\u0432\u043e\u0439 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430.<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">treeview.component.ts<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"javascript\">import {Component, Input, Output, EventEmitter} from 'angular2\/core';  export interface ITreeNode { \tid: number; \tname: string; \tchildren: Array&lt;ITreeNode&gt;; }  @Component({ \tselector: &quot;tree-view&quot;, \ttemplateUrl: &quot;\/app\/components\/treeview\/treeview.html&quot;, \tdirectives: [TreeViewComponent] }) export class TreeViewComponent {  \t@Input() Nodes: Array&lt;ITreeNode&gt;; \t@Input() SelectedNode: ITreeNode;  \t@Output() onSelectedChanged: EventEmitter&lt;ITreeNode&gt; = new EventEmitter(); \t@Output() onRequestNodes: EventEmitter&lt;ITreeNode&gt; = new EventEmitter();  \tconstructor() { }  \tonSelectNode(node: ITreeNode) { \t\tthis.onSelectedChanged.emit(node); \t}  \tonExpand(li: HTMLLIElement, node: ITreeNode) { \t\tif (this.isExpanden(li)) { \t\t\tli.classList.remove('expanded'); \t\t} \t\telse { \t\t\tli.classList.add('expanded');  \t\t\tif (node.children.length == 0) { \t\t\t\tthis.onRequest(node); \t\t\t} \t\t} \t}  \tonRequest(parent: ITreeNode) { \t\tthis.onRequestNodes.emit(parent); \t}  \tisExpanden(li: HTMLLIElement) { \t\treturn li.classList.contains('expanded'); \t} } <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">treeview.html<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"html\">&lt;ul class=&quot;treenodes&quot;&gt; \t&lt;li #li *ngFor=&quot;#node of Nodes&quot; class=&quot;treenode&quot;&gt; \t\t&lt;i class=&quot;nodebutton fa&quot; \t\t   (click)=&quot;onExpand(li, node)&quot; \t\t   [ngClass]=&quot;{'fa-minus-square-o': isExpanden(li), 'fa-plus-square-o': !isExpanden(li)}&quot;&gt; \t\t&lt;\/i&gt;  \t\t&lt;span class=&quot;nodetext&quot; \t\t\t  [ngClass]=&quot;{'bg-info': node == SelectedNode}&quot; \t\t\t  (click)=&quot;onSelectNode(node)&quot;&gt; \t\t\t{{node.name}} \t\t&lt;\/span&gt;  \t\t&lt;tree-view [Nodes]=&quot;node.children&quot; \t\t\t\t   [SelectedNode]=&quot;SelectedNode&quot; \t\t\t\t   (onSelectedChanged)=&quot;onSelectNode($event)&quot; \t\t\t\t   (onRequestNodes)=&quot;onRequest($event)&quot; \t\t\t\t   *ngIf=&quot;isExpanden(li)&quot;&gt; \t\t&lt;\/tree-view&gt; \t&lt;\/li&gt; &lt;\/ul&gt; <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0421\u0442\u0438\u043b\u0438 \u0441\u0434\u0435\u043b\u0430\u043b \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u043c \u0444\u0430\u0439\u043b\u043e\u043c.<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">treeview.css<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"css\">tree-view .treenodes { \tlist-style-type: none; \tpadding-left: 0; }  tree-view tree-view .treenodes { \tlist-style-type: none; \tpadding-left: 16px; }  tree-view .nodebutton { \tcursor: pointer; }  tree-view .nodetext { \tpadding-left: 3px; \tpadding-right: 3px; \tcursor: pointer; } <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u041a\u0430\u043a \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c:<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">sandbox.component.ts<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"javascript\">import {Component, OnInit} from 'angular2\/core'; import {NgClass} from 'angular2\/common'; import {TreeViewComponent, ITreeNode} from '..\/treeview\/treeview.component'; import {TreeService} from '..\/..\/services\/tree.service';  @Component({ \ttemplateUrl: '\/app\/components\/sandbox\/sandbox.html', \tdirectives: [NgClass, TreeViewComponent] }) export class SandboxComponent implements OnInit {  \tNodes: Array&lt;ITreeNode&gt;; \tselectedNode: ITreeNode; \/\/ \u043d\u0443\u0436\u0435\u043d \u0434\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0434\u0435\u0442\u0430\u043b\u044c\u043d\u043e\u0439 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043f\u043e \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u043c\u0443 \u0443\u0437\u043b\u0443.  \tconstructor(private treeService: TreeService) { \t}  \t\/\/ \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u0435 \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0432\u0435\u0440\u0445\u043d\u0435\u0433\u043e \u0443\u0440\u043e\u0432\u043d\u044f \u0438\u0435\u0440\u0430\u0440\u0445\u0438\u0438 \tngOnInit() { \t\tthis.treeService.GetNodes(0).subscribe( \t\t\tres =&gt; this.Nodes = res, \t\t\terror =&gt; console.log(error) \t\t); \t} \t\/\/ \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u0441\u043c\u0435\u043d\u044b \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u0433\u043e \u0443\u0437\u043b\u0430 \tonSelectNode(node: ITreeNode) { \t\tthis.selectedNode = node; \t} \t\/\/ \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0445 \u0443\u0437\u043b\u043e\u0432 \tonRequest(parent: ITreeNode) { \t\tthis.treeService.GetNodes(parent.id).subscribe( \t\t\tres =&gt; parent.children = res, \t\t\terror=&gt; console.log(error)); \t} } <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">sandbox.html<\/b><\/p>\n<div class=\"spoiler_text\">\u041d\u0430\u043f\u043e\u043c\u0438\u043d\u0430\u044e, \u0443 \u043c\u0435\u043d\u044f bootstrap 3.<\/p>\n<pre><code class=\"html\">&lt;div class=&quot;col-lg-3&quot;&gt; \t&lt;div class=&quot;panel panel-info&quot;&gt; \t\t&lt;div class=&quot;panel-body&quot;&gt; \t\t\t&lt;tree-view [Nodes]=&quot;Nodes&quot; \t\t\t\t\t   [SelectedNode]=&quot;selectedNode&quot; \t\t\t\t\t   (onSelectedChanged)=&quot;onSelectNode($event)&quot; \t\t\t\t\t   (onRequestNodes)=&quot;onRequest($event)&quot;&gt; \t\t\t&lt;\/tree-view&gt; \t\t&lt;\/div&gt; \t&lt;\/div&gt; &lt;\/div&gt; <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">tree.service.ts<\/b><\/p>\n<div class=\"spoiler_text\">\u0421\u0430\u043c\u044b\u0439 \u043f\u0440\u0438\u043c\u0438\u0442\u0438\u0432\u043d\u044b\u0439 \u0441\u0435\u0440\u0432\u0438\u0441  <\/p>\n<pre><code class=\"javascript\">import {Injectable} from 'angular2\/core'; import {Http} from 'angular2\/http'; import 'rxjs\/Rx';  @Injectable() export class TreeService { \tconstructor(public http: Http) {  \t} \tGetNodes(parentId: number) { \t\treturn this.http.get(&quot;\/api\/tree\/&quot; + parentId.toString()) \t\t\t.map(res=&gt; res.json()); \t} } <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u041f\u043e\u043b\u0443\u0447\u0438\u043b\u0441\u044f \u0432\u043e\u0442 \u0442\u0430\u043a\u043e\u0439 \u00ab\u043a\u0430\u0440\u043a\u0430\u0441\u00bb treeview. \u0412 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u043c \u043c\u043e\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u0434\u043b\u044f \u0438\u043a\u043e\u043d\u043e\u043a, \u0434\u043b\u044f \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u0438\u044f, \u0447\u0442\u043e\u0431\u044b \u043e\u0442\u0432\u044f\u0437\u0430\u0442\u044c treeview \u043e\u0442 bootstrap 3.<\/p>\n<p>  Backend \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u043d\u0435 \u0431\u0443\u0434\u0443, \u0442\u0430\u043c \u043d\u0438\u0447\u0435\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e\u0433\u043e, \u043e\u0431\u044b\u0447\u043d\u044b\u0439 web api \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440 \u0438 entity framework.<\/p>\n<p>  \u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043f\u043e\u0434\u043e\u043f\u044b\u0442\u043d\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 asp:ListView. \u0412 \u043c\u043e\u0451\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u043e\u043d \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043f\u043e\u0432\u0441\u044e\u0434\u0443 \u0438 \u043f\u043e \u0432\u0441\u044f\u043a\u043e\u043c\u0443. \u0421 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u043c\u0438 Insert, Update templates \u0438 \u0431\u0435\u0437, \u0441 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0439 \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u043e\u0439, \u0441 \u043f\u0435\u0439\u0434\u0436\u0438\u043d\u0433\u043e\u043c, \u0441 \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u043c\u0438\u2026<\/p>\n<p>  \u0413\u043e\u0442\u043e\u0432 \u043a \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u0438\u0432\u043d\u043e\u0439 \u043a\u0440\u0438\u0442\u0438\u043a\u0435.       <\/p>\n<div class=\"clear\"><\/div>\n<p> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habrahabr.ru\/post\/279045\/\"> https:\/\/habrahabr.ru\/post\/279045\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>       \u0412\u0434\u043e\u0445\u043d\u043e\u0432\u0438\u0432\u0448\u0438\u0441\u044c \u0441\u0442\u0430\u0442\u044c\u0435\u0439 <a href=\"https:\/\/habrahabr.ru\/post\/278523\/\">\u00ab\u041f\u043e\u0440\u043e\u0433 \u0432\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f \u0432 Angular 2 \u2014 \u0442\u0435\u043e\u0440\u0438\u044f \u0438 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0430\u00bb<\/a>, \u0440\u0435\u0448\u0438\u043b \u0442\u043e\u0436\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0441\u0442\u0430\u0442\u044c\u044e \u043f\u0440\u043e \u0441\u0432\u043e\u0438 \u043c\u0443\u043a\u0438 \u0442\u0432\u043e\u0440\u0447\u0435\u0441\u0442\u0432\u0430.<\/p>\n<p>  \u0423 \u043c\u0435\u043d\u044f \u0435\u0441\u0442\u044c \u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u043f\u0440\u043e\u0435\u043a\u0442, \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0439 \u043d\u0430 ASP.NET WebForms. \u0412 \u043d\u0435\u043c \u043d\u0430\u043c\u0435\u0448\u0430\u043d\u043e \u043c\u043d\u043e\u0433\u043e \u0432\u0441\u044f\u043a\u043e\u0433\u043e, \u0438 \u043f\u043e\u0441\u0442\u0435\u043f\u0435\u043d\u043d\u043e \u043c\u043d\u0435 \u044d\u0442\u043e \u0432\u0441\u0451 \u043f\u0435\u0440\u0435\u0441\u0442\u0430\u043b\u043e \u043d\u0440\u0430\u0432\u0438\u0442\u044c\u0441\u044f. \u0420\u0435\u0448\u0438\u043b \u044f \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u043f\u0435\u0440\u0435\u043f\u0438\u0441\u0430\u0442\u044c \u0432\u0441\u0451 \u043d\u0430 \u0447\u0435\u043c-\u043d\u0438\u0431\u0443\u0434\u044c \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u043c. Angular 2 \u043c\u043d\u0435 \u043f\u0440\u0438\u0433\u043b\u044f\u043d\u0443\u043b\u0441\u044f \u0441\u0440\u0430\u0437\u0443, \u0438 \u044f \u0440\u0435\u0448\u0438\u043b \u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e. \u0417\u0430\u0434\u0430\u0447\u0430 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043b\u0430\u0441\u044c \u0442\u0430\u043a\u0430\u044f: \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043d\u043e\u0432\u044b\u0439 frontend, \u043f\u0440\u0438\u043a\u0440\u0443\u0442\u0438\u0432 \u0435\u0433\u043e \u043a \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u043c\u0443 backend, \u0441 \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u043c\u0438 \u043f\u0435\u0440\u0435\u0434\u0435\u043b\u043a\u0430\u043c\u0438 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0433\u043e. \u041d\u043e\u0432\u044b\u0439 frontend \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c UI-\u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u044b\u043c \u0441\u043e \u0441\u0442\u0430\u0440\u044b\u043c, \u0447\u0442\u043e\u0431\u044b \u043a\u043e\u043d\u0435\u0447\u043d\u044b\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0437\u0430\u043c\u0435\u0442\u0438\u043b.<\/p>\n<p>  \u0418\u0442\u043e\u0433\u043e \u0438\u043c\u0435\u0435\u043c \u0442\u0430\u043a\u043e\u0439 \u0441\u0442\u044d\u043a: backend \u2014 ASP.NET Web API, Entity Framework, MS SQL; frontend \u2014 Angular 2; \u0442\u0435\u043c\u0430 Bootstrap 3.<\/p>\n<p>  \u0421\u0440\u0430\u0437\u0443 \u043f\u043e\u043a\u0430\u0436\u0443 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 TreeView:<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/files\/be5\/0c0\/675\/be50c067579a40c1a99cda75f0c7c80e.png\" alt=\"image\"\/>  <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-275926","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/275926","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=275926"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/275926\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=275926"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=275926"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=275926"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}