让我们在Angular中创建一个可重用的树视图组件

我正在开发几个Angular库,因此我喜欢为开发人员提供简单且易于重用的解决方案。最近,我的一个Twitter关注者问我如何制作一个组件,该组件可以在树状树状视图中显示其数据。 

我喜欢这些类型的问题,因为它们提供了机会,以最少的内部逻辑覆盖许多不同的用例。在本文中,我将描述解决此类问题时的想法。

免责声明:本教程面向Angular学习者。如果您了解如何创建递归类型,递归组件并转换其中的处理函数传递的数据,则可以跳过它。

那我们需要什么?

, . ?

: , . , .

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