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; }']
})
Это не работает для меня?
Я делаю что-то более сложное, что привело к большому количеству монолитного кода, установлению множества стилей, использованию AnimationBuilder и т.д. и т.д., мне кажется, что было бы намного лучше отделить это от классов и анимаций в CSS.
ViewEncapsulation = emulated/default, если это важно?
Ответы
Ответ 1
Вы можете использовать привязку хоста для привязки к атрибутам стиля:
@Directive({
selector: '[myHighlight]',
host: {
'[style.background-color]': '"yellow"',
}
})
или
@Directive({
selector: '[myHighlight]',
})
class MyDirective {
@HostBinding('style.background-color')
backgroundColor:string = 'yellow';
}
Ответ 2
В то время как другие ответы полезны в большинстве случаев, вам, похоже, нужен более традиционный подход к таблицам стилей CSS, например, у меня был вариант использования.
Проблема заключается в Angular по умолчанию для эмуляции Shadow DOM, который использует стили только внутри элемента хоста.
ДВА ОПЦИИ:
1)
Вы можете сказать Angular каскадировать стили вниз по всем своим потомкам с помощью :host /deep/ .some-style-to-cascade-down-like-normal {}
или заменить /deep/
на >>>
. См. Angular Docs об этом.
Три важных момента:
- ViewEncapsulation должно быть по умолчанию (эмулируемым) состоянием
- Angular/Chrome устаревают оба этих синтаксиса, пока они работают над лучшим подходом
- Если вы используете CLI Angular, вы должны использовать
/deep/
вместо >>>
2)
Хотя вы потеряете инкапсуляцию компонентов с областью (если это имеет значение в вашем случае), вот пример, используя "myHighlight" как директиву, хотя TypeScripted как компонент поэтому я могу импортировать таблицу стилей:
ПРИМЕНЕНИЕ:
<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 Материал 2 Кнопка использует этот же подход для решения этой проблемы.
И вот замечательная статья, называемая Все способы добавления CSS в Angular 2 Компоненты, которые привели меня к этому осознанию и объяснили, как Angular обрабатывает все три свойства ViewEncapsulation.
Ответ 3
Я прочитал ваш комментарий ниже первого ответа. Я не знаю, как вы сможете применить свои 30 правил.
Но здесь несколько способов - плункер.
selector:"[myHighlight]",
host: {
'(mouseenter)':'changeColor()',
'[style.background]': '"pink"',
'(click)':'clickMe()',
'(mouseout)':'changeColorOnOut()',
}
Ответ 4
Просто создайте элемент, как обычно, используя селектор атрибутов. Создайте файл 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);
}
}
Ответ 5
То же, что и @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'
);
}
}