Hagamos un componente de vista de árbol reutilizable en Angular

Estoy desarrollando varias bibliotecas angulares, así que me encanta crear soluciones simples y fácilmente reutilizables para desarrolladores. Recientemente, uno de los seguidores de Twitter me preguntó cómo hacer un componente que mostrara sus datos en una vista de árbol jerárquica. 

Me encantan este tipo de problemas porque brindan la oportunidad de cubrir muchos casos de uso diferentes con una cantidad mínima de lógica interna. En este artículo, describiré cómo pienso cuando resuelvo tales problemas.

Descargo de responsabilidad: este tutorial está destinado a una audiencia de estudiantes de Angular. Si comprende cómo hacer un tipo recursivo, un componente recursivo y convertir los datos pasados ​​por la función del controlador en él, puede omitirlo.

Entonces, ¿qué necesitamos?

, . ?

: , . , .

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