Je développe plusieurs bibliothèques angulaires, donc j'aime créer des solutions simples et facilement réutilisables pour les développeurs. Récemment, un de mes abonnés Twitter m'a demandé comment créer un composant qui afficherait ses données dans une arborescence hiérarchique - arborescence.
J'adore ce genre de problèmes car ils permettent de couvrir de nombreux cas d'utilisation différents avec un minimum de logique à l'intérieur. Dans cet article, je décrirai comment je pense lorsque je résous de tels problèmes.
Avertissement: ce didacticiel est destiné à un public d'apprenants Angular. Si vous comprenez comment créer un type récursif, un composant récursif et convertir les données transmises par la fonction de gestionnaire qu'il contient, vous pouvez l'ignorer.
Alors, de quoi avons-nous besoin?
, . ?
: , . , .
TypeScript:
export type MultidimensionalArray<string> =
| string
| ReadonlyArray<MultidimensionalArray<string>>;
TypeScript recursive type references :
readonly items: MultidimensionalArray<string> = [
"Hello",
["here", "is", ["some", "structured"], "Data"],
"Bye"
];
(«» («» («» …)))… !
, ? . , , , .
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 , , .
. : , , , .
Waterplea CSS-, :
…
?
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. , , , .
, , , .