2016-06-01 9 views
25

Supponendo di voler utilizzare un componente da qualche libreria in angular2 (esempio da material2). L'annotazione del componente è simile a questa:Estendere/Ignorare lo stile del componente angolare2 riutilizzabile

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

Questo componente viene fornito con un foglio di stile "predefinito", "input.css". Se usiamo questo componente nella nostra app probabilmente vorremmo sovrascrivere/estendere alcuni stili, senza copiare e manipolare il componente stesso. Come fare questo?

Possibile Soluzione 1: Impostare l'incapsulamento a "ViewEncapsulation.None":
Questo non è davvero una soluzione, solo una soluzione temporanea.

Possibile Soluzione 2: Usare ":: ombra" o "/ profondità /" nei CSS:
funziona anche, ma la sua deprecato in base alle WebComponent spec.

Possibile Soluzione 3: Usare CSS globale e sostituiscono il CSS componente:
funziona anche, ma viola il concetto dell'ombra DOM.

Possibile Soluzione 4: Override direttamente nel modello di componente principale:

Esempio:

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

non è veramente adatto se facciamo un sacco di rilevante.

Possibile Soluzione 5: Override o estendere la definizione di "@Component" con un foglio di stile in qualche modo aggiuntivo:
Questa sembra essere l'unica soluzione corretta (almeno per me). Ma non ho idea di come fare questo ...

Qualche consiglio su questo? Forse ho qualcosa di sbagliato ... Grazie.

risposta

9

Per la soluzione 5, è necessario creare una sottoclasse per il componente mirato, creare un decoratore personalizzato che gestisca/sostituisca i metadati e lo imposti per il componente secondario corrente.

Ecco un esempio:

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

Il CustomComponent decoratore sarebbe simile a questa:

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); 
    } 
} 

Vedere questa domanda per maggiori dettagli:

6

Possibile Soluzione 2: Usare ":: ombra" o "/ profondità /" nei CSS:

Questo vale solo se si utilizza ViewEncapsulation.Native.

Se si utilizza ViewEncapsulation.Emulated (impostazione predefinita), Angular utilizza la propria interpretazione di /deep/ e ::shadow e la rimozione non è valida.

Se si utilizza ViewEncapsulation.Native allora Attualmente sei fuori di fortuna perché browser nativo ::shadow e /deep/ profonda sono deprecati e angolare non fornisce ancora alcun supporto per il supporto themeing per ViewEncapsulation.Native come per esempio polimeri fa con (polyfilled) variabili CSS e mixin.

+0

grazie per questo chiarimento – patrickkeller

+1

È necessario essere consapevoli che l'estensione decoratori non sarà supportato dal compilatore modello non in linea e si scoraggia https://github.com/angular/angular/temi/7968 # issuecomment-223.779.992 –

7

A partire da Angular 2.3 possiamo utilizzare l'ereditarietà dei componenti. Per realizzare la tua soluzione 5 potremmo farlo.

//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 { 
} 
Problemi correlati