For convenience, all of this articleAngularAll versions are Angula2 or later for useAngular1/Angular.jsFor your reference

preface

Currently writing an Angular Markdown editor that requires a tree component to write the file system. Having used the Angular Material tree component before, I wanted to copy one. After all, importing Angular Material directly creates additional components that you don’t need, and implementing it yourself allows you to learn more about Angular.

introduce

I did a bit of research before writing this article and found that most of the Tree component implementations write the node template directly into the component, like the following

<! - the Tree component - >
<tree>
    <tree-node></tree-node>
</tree>
<! - TreeNode component - >
<tree-node>
    <! -- Contents of this node -->
    {{ nodeName }}
    <! -- Child node -->
    <tree-node *ngIf="hasChildren">
    </tree-node>
<tree-node>
Copy the code

The Tree component contains the TreeNode component, which implements the logic of recursive child nodes. This structure is good enough for my needs, but (due to obsessive-compulsive disorder) there is little reusability because the content of the node is already written into the TreeNode component. Then I thought of the Angular Material CdkTree. His structure is as follows

<tree dataSource="ds">
    <tree-node>
        <! -- Contents of this node -->
        {{ nodeName }}
        <! -- Child node exit -->
        <outlet></outlet>
    </tree-node>
</tree>
Copy the code

CdkTree saves the contents of
as a template, and then renders them recursively according to the data source. This allows us to change the contents of the Tree and TreeNode components without modifying them.

implementation

There are several decorators that you need to understand before implementing Angular, which should be familiar to anyone who has studied Angular.

  • @ViewChild– Queries the view for the first matched element
  • @ViewChildren– Queries all matched elements in the view
  • @ContentChild– Queries for the first matching element in the content of the component tag wrap
  • @ContentChildren– Queries all matched elements in the contents of the component label wrap

View: The Content defined in the component’s template, that is, the Content we wrote manually in xxx.component.html Content: the Content in the

and

tags of the Host element

An overview of

There are four important classes in the Tree component

  • @Component: TreeComponent
  • @Component: TreeNodeComponent
  • @Directive: TreeNodeOutletDirective
  • @Directive: TreeNodeDefDirective

TreeComponent

This component is the Tree component we implement to wrap the TreeNode

TreeNodeComponent

Tree node component, our custom template is written in this

TreeNodeOutletDirective

This directive sets the exit position of the child node

TreeNodeDefDirective

This directive defines the data required for each tree node, i.e. we use this directive to make the template available for each tree node

implementation

So let’s see what it looks like when it’s finished

<nb-tree [dataSource] ="fileTree">
    <nb-tree-node *nbTreeNodeDef="let data = data">
        <li>
          <span>{{ data.title }}</span>
        </li>
        <ul>
          <ng-container nbTreeNodeOutlet></ng-container>
        </ul>
    </nb-tree-node>
</nb-tree>
Copy the code

(Please ignore the NB in front of the label, this is just the default prefix.) We can see that the dataSource is set up on the tree component.

Then in the treeNodeDef directive we export the data object data. It was then used in the template {{data.title}}.

Finally, we set up the child node’s exit with the treeNodeOutlet directive on

. Too lazy to write internship in detail… Write it later. This article mainly provides a general tree component idea.

If you want to see the code, look at the end. There is a less-than-perfect tree component that I’m using in the Markdown editor I’m writing.

At the end

Github: Tree component link