Let's make a reusable tree view component in Angular

I am developing several Angular libraries, so I love making simple and easily reusable solutions for developers. Recently, one of my Twitter followers asked me how to make a component that would display its data in a hierarchical tree - tree view. 

I love these kinds of problems because they provide an opportunity to cover many different use cases with a minimum amount of logic inside. In this article, I will describe how I think when I solve such problems.

Disclaimer: This tutorial is intended for an audience of Angular learners. If you understand how to make a recursive type, a recursive component and convert the data passed by the handler function in it, you can skip it.

So what do we need?

, . ?

: , . , .

TypeScript:

export type MultidimensionalArray<string> =
| string
| ReadonlyArray<MultidimensionalArray<string>>;

TypeScript recursive type references :

readonly items: MultidimensionalArray<string> = [
    "Hello",
    ["here", "is", ["some", "structured"], "Data"],
    "Bye"
];

(«» («» («» …)))… !

, ? . , , , .

. TypeScript generics:

export type MultidimensionalArray<T> =
| T
| ReadonlyArray<MultidimensionalArray<T>>;

- !

Angular-

Angular . tree view, , .

tree view:

, isArray , HostBinding, .

@Component({
    selector: "m-dimensional-view",
    templateUrl: "./m-dimensional-view.template.html",
    styleUrls: ["./m-dimensional-view.styles.less"],
    changeDetection: ChangeDetectionStrategy.OnPush
})
export class MultidimensionalViewComponent<T> {
    @Input()
    value: MultidimensionalArray<T> = [];

    @HostBinding("class._array")
    get isArray(): boolean {
        return Array.isArray(this.value);
    }
}

isArray- *ngIf

, *ngFor m-dimensional-view , — . 

, , . 

<ng-container *ngIf="isArray; else itemView">
<m-dimensional-view
    *ngFor="let item of value"
    [value]="item"
></m-dimensional-view>
</ng-container>
<ng-template #itemView>
    {{ value }}
</ng-template>

, , .

:host {
    display: block;

    &._array {
      margin-left: 20px;
    }
}

margin-left , LESS

, :

toString ( {{value}} ).

, , toString-. , [object Object]

 

— -. , - . : « ?».

:

@Component({})
export class MultidimensionalViewComponent<T> {
    // ...

    @Input()
    stringify: (item: T) => string = (item: T) => String(item);

    // ...
}

, . String.

:

<ng-container *ngIf="isArray; else itemView">
<m-dimensional-view
  *ngFor="let item of value"
  [stringify]="stringify"
  [value]="item"
></m-dimensional-view>
</ng-container>
<ng-template #itemView>
   {{stringify(value)}}
</ng-template>

stringify , , .

. : , , , .

: Stackblitz

Waterplea CSS-, :

?

ng-polymorheus. , .

ng-polymorheus:

npm i @tinkoff/ng-polymorpheus

«», «», «», «». :

import { PolymorpheusContent } from "@tinkoff/ng-polymorpheus";

// ...

@Component({
  selector: "m-dimensional-view",
  templateUrl: "./m-dimensional-view.template.html",
  styleUrls: ["./m-dimensional-view.styles.less"],
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class MultidimensionalViewComponent<T> {
  @Input()
  value: MultidimensionalArray<T> = [];

  @Input()
  content: PolymorpheusContent = "";

  @HostBinding("class._array")
  get isArray(): boolean {
    return Array.isArray(this.value);
  }
}

stringify polymorpheus-outlet. . , . — , , context .

. :

readonly itemsWithIcons: MultidimensionalArray<Node> = [
    {
      title: "Documents",
      icon: "https://www.flaticon.com/svg/static/icons/svg/210/210086.svg"
    },
    [
      {
        title: "hello.doc",
        icon: "https://www.flaticon.com/svg/static/icons/svg/2306/2306060.svg"
      },
      {
        title: "table.csv",
        icon: "https://www.flaticon.com/svg/static/icons/svg/2306/2306046.svg"
      }
    ]
];

polymorheus , :

<m-dimensional-view
    [value]="itemsWithIcons"
    [content]="itemView"
></m-dimensional-view>

<ng-template #itemView let-icon="icon" let-title="title">
    <img alt="icon" width="16" [src]="icon" />
    {{title}}
</ng-template>

, tree view . let-icon , ng-template. :

ng-polymorheus: Stackblitz

, , HTML. , , , .

, , , .




All Articles