Mari kita membuat komponen tampilan pohon yang dapat digunakan kembali di Angular

Saya mengembangkan beberapa perpustakaan Angular, jadi saya suka membuat solusi yang sederhana dan mudah digunakan kembali untuk pengembang. Baru-baru ini, salah satu pengikut Twitter saya bertanya kepada saya bagaimana membuat komponen yang akan menampilkan datanya dalam tampilan hierarki pohon-pohon. 

Saya suka jenis masalah ini karena memberikan kesempatan untuk mencakup banyak kasus penggunaan berbeda dengan jumlah logika minimum di dalamnya. Dalam artikel ini, saya akan menjelaskan bagaimana saya berpikir ketika saya menyelesaikan masalah seperti itu.

Penafian: Tutorial ini ditujukan untuk audiens pelajar Angular. Jika Anda memahami cara membuat tipe rekursif, komponen rekursif dan mengonversi data yang dilewatkan oleh fungsi penangan di dalamnya, Anda dapat melewatinya.

Jadi apa yang kita butuhkan?

Pertama-tama, kita perlu memahami data apa yang akan kita gunakan. Apa yang menggambarkan struktur pohon seperti itu?

Di sini, hal pertama yang terlintas dalam pikiran adalah array multidimensi: jika kita bertemu dengan elemen di dalamnya, maka kita akan menunjukkannya. Jika kita menemukan array bersarang, kita menyelam satu tingkat di bawah.

Mari kita gambarkan tipe ini di 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