Angular2 Styles in Directive

In the examples of attribute directives (i.e., directives for adding appearance / behavior), we have a fairly simple style setting for the host element. For example,

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

Instead of setting a style, can I use styles instead? eg.

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

This does not work for me?

I am doing something more complex, which has led to a lot of monolithic code, setting a lot of styles, using AnimationBuilder, etc. etc., it seems to me that it would be much better to separate this from classes and animations in CSS.

ViewEncapsulation = emulated / default, if this is important?

+21
angular angular2-directives
Mar 10 '16 at 11:38
source share
5 answers

You can use host binding to bind to style attributes:

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

or

 @Directive({ selector: '[myHighlight]', }) class MyDirective { @HostBinding('style.background-color') backgroundColor:string = 'yellow'; } 
+19
Mar 10 '16 at 11:41
source share

While other answers are useful in most cases, you seem to need a more traditional approach to CSS style sheets, for example, I had a use case.

The problem is Angular's default for emulating the Shadow DOM, which only uses styles inside the host element.

TWO OPTIONS:

one)

You can tell Angular to cascade styles down all its descendants with :host /deep/ .some-style-to-cascade-down-like-normal {} or replace /deep/ with >>> . See Angular Docs about this.

Three important points:

  • ViewEncapsulation should be the default (emulated) state
  • Angular / Chrome deprecates both of these syntaxes while they work on a better approach
  • If you use the Angular CLI, you should use /deep/ instead of >>>

2)

Although you will lose the encapsulation of components with scope (if that matters in your case), here is an example using "myHighlight" as a directive , although TypeScripted as a component so I can import the stylesheet:

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

TS (component is considered as a directive):

 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 Button uses the same approach to solve this problem.

And here's a great article, called All Ways to Add CSS to Angular 2 Components that brought me to this awareness and explained how Angular handles all three ViewEncapsulation properties.

+9
Mar 14 '17 at 18:36
source share

I read your comment below the first answer. I don’t know how you can apply your 30 rules. But there are several ways - a plunker .

 selector:"[myHighlight]", host: { '(mouseenter)':'changeColor()', '[style.background]': '"pink"', '(click)':'clickMe()', '(mouseout)':'changeColorOnOut()', } 
+3
Mar 10 '16 at 12:01
source share

Just create the element as usual using the attribute selector. Create the file myHighlight.directive.scss (or any other) in the same folder as your directive, and write the styles there:

 [myhighlight] { background-color: yellow; } 

If your application does not automatically include your style file, simply import it into the main style file. For me, in Ionic 2, it was automatically selected.

If you want to use a specific class instead of the attribute selector, use Renderer to add the class.

 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); } } 
+1
Oct 21 '16 at 10:56
source share

Same as @ m.spyratos, but using 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' ); } } 
0
Nov 27 '17 at 14:57
source share



All Articles