2016-03-10 54 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' 
    ); 
    } 
}