2016-03-10 121 views
23

在Attribute指令的給定示例中(即添加外觀/行爲的指令),我們在主機元素上設置了相當簡單的樣式。指令中的Angular2樣式

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

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

而不是設置樣式,我可以使用樣式嗎?例如

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

這似乎不適用於我?

我正在做一些稍微複雜的事情,這導致了相當數量的monolothic代碼,設置了很多樣式,使用AnimationBuilder等等。感覺對我來說,將它分成類和動畫會更好在CSS中。

ViewEncapsulation =模擬/默認如果重要?

+0

雖然已經過了一年,爲後人的緣故,我加了下面的答案。它涉及使用組件作爲指令,並更改默認的ViewEncapsulation。請參閱下面的答案。 - 乾杯 –

回答

20

可以使用主機綁定綁定到樣式屬性:

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

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

謝謝,但這仍然讓我需要單獨設置n個屬性的問題,而不是利用內聯/外部CSS?這個簡單的例子很好,但是如果我有30多個動畫規則,並且這些規則可以在不同的狀態/組合下應用,例如徘徊,點擊等。 – ct5845

+0

在這種情況下欣賞你的答案比向ElementRef添加依賴要好得多! – ct5845

+4

這是Angular提供的。只有組件支持添加樣式表(內嵌或導入)。 ('styles','styleUrls')。 –

4

我已閱讀下面第一個回答您的評論。我不知道你將如何運用你的30條規則。 But few ways are here- plunker

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

只需使用屬性選擇器來設置元素的樣式即可。在那裏創建在同一文件夾作爲您的指令一個myHighlight.directive.scss(或其他)文件,並寫入你的風格:

[myhighlight] { 
    background-color: yellow; 
} 

如果您的應用程序不會自動包括你的風格文件,只需要導入它在你的主樣式文件。對於Ionic 2來說,它是自動拾取的。

如果您想要使用特定的類而不是屬性選擇器,請使用Renderer添加該類。

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

使用第一種方法並不適合我。使用Angular 2.4。 如果我需要導入global.scss,我會丟失樣式封裝。 您只能將自定義類設置爲指令,或者使用不帶視圖封裝的@Component。 – aelkz

+0

適合我。當我將元素選擇器更改爲屬性選擇器並將屬性選擇器添加到我的組件中的'ion-card'元素時,將'parentElement {ion-card {}}'更改爲'[parentElement] {} 。 –

+0

@aelkz:我對聚會有點晚了,但是它適用於Angular 5和Ionic 3.我是否檢查過scss中的選擇器與.ts文件中的選擇器不同?也就是說,在.ts文件中,它通常會顯示「selector:[mySelectorSomething]」,並且爲了使scss具有某種效果,它必須引用全小寫,又名[myselectorsomething]:{},如上例中所述。它很微妙,不太合乎邏輯,所以很容易錯過(至少對我來說)。 – yogibimbi

9

而其他的答案是在大多數情況下有幫助,你似乎需要一個更傳統的CSS樣式表的做法就像我有一個用例。

問題是Angular默認模擬一個Shadow DOM,它只在主機元素中作用於風格。

兩個選項:

1)

你可以告訴角度通過其所有後代使用:host /deep/ .some-style-to-cascade-down-like-normal {}下級聯您的樣式或>>>更換/deep/。關於這個請看Angular's Docs

三個重要的事情需要注意:

  • ViewEncapsulation需要將其默認值(仿真)狀態
  • 角/鉻廢除了這兩種語法,而他們是在一個更好的方法
  • 如果你工作「再使用角CLI,你必須使用,而不是/deep/>>>

2)

雖然你會鬆動範圍的組件封裝(如果你的情況事項),這裏是用「myHighlight」 作爲指令雖然TypeScripted作爲一個組件這樣我就可以導入樣式表的例子:

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

TS(作爲指令處理成分):

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使用相同的方法來解決此問題。

這裏有一篇很棒的文章叫做All the Ways to Add CSS to Angular 2 Components,它引起了我的注意,並解釋了Angular如何處理所有三個ViewEncapsulation屬性。

+2

upvote for「encapsulation:ViewEncapsulation.None」:D –

+0

「Angular Material 2的Button使用相同的方法來解決這個問題。」 - 他們確實使用了你正在使用的技術,而選擇器是指令性的。但與本主題不同的是,他們並未試圖爲指令添加樣式。對於那些決定將它們的指令轉換爲僅用於此樣式優點的組件,您使用的是什麼模板?你可以添加你的。\ my-highlight.component.html所以我們可以看到如何使這項工作?這不會與其他組件相沖突嗎?例如 jcairney

0

同@ m.spyratos,但使用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' 
    ); 
    } 
}