Wie kann man Komponenten erweitern / erben?

159

Ich möchte Erweiterungen für einige Komponenten erstellen, die bereits in Angular 2 bereitgestellt wurden, ohne sie fast vollständig neu schreiben zu müssen, da die Basiskomponente Änderungen unterliegen könnte und wünschte, diese Änderungen würden sich auch in den abgeleiteten Komponenten widerspiegeln.

Ich habe dieses einfache Beispiel erstellt, um meine Fragen besser zu erklären:

Mit folgender Basiskomponente app/base-panel.component.ts:

import {Component, Input} from 'angular2/core';

@Component({
    selector: 'base-panel',
    template: '<div class="panel" [style.background-color]="color" (click)="onClick($event)">{{content}}</div>',
    styles: [`
    .panel{
    padding: 50px;
  }
  `]
})
export class BasePanelComponent { 

  @Input() content: string;

  color: string = "red";

  onClick(event){
    console.log("Click color: " + this.color);
  }
}

Möchten Sie eine andere abgeleitete Komponente erstellen, ändern Sie beispielsweise nur ein grundlegendes Verhalten der Komponente im Fall der Beispielfarbe app/my-panel.component.ts:

import {Component} from 'angular2/core';
import {BasePanelComponent} from './base-panel.component'

@Component({
    selector: 'my-panel',
    template: '<div class="panel" [style.background-color]="color" (click)="onClick($event)">{{content}}</div>',
    styles: [`
    .panel{
    padding: 50px;
  }
  `]
})
export class MyPanelComponent extends BasePanelComponent{

  constructor() {
    super();
    this.color = "blue";
  }
}

Vollständiges Arbeitsbeispiel in Plunker

Hinweis: Dieses Beispiel ist offensichtlich einfach und könnte gelöst werden, da sonst keine Vererbung erforderlich ist. Es soll jedoch nur das eigentliche Problem veranschaulichen.

Wie Sie in der Implementierung der abgeleiteten Komponente sehen können app/my-panel.component.ts, wurde ein Großteil der Implementierung wiederholt, und der einzelne Teil, der wirklich geerbt wurde class BasePanelComponent, war der , aber der @Componentmusste im Grunde vollständig wiederholt werden, nicht nur die geänderten Teile, wie der selector: 'my-panel'.

Gibt es eine Möglichkeit, eine Komponente Angular2 buchstäblich vollständig zu vererben, indem beispielsweise die classDefinition der Markierungen / Anmerkungen übernommen wird @Component?

Bearbeiten 1 - Funktionsanforderung

Feature-Anforderung angular2 wurde dem Projekt auf GitHub hinzugefügt: Erweitern / Erben der Angular2-Komponentenanmerkungen # 7968

Bearbeiten 2 - Geschlossene Anfrage

Aus diesem Grund wurde die Anfrage geschlossen, die kurzzeitig nicht wissen würde, wie der Dekorateur zusammengeführt werden soll. Lassen Sie uns keine Optionen. Meine Meinung wird also in der Ausgabe zitiert .

Fernando Leal
quelle
Überprüfen Sie diese Antwort stackoverflow.com/questions/36063627/… Grüße
NicolasB
Ok NicolasB. Mein Problem ist jedoch die Vererbung des Decorators @Component, die nicht auf die Vererbungsmetadaten angewendet wird. = /
Fernando Leal
Menschen, bitte vermeiden Sie die Verwendung von Vererbung mit Winkel. Beispiel: Die Exportklasse PlannedFilterComponent erweitert AbstractFilterComponent implementiert OnInit {ist sehr schlecht. Es gibt andere Möglichkeiten, Code gemeinsam zu nutzen, z. B. Dienste und kleinere Komponenten. Vererbung ist nicht der Winkelweg. Ich bin in einem Winkelprojekt, in dem sie Vererbung verwendet haben, und es gibt Dinge, die kaputt gehen, wie das Exportieren von Komponenten, die von abstrakten Komponenten erben, fehlen Eingaben der abstrakten Klasse.
Robert King
1
Verwenden Sie stattdessen die Inhaltsprojektion, z. B. github.com/angular/components/blob/master/src/material/card/…. Verwenden Sie keine Vererbung
Robert King

Antworten:

39

Alternative Lösung:

Diese Antwort von Thierry Templier ist eine alternative Möglichkeit, das Problem zu umgehen.

Nach einigen Fragen an Thierry Templier kam ich zu folgendem Arbeitsbeispiel, das meine Erwartungen als Alternative zur in dieser Frage erwähnten Vererbungsbeschränkung erfüllt:

1 - Benutzerdefinierten Dekorateur erstellen:

export function CustomComponent(annotation: any) {
  return function (target: Function) {
    var parentTarget = Object.getPrototypeOf(target.prototype).constructor;
    var parentAnnotations = Reflect.getMetadata('annotations', parentTarget);

    var parentAnnotation = parentAnnotations[0];
    Object.keys(parentAnnotation).forEach(key => {
      if (isPresent(parentAnnotation[key])) {
        // verify is annotation typeof function
        if(typeof annotation[key] === 'function'){
          annotation[key] = annotation[key].call(this, parentAnnotation[key]);
        }else if(
        // force override in annotation base
        !isPresent(annotation[key])
        ){
          annotation[key] = parentAnnotation[key];
        }
      }
    });

    var metadata = new Component(annotation);

    Reflect.defineMetadata('annotations', [ metadata ], target);
  }
}

2 - Basiskomponente mit @Component Decorator:

@Component({
  // create seletor base for test override property
  selector: 'master',
  template: `
    <div>Test</div>
  `
})
export class AbstractComponent {

}

3 - Unterkomponente mit @CustomComponent Decorator:

@CustomComponent({
  // override property annotation
  //selector: 'sub',
  selector: (parentSelector) => { return parentSelector + 'sub'}
})
export class SubComponent extends AbstractComponent {
  constructor() {
  }
}

Plunkr mit vollständigem Beispiel.

Fernando Leal
quelle
3
Ich gehe davon aus, dass dies nicht mit dem Offline-Vorlagen-Compiler kompatibel ist.
Günter Zöchbauer
@ GünterZöchbauer, ich habe keine Kenntnisse über "Offline-Compiler-Vorlage" von Angular2. Aber ich denke, das ist möglicherweise nicht kompatibel, und es wäre eine alternative Option. Wo wäre der Modus "Offline Template Compiler" von Angular2 nützlich? Sie können mir etwas zeigen, um das besser zu verstehen? So kann ich verstehen, wie wichtig diese Kompatibilität für mein Projekt ist.
Fernando Leal
Der Offline Template Compiler (OTC) ist noch nicht funktionsfähig, obwohl er bereits in RC.3 enthalten ist. OTC analysiert die Dekoratoren und generiert Code während eines Erstellungsschritts, wenn das Deployable generiert wird. Mit OTC können Angular2-Parser und -Compiler entfernt werden, die Dekoratoren und Bindungen zur Laufzeit verarbeiten. Dies führt zu einer deutlich geringeren Codegröße und einer schnelleren Initialisierung von Anwendungen und Komponenten. OTC wird wahrscheinlich mit einem der nächsten Updates verwendet.
Günter Zöchbauer
1
@ GünterZöchbauer, jetzt verstehe ich, wie wichtig es ist, die mit OTC kompatible Funktionalität aufrechtzuerhalten. Es wird eine Vorkompilierung von eckigen Dekorateuren sein, die den Overhead reduzieren, um Komponenten zu initialisieren. Ich hätte gerne gewusst, wie dieser Prozess funktioniert und weil die Lösung dieser Antwort nicht mit OTC kompatibel ist. Wie ist die Vorkompilierung von Dekorateuren? Mit diesem Wissen könnten wir uns etwas einfallen lassen, um diese funktionale Alternative zu OTC beizubehalten. Danke für die Klarstellung!
Fernando Leal
24

Angular 2 Version 2.3 wurde gerade veröffentlicht und enthält die native Komponentenvererbung. Es sieht so aus, als könnten Sie alles erben und überschreiben, was Sie wollen, mit Ausnahme von Vorlagen und Stilen. Einige Referenzen:

Daniel Griscom
quelle
Ein "Gotcha" tritt hier auf, wenn Sie vergessen, einen neuen "Selektor" in der untergeordneten Komponente anzugeben. More than one component matched on this elementWenn Sie dies nicht tun, wird ein Laufzeitfehler angezeigt .
Die Aelfinn
@TheAelfinn Ja: Jede Komponente muss eine vollständige Spezifikation im @Component()Tag haben. Sie können die HTML- oder CSS-Datei jedoch freigeben, indem Sie auf dieselbe Datei verweisen, wenn Sie möchten. Alles in allem ist es ein großes Plus.
Daniel Griscom
In Ihrem zweiten Link scotch.io/tutorials/component-inheritance-in-angular-2 behauptet der Autor, dass Komponenten die abhängigkeitsinjizierten Dienste ihrer Eltern erben, mein Code schlägt etwas anderes vor. Können Sie bestätigen, dass dies unterstützt wird?
Die Aelfinn
18

Jetzt, da TypeScript 2.2 Mixins durch Klassenausdrücke unterstützt, haben wir eine viel bessere Möglichkeit, Mixins auf Komponenten auszudrücken. Beachten Sie jedoch, dass Sie auch die Komponentenvererbung seit Winkel 2.3 ( Diskussion ) oder einen benutzerdefinierten Dekorateur verwenden können, wie in anderen Antworten hier beschrieben. Ich denke jedoch, dass Mixins einige Eigenschaften haben, die sie für die Wiederverwendung des Verhaltens zwischen Komponenten vorziehen:

  • Mixins setzen sich flexibler zusammen, dh Sie können Mixins auf vorhandenen Komponenten mischen und anpassen oder Mixins kombinieren, um neue Komponenten zu bilden
  • Die Mixin-Zusammensetzung bleibt dank ihrer offensichtlichen Linearisierung zu einer Klassenvererbungshierarchie leicht zu verstehen
  • Sie können Probleme mit Dekoratoren und Anmerkungen, die die Vererbung von Komponenten beeinträchtigen, leichter vermeiden ( Diskussion ).

Ich empfehle dringend, dass Sie die obige TypeScript 2.2-Ankündigung lesen, um zu verstehen, wie Mixins funktionieren. Die verknüpften Diskussionen in eckigen GitHub-Problemen bieten zusätzliche Details.

Sie benötigen diese Typen:

export type Constructor<T> = new (...args: any[]) => T;

export class MixinRoot {
}

Und dann können Sie ein Mixin wie dieses deklarieren Destroyable, mit dessen Hilfe Komponenten Abonnements verfolgen können, die entsorgt werden müssen ngOnDestroy:

export function Destroyable<T extends Constructor<{}>>(Base: T) {
  return class Mixin extends Base implements OnDestroy {
    private readonly subscriptions: Subscription[] = [];

    protected registerSubscription(sub: Subscription) {
      this.subscriptions.push(sub);
    }

    public ngOnDestroy() {
      this.subscriptions.forEach(x => x.unsubscribe());
      this.subscriptions.length = 0; // release memory
    }
  };
}

Um sich Destroyablein a zu mischen Component, deklarieren Sie Ihre Komponente wie folgt:

export class DashboardComponent extends Destroyable(MixinRoot) 
    implements OnInit, OnDestroy { ... }

Beachten Sie, dass dies MixinRootnur erforderlich ist, wenn Sie extendeine Mixin-Komposition erstellen möchten . Sie können problemlos mehrere Mixins erweitern, z A extends B(C(D)). Dies ist die offensichtliche Linearisierung von Mixins, über die ich oben gesprochen habe, z. B. wenn Sie effektiv eine Vererbungshierarchie erstellen A -> B -> C -> D.

In anderen Fällen, z. B. wenn Sie Mixins für eine vorhandene Klasse erstellen möchten, können Sie das Mixin folgendermaßen anwenden:

const MyClassWithMixin = MyMixin(MyClass);

Ich fand jedoch, dass der erste Weg am besten für Componentsund funktioniert Directives, da diese auch mit @Componentoder @Directivesowieso dekoriert werden müssen.

Johannes Rudolph
quelle
das ist fantastisch! danke für den Vorschlag. Wird MixinRoot hier einfach als leerer Klassenplatzhalter verwendet? Ich möchte nur sicherstellen, dass mein Verständnis korrekt ist.
Alex Lockwood
@AlexLockwood yup, leerer Klassenplatzhalter ist genau das, wofür ich ihn benutze. Ich würde es gerne vermeiden, aber im Moment habe ich keinen besseren Weg gefunden, es zu tun.
Johannes Rudolph
2
Am Ende habe ich verwendet function Destroyable<T extends Constructor<{}>>(Base = class { } as T). Auf diese Weise kann ich Mixins mit erstellen extends Destroyable().
Alex Lockwood
1
Dies sieht sehr gut aus, es scheint jedoch, dass AoT Build (Cli1.3) ngOnDestroy aus DashBoardComponent entfernt, da es nie aufgerufen wird. (Gleiches gilt für ngOnInit)
Dzolnjan
Danke für diese Lösung. Nach einem Produktaufbau mit ionischem oder eckigem Cli funktioniert das Mixin jedoch irgendwie nicht, als ob es nicht erweitert worden wäre.
Han Che
16

aktualisieren

Die Vererbung von Komponenten wird seit 2.3.0-rc.0 unterstützt

Original

Bisher ist die bequemste für mich Vorlage zu halten und anderen Artikel in separaten *html& *.cssDateien und gibt diejenigen , die durch templateUrlund styleUrls, so ist es leicht wiederverwendbar ist.

@Component {
    selector: 'my-panel',
    templateUrl: 'app/components/panel.html', 
    styleUrls: ['app/components/panel.css']
}
export class MyPanelComponent extends BasePanelComponent
am0wa
quelle
2
Genau das brauche ich. Wie würde der @ Component-Dekorator für BasePanelComponent aussehen? Könnte es auf verschiedene HTML / CSS-Dateien verweisen? Könnte es auf dieselben HTML- / CSS-Dateien verweisen, auf die MyPanelComponent verweist?
ebhh2001
1
Das erbt nicht @Input()und @Output()Dekorateure, oder?
Leon Adler
10

Soweit ich weiß, wurde die Komponentenvererbung in Angular 2 noch nicht implementiert, und ich bin mir nicht sicher, ob dies geplant ist. Da Angular 2 jedoch Typoskript verwendet (wenn Sie sich für diesen Weg entschieden haben), können Sie die Klassenvererbung verwenden indem du es tust class MyClass extends OtherClass { ... }. Für die Vererbung von Komponenten würde ich empfehlen, sich mit dem Angular 2-Projekt zu befassen, indem Sie auf https://github.com/angular/angular/issues gehen und eine Funktionsanfrage senden!

Watzon
quelle
Verstanden, ich werde in den nächsten Tagen versuchen, mein Angular2-Projekt zu wiederholen und zu überprüfen, ob die Anforderungsfunktion nicht mehr in den Projektproblemen in Git enthalten ist. Wenn nicht, werde ich eine Anforderung für die Ressource erstellen, da sie mir sehr interessant erscheint Feature. Haben Sie zusätzliche Argumente, um die interessanteste Anfrage zu stellen?
Fernando Leal
1
In Bezug auf das Typoskript der Vererbungsressource, die ich bereits in meiner ursprünglichen Lösung ( export class MyPanelComponent extends BasePanelComponent) verwende, besteht das Problem nur im Fall, dass Anmerkungen / Dekorateure nicht vererbt werden.
Fernando Leal
1
Ja, ich weiß wirklich nicht, was Sie noch hinzufügen könnten. Ich mag die Idee, entweder einen neuen Dekorator (so etwas wie @SubComponent()) zu haben, der eine Klasse als Unterkomponente kennzeichnet, oder ein zusätzliches Feld im @ComponentDekorator zu haben, mit dem Sie auf eine übergeordnete Komponente verweisen können, von der geerbt werden soll.
Watzon
1
Feature-Anfrage angular2 zum Projekt auf GitHub hinzugefügt: Anmerkungen zu Angular2-Komponenten erweitern / erben # 7968
Fernando Leal
9

Lassen Sie uns einige wichtige Einschränkungen und Funktionen des Komponentenvererbungssystems von Angular verstehen.

Die Komponente erbt nur die Klassenlogik:

  • Alle Metadaten im @ Component-Dekorator werden nicht vererbt.
  • Die Eigenschaften der Komponenten @Input und @Output werden vererbt.
  • Der Komponentenlebenszyklus wird nicht vererbt.

Diese Funktionen sind sehr wichtig. Lassen Sie uns sie daher einzeln untersuchen.

Die Komponente erbt nur die Klassenlogik

Wenn Sie eine Komponente erben, wird die gesamte darin enthaltene Logik gleichermaßen vererbt. Es ist erwähnenswert, dass nur öffentliche Mitglieder geerbt werden, da auf private Mitglieder nur in der Klasse zugegriffen werden kann, die sie implementiert.

Alle Metadaten im @ Component-Dekorator werden nicht vererbt

Die Tatsache, dass keine Metadaten vererbt werden, mag zunächst kontraintuitiv erscheinen, aber wenn Sie darüber nachdenken, ist dies tatsächlich absolut sinnvoll. Wenn Sie von einem Component say (componentA) erben, möchten Sie nicht, dass der Selektor von ComponentA, von dem Sie erben, den Selektor von ComponentB ersetzt, der die Klasse ist, die erbt. Gleiches gilt für die Vorlage / templateUrl sowie die style / styleUrls.

Die Eigenschaften der Komponenten @Input und @Output werden vererbt

Dies ist eine weitere Funktion, die ich an der Komponentenvererbung in Angular sehr liebe. In einem einfachen Satz werden diese Eigenschaften immer dann vererbt, wenn Sie über eine benutzerdefinierte Eigenschaft @Input und @Output verfügen.

Der Komponentenlebenszyklus wird nicht vererbt

Dieser Teil ist derjenige, der besonders für Menschen, die nicht umfassend mit OOP-Prinzipien gearbeitet haben, nicht so offensichtlich ist. Angenommen, Sie haben ComponentA, das einen der vielen Lifecycle-Hooks von Angular wie OnInit implementiert. Wenn Sie ComponentB erstellen und ComponentA erben, wird der OnInit-Lebenszyklus von ComponentA erst ausgelöst, wenn Sie ihn explizit aufrufen, selbst wenn Sie diesen OnInit-Lebenszyklus für ComponentB haben.

Aufrufen von Super / Base-Komponentenmethoden

Damit die ngOnInit () -Methode von ComponentA ausgelöst wird, müssen wir das Schlüsselwort super verwenden und dann die benötigte Methode aufrufen, die in diesem Fall ngOnInit ist. Das Super-Schlüsselwort bezieht sich auf die Instanz der Komponente, die geerbt wird, von der in diesem Fall ComponentA ist.

Masoud Bimar
quelle
5

Wenn Sie die CDK-Bibliotheken und die Materialbibliotheken durchlesen, verwenden sie die Vererbung, aber nicht so sehr die Komponenten selbst. Die Projektion von Inhalten ist König IMO. Siehe diesen Link https://blog.angular-university.io/angular-ng-content/, auf dem "das Hauptproblem bei diesem Design" steht.

Ich weiß, dass dies Ihre Frage nicht beantwortet, aber ich denke wirklich, dass das Erben / Erweitern von Komponenten vermieden werden sollte . Hier ist meine Argumentation:

Wenn die um zwei oder mehr Komponenten erweiterte abstrakte Klasse eine gemeinsame Logik enthält: Verwenden Sie einen Dienst oder erstellen Sie sogar eine neue Typoskriptklasse, die von den beiden Komponenten gemeinsam genutzt werden kann.

Wenn die abstrakte Klasse ... gemeinsam genutzte Variablen oder onClicketc-Funktionen enthält, erfolgt eine Duplizierung zwischen dem HTML-Code der beiden erweiterten Komponentenansichten. Dies ist eine schlechte Praxis und das gemeinsam genutzte HTML muss in Komponenten aufgeteilt werden. Diese Komponente (n) (Teile) können zwischen den beiden Komponenten geteilt werden.

Vermisse ich andere Gründe für eine abstrakte Klasse für Komponenten?

Ein Beispiel, das ich kürzlich gesehen habe, waren Komponenten, die AutoUnsubscribe erweitern:

import { Subscription } from 'rxjs';
import { OnDestroy } from '@angular/core';
export abstract class AutoUnsubscribeComponent implements OnDestroy {
  protected infiniteSubscriptions: Array<Subscription>;

  constructor() {
    this.infiniteSubscriptions = [];
  }

  ngOnDestroy() {
    this.infiniteSubscriptions.forEach((subscription) => {
      subscription.unsubscribe();
    });
  }
}

Dies war bas, weil in einer großen Codebasis infiniteSubscriptions.push()nur 10 Mal verwendet wurde. Auch das Importieren und Erweitern erfordert AutoUnsubscribemehr Code als nur das Hinzufügen mySubscription.unsubscribe()der ngOnDestroy()Methode der Komponente selbst, was ohnehin zusätzliche Logik erfordert.

Robert King
quelle
Ok, ich verstehe Ihre Kollokation und stimme zu, dass die Aggregation fast alle Probleme löst, die eine Vererbung erfordern. Und es ist immer interessant, sich Komponenten als kleine Teile der Anwendung vorzustellen, die auf verschiedene Arten angedockt werden können. Bei der Frage besteht das Problem jedoch darin, dass ich keine Kontrolle / keinen Zugriff auf Änderungen in der Komponente habe, die ich erben möchte (es ist eine dritte Komponente), dann würde eine Aggregation unmöglich und die Vererbung wäre die ideale Lösung.
Fernando Leal
Warum können Sie nicht einfach eine neue Komponente erstellen, die diese Komponente eines Drittanbieters kapselt? Was ist Ihre Drittanbieter-Komponente aus Interesse? zB <mein-Kalender [Zeug] = Zeug> <Drittanbieter-Kalender [Zeug] = Zeug> </ ..> </ ..>
Robert King
@robertking sich zu wiederholen ist ein sehr schwaches Muster ... Deshalb wirst du anfangen, deinen Job zu hassen ... anstatt ihn zu genießen.
Dariusz Filipiak
Für mich ist es eine gute Idee, Komponenten zu erweitern, falls Sie dieselben Eingabe- / Ausgabeparameter für eine Reihe von Komponenten haben möchten, damit sie sich wie eine verhalten können. Zum Beispiel habe ich mehrere Registrierungsschritte (credentialsStep, addressStep, selectBenefitsStep). Sie sollten alle die gleichen Eingabeoptionen (stepName, actionButtons ...) und Ausgänge (vollständig, abbrechen) haben.
Sergey_T
@Sergey_T Könnten Sie eine Komponente mit ng select und Inhaltsprojektion in Betracht ziehen? Auch das Wiederholen einiger Eingaben scheint nicht wirklich viel Funktionalität für TBH zu sparen.
Robert King
2

Wenn jemand nach einer aktualisierten Lösung sucht, ist Fernandos Antwort ziemlich perfekt. Nur dass ComponentMetadatadies veraltet ist. Verwenden Componentstattdessen für mich gearbeitet.

Die vollständige Custom Decorator- CustomDecorator.tsDatei sieht folgendermaßen aus:

import 'zone.js';
import 'reflect-metadata';
import { Component } from '@angular/core';
import { isPresent } from "@angular/platform-browser/src/facade/lang";

export function CustomComponent(annotation: any) {
  return function (target: Function) {
    var parentTarget = Object.getPrototypeOf(target.prototype).constructor;
    var parentAnnotations = Reflect.getMetadata('annotations', parentTarget);

    var parentAnnotation = parentAnnotations[0];
    Object.keys(parentAnnotation).forEach(key => {
      if (isPresent(parentAnnotation[key])) {
        // verify is annotation typeof function
        if(typeof annotation[key] === 'function'){
          annotation[key] = annotation[key].call(this, parentAnnotation[key]);
        }else if(
          // force override in annotation base
          !isPresent(annotation[key])
        ){
          annotation[key] = parentAnnotation[key];
        }
      }
    });

    var metadata = new Component(annotation);

    Reflect.defineMetadata('annotations', [ metadata ], target);
  }
}

Importieren Sie es dann in Ihre neue Komponentendatei sub-component.component.tsund verwenden Sie @CustomComponentstattdessen @ComponentFolgendes:

import { CustomComponent } from './CustomDecorator';
import { AbstractComponent } from 'path/to/file';

...

@CustomComponent({
  selector: 'subcomponent'
})
export class SubComponent extends AbstractComponent {

  constructor() {
    super();
  }

  // Add new logic here!
}
Rhyneav
quelle
Sind benutzerdefinierte Dekorateure nicht sehr entmutigt? Von vielen anderen Posts / Threads wurde diese Lösung als völlig falsch markiert, weil AOT sie nicht unterstützt?
TerNovi
2

Sie können @Input, @Output, @ViewChild usw. erben. Sehen Sie sich das Beispiel an:

@Component({
    template: ''
})
export class BaseComponent {
    @Input() someInput: any = 'something';

    @Output() someOutput: EventEmitter<void> = new EventEmitter<void>();

}

@Component({
    selector: 'app-derived',
    template: '<div (click)="someOutput.emit()">{{someInput}}</div>',
    providers: [
        { provide: BaseComponent, useExisting: DerivedComponent }
    ]
})
export class DerivedComponent {

}
Mizuwokiru
quelle
1

Komponenten können wie eine Vererbung von Typoskriptklassen erweitert werden, nur dass Sie den Selektor mit einem neuen Namen überschreiben müssen. Alle Input () - und Output () -Eigenschaften der übergeordneten Komponente funktionieren wie gewohnt

Aktualisieren

@Component ist ein Dekorateur,

Dekoratoren werden während der Deklaration der Klasse nicht auf Objekte angewendet.

Grundsätzlich fügen Dekorateure dem Klassenobjekt einige Metadaten hinzu, auf die nicht über die Vererbung zugegriffen werden kann.

Wenn Sie die Vererbung des Dekorateurs erreichen möchten, würde ich vorschlagen, einen benutzerdefinierten Dekorateur zu schreiben. So etwas wie das folgende Beispiel.

export function CustomComponent(annotation: any) {
    return function (target: Function) {
    var parentTarget = Object.getPrototypeOf(target.prototype).constructor;

    var parentAnnotations = Reflect.getMetadata('annotations', parentTarget);
    var parentParamTypes = Reflect.getMetadata('design:paramtypes', parentTarget);
    var parentPropMetadata = Reflect.getMetadata('propMetadata', parentTarget);
    var parentParameters = Reflect.getMetadata('parameters', parentTarget);

    var parentAnnotation = parentAnnotations[0];

    Object.keys(parentAnnotation).forEach(key => {
    if (isPresent(parentAnnotation[key])) {
        if (!isPresent(annotation[key])) {
        annotation[key] = parentAnnotation[key];
        }
    }
    });
    // Same for the other metadata
    var metadata = new ComponentMetadata(annotation);

    Reflect.defineMetadata('annotations', [ metadata ], target);
    };
};

Siehe: https://medium.com/@ttemplier/angular2-decorators-and-class-inheritance-905921dbd1b7

MAHESH VALIYA VEETIL
quelle
Könnten Sie am Beispiel der Frage veranschaulichen, wie das funktionieren würde? Sie können stackblitz verwenden , um das Beispiel zu entwickeln und den Link freizugeben .
Fernando Leal
@Component ist ein Dekorator. Dekoratoren werden während der Deklaration der Klasse nicht auf Objekte angewendet.
MAHESH VALIYA VEETIL
Du hast recht. Dekorateure machen keinen Unterschied. Es ist nur erforderlich, wenn die Basiskomponente woanders als Komponente verwendet wird
MAHESH VALIYA VEETIL
0
just use inheritance,Extend parent class in child class and declare constructor with parent class parameter and this parameter use in super().

1.parent class
@Component({
    selector: 'teams-players-box',
    templateUrl: '/maxweb/app/app/teams-players-box.component.html'
})
export class TeamsPlayersBoxComponent {
    public _userProfile:UserProfile;
    public _user_img:any;
    public _box_class:string="about-team teams-blockbox";
    public fullname:string;
    public _index:any;
    public _isView:string;
    indexnumber:number;
    constructor(
        public _userProfilesSvc: UserProfiles,
        public _router:Router,
    ){}
2.child class
@Component({

    selector: '[teams-players-eligibility]',
    templateUrl: '/maxweb/app/app/teams-players-eligibility.component.html'
})
export class TeamsPlayersEligibilityComponent extends TeamsPlayersBoxComponent{

    constructor (public _userProfilesSvc: UserProfiles,
            public _router:Router) {
            super(_userProfilesSvc,_router);
        }
}
mittal bhatt
quelle