Как добавить «класс» к элементу хоста?


190

Я не знаю, как добавить к моему компоненту атрибут <component></component>динамического класса, но внутри шаблона html (component.html).

Единственное решение, которое я нашел, это изменить элемент с помощью нативного элемента "ElementRef". Это решение кажется немного сложным, чтобы сделать что-то, что должно быть очень простым.

Другая проблема заключается в том, что CSS должен быть определен вне области компонента, нарушая инкапсуляцию компонента.

Есть ли более простое решение? Что-то вроде <root [class]="..."> .... </ root>внутри шаблона.

Ответы:


296
@Component({
   selector: 'body',
   template: 'app-element',
   // prefer decorators (see below)
   // host:     {'[class.someClass]':'someField'}
})
export class App implements OnInit {
  constructor(private cdRef:ChangeDetectorRef) {}

  someField: boolean = false;
  // alternatively also the host parameter in the @Component()` decorator can be used
  @HostBinding('class.someClass') someField: boolean = false;

  ngOnInit() {
    this.someField = true; // set class `someClass` on `<body>`
    //this.cdRef.detectChanges(); 
  }
}

Пример плунжера

Таким образом, вам не нужно добавлять CSS за пределы компонента. CSS как

:host(.someClass) {
  background-color: red;
}

работает изнутри компонента, а селектор применяется, только если класс someClassустановлен на элементе хоста.


Я должен был сделать someField = trueв ngOnInit()-методе вместо ngAfterViewInit(). Я не мог заставить это работать иначе.
Джон

Сделал здесь развилку, которая показывает фактическую :hostчасть работы. Где я могу узнать больше о параметре хоста в декораторе @Component () (синтаксис для меня неочевиден, а документация @Component мало что объясняет ) или узнать больше о предпочитаемом HostBinding (он указан только как Интерфейс на Сайт Angular2?)
Красный горох

Я не знаю лучших документов, но это просто другой способ делать то, что вы можете сделать@Input() @Output() @HostBinding() @HostListener() @ViewChild(ren)() @ContentChild(ren)()
Гюнтер Цохбауэр

1
использовать привязку с другим именем для привязки хоста, которая возвращает инвертированное значение@HostBinding('class.xxx') get xxxclass(){ return !this.someField;}
Günter Zöchbauer

1
@YochaiAkoka не уверен, что вы имеете в виду. Я не знаю об этом правиле. Меньше, как правило, больше, поэтому, если вы можете избежать добавления дополнительных элементов, вам следует избегать этого.
Гюнтер Цохбауэр,

184

Ответ Гюнтера великолепен (вопрос требует атрибута динамического класса), но я подумал, что добавлю только для полноты ...

Если вы ищете быстрый и понятный способ добавить один или несколько статических классов к элементу host вашего компонента (т. Е. Для целей оформления тем), вы можете просто сделать:

@Component({
   selector: 'my-component',
   template: 'app-element',
   host: {'class': 'someClass1'}
})
export class App implements OnInit {
...
}

И если вы используете класс в теге entry, Angular объединит классы, т.е.

<my-component class="someClass2">
  I have both someClass1 & someClass2 applied to me
</my-component>

1
Люблю это для простоты. Однако в моем случае элемент хоста инкапсулирован с другим атрибутом, давайте назовем его, ngcontent_hostчем любой из атрибутов элементов в моем шаблоне , let's call those ngcontent_template , so if I put a style in the styleUrls` моего компонента, они не будут влиять на элемент хоста, потому что они не будут влиять ngcontent_host, они может влиять только на элементы шаблона; они могут только влиять ngcontent_template. Я ошибаюсь? Есть предложения по этому поводу? Я думаю, что я всегда мог повернутьViewEncapsulation.None
Красный горох

11
Другой способ - просто пропустить переменную @HostBinding('class.someClass') true;. Вы даже можете сделать это из любого класса, который расширяет ваш компонент.
adamdport

3
Чтобы добавить несколько классов, вы можете сделать host: {'[class]': '"class1 class2"'}
jbojcic

4
Если вы используете {}вариант host:, вы можете установить use-host-property-decoratorзначение falsein tslint.json. В противном случае вы получите предупреждения IDE. @adamdport Этот метод больше не работает. Используя Angular 5.2.2 в нашем приложении.
Рууд Воост

1
Это только я, или старый способ кажется лучше, чем новый? Я уверен, что у них были веские причины для миграции, но,
раздавить

13

Вы можете просто добавить @HostBinding('class') class = 'someClass';в свой класс @Component .

Пример:

@Component({
   selector: 'body',
   template: 'app-element'       
})
export class App implements OnInit {

  @HostBinding('class') class = 'someClass';

  constructor() {}      

  ngOnInit() {}
}

1
Имя класса директива может также использоваться и лучше избегать использования в classкачестве имени переменной (так как вы можете ссылаться на него и изменить его позже). Пример: @HostBinding('className') myTheme = 'theme-dark';.
CPHPython

3

Если вы хотите добавить динамический класс к вашему хост-элементу, вы можете объединить его HostBindingс геттером как

@HostBinding('class') get class() {
    return aComponentVariable
}

Демонстрация Stackblitz по адресу https://stackblitz.com/edit/angular-dynamic-hostbinding


0

Вот как я это сделал (Angular 7):

В компонент добавьте вход:

@Input() componentClass: string = '';

Затем в HTML-шаблон компонента добавьте что-то вроде:

<div [ngClass]="componentClass">...</div>

И, наконец, в шаблоне HTML, где вы создаете экземпляр компонента:

<root componentClass="someclass someotherclass">...</root>

Отказ от ответственности: я довольно новичок в Angular, так что, возможно, мне просто повезло здесь!


2
Немного некро, но: это не добавляет класс CSS к элементу хоста - который является элементом для <root>тега, а не чем-либо, что вы добавляете в шаблон элемента.
миллимус
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.