2016-03-10 32 views
23

Negli esempi forniti di direttive Attribute (ad esempio una direttiva per aggiungere aspetto/comportamento), abbiamo un'impostazione abbastanza semplice di uno stile sull'elemento host. Ad es.Stili angolari2 in una direttiva

import {Directive, ElementRef } from 'angular2/core'; 
@Directive({ 
    selector: '[myHighlight]' 
}) 
export class HighlightDirective { 
    constructor(element) { 
     element.nativeElement.style.backgroundColor = 'yellow'; 
    } 

static get parameters(){ 
    return [[ElementRef]]; 
} 

Piuttosto che impostare lo stile, posso invece usare uno stile? per esempio.

@Directive({ 
    selector: '[myHighlight]', 
    styles: [':host { background-color: yellow; }'] 
}) 

Questo non sembra funzionare per me?

Sto facendo qualcosa di leggermente più complesso che ha portato a una buona quantità di codice monolingue, l'impostazione di molti stili, utilizzando AnimationBuilder ecc ecc. Mi sembra come sarebbe molto meglio separarlo in classi e animazioni in un CSS.

ViewEncapsulation = emulato/predefinito se ciò è importante?

+0

Anche se è stato un anno, per l'amor di posteri, ho aggiunto la risposta qui sotto. Implica sia l'uso di un componente come direttiva, sia la modifica del ViewEncapsulation di default. Vedi la mia risposta qui sotto. - Cheers –

risposta

20

È possibile utilizzare vincolante per l'associazione a stile ospite attributi:

@Directive({ 
    selector: '[myHighlight]', 
    host: { 
     '[style.background-color]': '"yellow"', 
    } 
}) 

o

@Directive({ 
    selector: '[myHighlight]', 
}) 
class MyDirective { 
    @HostBinding('style.background-color') 
    backgroundColor:string = 'yellow'; 
} 
+1

Grazie, ma questo mi lascia ancora il problema di dover impostare n numero di proprietà singolarmente, piuttosto che utilizzare CSS in linea/esterni? Va bene in questo semplice esempio, ma cosa succede se ho 30+ regole con animazioni, e quelle regole possono essere applicate in diversi stati/combinazioni, ad es. aleggia, clicca ecc. – ct5845

+0

Apprezzare la tua risposta in questo caso è molto meglio che aggiungere una dipendenza a ElementRef! – ct5845

+4

Questo è ciò che fornisce Angular. Solo i componenti supportano l'aggiunta di fogli di stile (in linea o importazioni). ('styles',' styleUrls'). –

4

Ho letto il tuo commento qui sotto prima risposta. Non so come saresti in grado di applicare le tue 30 regole. But few ways are here- plunker.

selector:"[myHighlight]", 
    host: {   
    '(mouseenter)':'changeColor()', 
    '[style.background]': '"pink"', 
    '(click)':'clickMe()', 
    '(mouseout)':'changeColorOnOut()', 
    } 
1

Basta impostare l'elemento come si farebbe normalmente utilizzando il selettore di attributo. Creare un file myHighlight.directive.scss (o altro) nella stessa cartella direttiva e scrivere i vostri stili in là:

[myhighlight] { 
    background-color: yellow; 
} 

Se la vostra applicazione non include il file stile automaticamente, basta importare nel vostro file di stile principale. Per me in Ionic 2 è stato rilevato automaticamente.

Se si desidera utilizzare una classe specifica anziché il selettore di attributo, utilizzare il Renderer per aggiungere la classe.

import {Directive, ElementRef, Renderer} from 'angular2/core'; 
@Directive({ 
    selector: '[myHighlight]' 
}) 
export class HighlightDirective { 
    constructor(private el: ElementRef, private renderer: Renderer) { 
     this.renderer.setElementClass(this.el.nativeElement, 'my-highlight', true); 
    } 
} 
+0

L'utilizzo del primo approccio non ha funzionato per me. Utilizzando Angular 2.4. Se devo importare nel file global.scss, perdo l'incapsulamento di stile. È possibile impostare una classe personalizzata solo su una direttiva o utilizzare un componente @ senza incapsulamento della vista. – aelkz

+0

funziona per me. Altered 'parentElement {ion-card {}}' a '[parentElement] {}' quando ho cambiato il selettore di elementi in un selettore di attributi e ho aggiunto il selettore di attributi all'elemento 'ion-card' nel mio componente . –

+0

@aelkz: Sono un po 'in ritardo per la festa, ma funziona per me in Angular 5 e Ionic 3. Hai controllato che il selettore in scss non è lo stesso del file .ts? alias, nel file .ts di solito dice "selector: [mySelectorSomething]" e per lo scss avere qualche effetto deve fare riferimento a lettere maiuscole, ovvero [myselectorsomething]: {}, come indicato anche nell'esempio precedente. È piuttosto sottile e non molto logico, quindi è facile non vederlo (era almeno per me). – yogibimbi

9

Mentre le altre risposte sono utili nella maggior parte dei casi, ti sembra di avere bisogno di un approccio più tradizionale di stile CSS, come ho avuto un caso d'uso per.

Il problema è l'impostazione predefinita di Angular di emulare un DOM ombra che circoscrive gli stili solo all'interno dell'elemento host.

due opzioni:

1)

Si può dire angolare a cascata gli stili verso il basso attraverso tutti i suoi discendenti con il :host /deep/ .some-style-to-cascade-down-like-normal {} o sostituire /deep/ con >>>. Vedi Angular's Docs su questo.

Tre cose importanti da notare:

  • ViewEncapsulation ha bisogno di essere il suo stato (emulato) predefinita
  • angolare/Chrome deprecarla entrambe queste sintassi, mentre si sta lavorando su un approccio migliore
  • Se 're utilizzando la CLI angolare, è necessario utilizzare la /deep/ invece di >>>

2)

Anche se si perde l'incapsulamento componente ambito (se quello che conta nel tuo caso), ecco un esempio utilizzando "myHighlight" come una direttiva se TypeScripted come componente così posso importare il foglio di stile:

USO:
<p myHighlight>Highlight me!</p>

TS (componente trattata come una direttiva ):

import { 
    Component, 
    ViewEncapsulation 
} from '@angular/core'; 

@Component({ 
    selector: 'p[myHighlight]', // Refer to it like an attribute directive 
    templateUrl: './my-highlight.component.html', 
    styleUrls: ['./my-highlight.component.scss'], 
    encapsulation: ViewEncapsulation.None // Tell Angular to not scope your styles 
}) 

Angular Material 2's Button utilizza questo stesso approccio per risolvere questo problema.

Ed ecco un grande articolo chiamato All the Ways to Add CSS to Angular 2 Components che mi ha portato a questa consapevolezza e spiega come Angular tratta tutte e tre le proprietà ViewEncapsulation.

+2

upvote per "incapsulamento: ViewEncapsulation.None": D –

+0

"Il pulsante Angular Material 2 utilizza questo stesso approccio per risolvere questo problema." - usano la tecnica che stai usando e il selettore è simile a una direttiva. Ma a differenza di questo argomento non stavano cercando di aggiungere stili a una direttiva. Per coloro che decidono di convertire la loro direttiva in un componente solo per questo vantaggio di stile, quale modello utilizzi? Potresti aggiungere il tuo. \ My-highlight.component.html in modo che possiamo vedere come farlo funzionare? E questo non entrerà in conflitto con altri componenti creati dallo stesso elemento? per esempio. jcairney

0

Uguale @ m.spyratos, ma utilizzando Renderer2:

import { 
    Directive, 
    ElementRef, 
    OnInit, 
    Renderer2 
} from '@angular/core'; 

@Directive({ 
    selector: '[myButton]' 
}) 
export class MyButtonDirective implements OnInit { 
    constructor(
    private elementRef: ElementRef, 
    private renderer: Renderer2 
) { } 

    public ngOnInit(): void { 
    this.renderer.addClass(
     this.elementRef.nativeElement, 
     'my-button' 
    ); 
    } 
} 
Problemi correlati