2016-06-01 1 views
25

Angenommen, wir möchten eine Komponente aus einer Bibliothek in angular2 verwenden (Beispiel aus material2). Die Komponente Anmerkung sieht wie folgt aus:Stil der wiederverwendbaren angular2-Komponente erweitern/überschreiben

@Component({ 
    moduleId: module.id, 
    selector: 'md-input', 
    templateUrl: 'input.html', 
    styleUrls: ['input.css'], 
    providers: [MD_INPUT_CONTROL_VALUE_ACCESSOR], 
    host: {'(click)' : 'focus()'} 
}) 

Diese Komponente wird mit einem „default“ Sheet, das „input.css“. Wenn wir diese Komponente in unserer App verwenden, möchten wir wahrscheinlich einen Teil des Stils überschreiben/erweitern, ohne die Komponente selbst zu kopieren und zu manipulieren. Wie macht man das?

Mögliche Lösung 1: Stellen Sie die Verkapselung auf „ViewEncapsulation.None“:
Das ist nicht wirklich eine Lösung, nur eine Abhilfe.

Mögliche Lösung 2: Verwenden Sie ":: Schatten" oder "/ deep /" in CSS:
funktioniert auch, aber seine veralteten nach WebComponent spec.

Mögliche Lösung 3: Verwenden Sie globale CSS und überschreiben Sie die Komponente CSS:
funktioniert auch, aber es verstößt gegen die Schatten DOM-Konzept.

Mögliche Lösung 4: Überschreiben Sie direkt in der Vorlage der Stammkomponente:

Beispiel:

<my-cmp [font-size]="100"></my-cmp> 

ist nicht wirklich geeignet, wenn wir viele zwingende tun.

Mögliche Lösung 5: außer Kraft setzen oder die „@Component“ Definition mit einem zusätzlichen Sheet erweitert irgendwie:
Dies scheint die einzig richtige Lösung (zumindest für mich) zu sein. Aber ich habe keine Ahnung, wie man das macht ...

Irgendwelche Ratschläge dazu? Vielleicht habe ich etwas falsch gemacht ... Danke.

Antwort

9

Für die Lösung 5 müssen Sie eine Unterklasse für die Zielkomponente erstellen, einen benutzerdefinierten Dekorator erstellen, der die Metadaten behandelt/überschreibt und für die aktuelle Unterkomponente festlegt.Hier

ist ein Beispiel:

@CustomComponent({ 
    styleUrls: ['css/style.css'] 
}) 
export class OverridenComponent extends SomeComponent { 
} 

Der CustomComponent Dekorateur würde wie folgt aussehen:

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])) { 
     annotation[key] = parentAnnotation[key]; 
     } 
    }); 
    var metadata = new ComponentMetadata(annotation); 

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

Sehen Sie diese Frage für weitere Informationen:

6

Mögliche Lösung 2: Verwenden Sie ":: Schatten" oder "/ deep /" in CSS:

Dies gilt nur, wenn Sie ViewEncapsulation.Native verwenden.

Wenn Sie ViewEncapsulation.Emulated (Standard) verwenden, dann verwendet Angular seine eigene Interpretation von /deep/ und ::shadow und die Abwertung gilt nicht.

Wenn Sie ViewEncapsulation.Native verwenden, dann sind Sie zur Zeit kein Glück, weil Browser nativen ::shadow und /deep/ tief sind veraltet und Angular bietet keine noch keine Unterstützung für themeing Unterstützung für ViewEncapsulation.Native wie zum Beispiel Polymer tut mit (polyfilled) CSS Variablen und Mixins.

+0

Dank für diese Klarstellung – patrickkeller

+1

Sie sollten sich bewusst sein, dass Dekorateure Verlängerung nicht durch die Offline-Template Compiler unterstützt werden und wird abgeraten https://github.com/angular/angular/issues/7968 # issuecomment-223779992 –

7

Beginnend mit Angular 2.3 können wir die Komponentenvererbung verwenden. Um Ihre Lösung 5 zu erreichen, könnten wir dies tun.

//This is our base component that we want to override 
@Component({ 
    selector: 'pagination', 
    templateUrl: './pagination.component.html', 
    styleUrls: ['./pagination.component.css'] 
}) 
export class PaginationComponent { 
} 


//This inherits from our base component and uses a different style sheet. 
@Component({ 
    selector: 'pagination2', 
    //This is sharing the template with the parent class. Note 
    //this needs to be included since templateUrl doesn't automatically 
    //inherit. 
    templateUrl: './pagination.component.html', 
    //This is using a unique css file 
    styleUrls: ['./pagination2.component.css'] 
}) 
export class PaginationComponent2 extends PaginationComponent { 
} 
Verwandte Themen