لنقم بإنشاء مكون عرض شجرة قابل لإعادة الاستخدام في 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