Winkelkomponenten mit Inline-Inhalt

Wenn Sie bei der Entwicklung auf Angular neue Komponenten erstellen, bemühen Sie sich, diese so zu erstellen, dass sie viele Male wiederverwendet werden können. Genau wie bei der Softwareentwicklung bemüht sich ein Programmierer, seinen Code so wiederverwendbar wie möglich zu machen. Gleichzeitig möchte ich Komponenten haben, die flexibel, aber nicht zu komplex sind.



Komponenten müssen in der Regel so dumm wie möglich sein, damit Wartung und Test einfacher sind. Gleichzeitig sind sie anpassbar und flexibel, sodass Sie sie viele Male wiederverwenden können und nicht mit Komponenten klonen müssen, die optisch und funktional ähnlich sind, sich jedoch in etwas unterscheiden. Oder fügen Sie den Komponenten keine Reihe von Parametern hinzu, die darauf basieren, ob ein Verhalten der Komponente aktiviert oder deaktiviert werden soll, die jedoch tatsächlich in 1 von 100 Fällen verwendet werden.

Es ist keine leichte Aufgabe, ein U-Boot zu bauen, das auf den Grund des blauen Meeres sinken sollte, ohne das Leben der Besatzung zu gefährden, und es dann zu modifizieren, bevor es durch den blauen Himmel fliegt.

Eine eckige Komponente ist die kleinste Einheit der Benutzeroberfläche, die eine einfache Aufgabe und nichts weiter ausführen sollte. Das Erstellen von Komponenten für alle Gelegenheiten ist eine schlechte Praxis. Daher müssen Sie einen Kompromiss zwischen Flexibilität und Einfachheit finden.

Angenommen, Sie möchten eine Komponente erstellen, die aus einer Art Wrapper besteht, in dem sich eine Kopfzeile und eine Art Schalter befinden, sowie ein Teil des Inhalts darunter. So etwas in der Art:



Die gesamte Komponente, die als Widget bezeichnet wird, ist grün umrandet. Der Kopfzeilenschalter ist rot und der Inhalt blau hervorgehoben. Angular ist ein unglaublich leistungsfähiges Framework, und die Erstellung einer Komponente, die der im Bild ähnelt, ist für Angular eine sehr triviale Aufgabe.

Was aber, wenn diese Komponente beispielsweise flexibler gestaltet wird, sodass sich der Inhalt in Abhängigkeit von den Parametern der Widget-Komponente ändert?

Sie können die externe Darstellung von Inhalten basierend auf dem Widget-Parameter auflösen, z. B. mithilfe der Strukturanweisung ngIf . Sie können zwischen verschiedenen Ansichten wechseln. Und wenn es zu viele Einreichungen gibt, können Sie eine andere ngSwitch- Strukturanweisung verwenden.

Und ob verschiedene Ansichten unterschiedlich auf Benutzeraktionen reagieren? Dann enthält der Komponentencode auch eine Reihe von bedingten Anweisungen. Aber der Code, in dem es viele bedingte Anweisungen gibt, wird im Laufe der Zeit schwierig zu warten, Fehler zu beheben oder die Funktionalität zu erweitern ...

Sie können eine Widget-Komponente so erstellen, dass sie beliebigen Inhalt empfängt, gleichzeitig aber die ausgewählten Werte des Filterbereichs in die Komponenten des Inhaltsbereichs wirft. Und ich möchte auch in der Lage sein, Parameter von der übergeordneten Komponente des Widgets an den Inhalt weiterzuleiten, ohne die Widget-Komponente selbst zu beeinflussen. Um dieses Problem zu lösen, können Sie die wunderbare Direktive ngTemplateOutlet verwenden , mit der Sie die visuelle Darstellung der Komponente „auflösen“ können. Weitere Informationen finden Sie in der Dokumentation , obwohl dort meiner Meinung nach nicht alle Möglichkeiten gezeigt werden.

In diesem Fall kann die Widget-Komponente wie folgt dargestellt werden:

// widget.component.ts … private widgetContentTemplate: TemplateRef<any>; //      @ContentChild(WidgetContentTemplateDirective, { read: TemplateRef }) set WidgetContentTemplate(value: TemplateRef<any>) { this.widgetContentTemplate = value; } get WidgetContentTemplate(): TemplateRef<any> { return this.widgetContentTemplate; } … 

 <!-- widget.component.html --><div class="widget__content"> <!--      ,      context.   ,     --> <ng-container *ngTemplateOutlet="WidgetContentTemplate || DefaultWidgetContentTemplate; context: { post: SelectedPost }"> </ng-container> </div> <ng-template #DefaultWidgetContentTemplate> <div>[    ]</div> </ng-template> 

Die Direktive ngTemplateOutlet akzeptiert ein TemplateRef-Objekt, das mit @ContentChild in die Komponente eingelesen wird. Dazu müssen Sie eine einfache Direktive erstellen. Hier ist ihr Code:

 // widget-content-template.directive.ts import { Directive, TemplateRef } from '@angular/core'; @Directive({ selector: '[appWidgetContentTemplate]' }) export class WidgetContentTemplateDirective { get Template(): TemplateRef<any> { return this.template; } constructor(private readonly template: TemplateRef<any>) {} } 

Parameter aus dem Widget-Schalter können mithilfe des Kontextobjekts an den Inhalt übergeben werden. Damit die Parameter aus dem Kontext von der Komponente korrekt gelesen werden, muss sie in der übergeordneten Komponente (in unserem Fall AppComponent) wie folgt beschrieben werden:

 <!-- app.component.html --> <app-widget-component Title="  (  )"> <!-- let-post="post" ,         --> <ng-template appWidgetContentTemplate let-post="post"> <app-post-view [Post]="post"></app-post-view> </ng-template> </app-widget-component> <br> <br> <app-widget-component Title="  (  )"> <!--  let-post="post"     ,  ShowPostInfo  AppComponent --> <ng-template appWidgetContentTemplate let-post="post"> <app-post-view [Post]="post" [ShowPostInfo]="ShowPostInfo"></app-post-view> </ng-template> </app-widget-component> 

Wir haben also eine Widget-Komponente, die Inhalte akzeptiert und anzeigt, während die Widget-Komponente selbst nichts über den Inhalt wissen muss. Die Switch-Optionen werden einfach weitergeleitet. Lesen Sie sie oder nicht ist eine Frage des Inhalts.



Die Vollversion des Codes finden Sie hier .

Source: https://habr.com/ru/post/de478886/


All Articles