【Angular】動的にCSSを変更する方法

# はじめに
CSSを動的に変更する方法でバインディングや直接DOM操作と何パターンかあるのでまとめることにしました。
今後、Angularで実装する方の参考になればと思います。

# バージョン
・Angular: 9.1.11
バージョンの確認方法については過去記事に記載しております。

https://qiita.com/Shogongon/items/81c8a26028c82892a5c4#%E3%83%90%E3%83%BC%E3%82%B8%E3%83%A7%E3%83%B3

# NgStyle
参考：[Angular:NgStyle](https://angular.jp/api/common/NgStyle)
```tsx:test.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-test',
  templateUrl: './test.component.html'
})
export class TestComponent {
  color = "red";
  style = {'width': '50px', 'height': '50px','background-color':'red'};

  constructor() { }

  onClickChangeColor() {
    this.color = "blue";
  }

  onClickChangeObject() {
    this.style = {'width': '100px', 'height': '100px','background-color':'blue'};
  }
}
```
```html:test.component.html
<div [ngStyle]="{'width': '100px', 'height': '100px','background-color': color}"></div>
<button (click)="onClickChangeColor()">カラー変更</button>

<div [ngStyle]="style"></div>
<button (click)="onClickChangeObject()">オブジェクト変更</button>
```

# style binding
参考：[Angular:Class and style binding](https://angular.jp/guide/class-binding)
```tsx:test.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-test',
  templateUrl: './test.component.html'
})
export class TestComponent {
  color1 = "red";
  color2 = "red";
  style = {'width': '50px', 'height': '50px','background-color':'red'};

  constructor() { }

  onClickChangeColor1() {
    this.color1= "blue";
  }

  onClickChangeColor2() {
    this.color2= "blue";
  }

  onClickChangeObject() {
    this.style = {'width': '100px', 'height': '100px','background-color':'blue'};
  }
}
```
```html:test.component.html
<div [style.background-color]="color1" style="width: 100px; height : 100px;"></div>
<button (click)="onClickChangeColor1()">カラー変更1</button>

<div [style]="{'width': '100px', 'height': '100px','background-color': color2}"></div>
<button (click)="onClickChangeColor2()">カラー変更2</button>

<div [style]="style"></div>
<button (click)="onClickChangeObject()">オブジェクト変更</button>
```

# Renderer2
参考：[Angular:Renderer2](https://angular.io/api/core/Renderer2)
```tsx:test.component.ts
import { Component, ViewChild, ElementRef, Renderer2 } from '@angular/core';

@Component({
  selector: 'app-test',
  templateUrl: './test.component.html'
})
export class TestComponent {
	@ViewChild('element') public element: ElementRef;

  constructor(
    private renderer: Renderer2
  ) { }

  ngAfterViewInit(): void {
    console.log(this.element);
  }

  onClickChangeColor() {
    this.renderer.setStyle(this.element.nativeElement, 'background-color', 'blue');
  }
}
```
```html:test.component.html
<div #element style="width: 100px; height: 100px; background-color: red"></div>
<button (click)="onClickChangeColor()">カラー変更</button>
```

# 注意
下記二つは推奨されていません。
基本的にはDOMに直接アクセスするのは良くないみたいです。
詳しくは[Angular:ElementRef#properties](https://angular.jp/api/core/ElementRef#properties)の**USE WITH CAUTION**をご確認ください

## ViewChild
参考：[Angular:ViewChild](https://angular.jp/api/core/ViewChild)
```tsx:test.component.ts
import { Component, ViewChild, ElementRef } from '@angular/core';

@Component({
  selector: 'app-test',
  templateUrl: './test.component.html'
})
export class TestComponent {
	@ViewChild('element') public element: ElementRef;

  constructor() { }

  public ngAfterViewInit(): void {
    this.element.nativeElement.style.width = "100px";
    this.element.nativeElement.style.height = "100px";
    this.element.nativeElement.style.backgroundColor = "red";
  }

  onClickChangeColor() {
    this.element.nativeElement.style.backgroundColor = "blue";
  }
}
```
```html:test.component.html
<div #element></div>
<button (click)="onClickChangeColor()">カラー変更</button>
```

## ViewChildren
参考：[Angular:ViewChildren](https://angular.jp/api/core/ViewChildren)
※`#elements`には`QueryList`がセットされているため詳細な使い方は[Angular:QueryList](https://angular.io/api/core/QueryList)を確認してください。
```tsx:test.component.ts
import { Component, ViewChildren, QueryList, ElementRef } from '@angular/core';

@Component({
  selector: 'app-test',
  templateUrl: './test.component.html'
})
export class TestComponent {
	@ViewChildren('elements') public elements: QueryList<ElementRef>;

  constructor() { }

  public ngAfterViewInit(): void {
    console.log(this.elements);
  }

  onClickChangeColor() {
    for(let element of this.elements) {
      element.nativeElement.style.width = "100px";
      element.nativeElement.style.height = "100px";
      switch(element.nativeElement.id) {
        case "ele1":
          element.nativeElement.style.backgroundColor = "red";
          break;

        case "ele2":
          element.nativeElement.style.backgroundColor = "blue";
          break;

        case "ele3":
          element.nativeElement.style.backgroundColor = "yellow";
          break;
      }
    }
  }
}
```
```html:test.component.html
<div #elements id="ele1"></div>
<div #elements id="ele2"></div>
<div #elements id="ele3"></div>
<button (click)="onClickChangeColor()">カラー変更</button>
```

# 補足
- `#element`,`#elements`はテンプレート変数です。テンプレート変数は[Angular:Understanding template variables](https://angular.jp/guide/template-reference-variables)を確認してください。
- ViewChild、ViewChildrenで`#element`,`#elements`取得時の注意
    - `#element`,`#elements`はngAfterViewInit()以降で取得することができます。
    - ちなみにngAfterViewInit()はライフサイクルの一つです。
    - ライフサイクルの順序は下記のようになっています。
        - ngOnChanges()
        - ngOnInit()
        - ngDoCheck()
        - ngAfterContentInit()
        - ngAfterContentChecked()
        - ngAfterViewInit()
        - ngAfterViewChecked()
        - ngOnDestroy()

# 参考文献
[Angular:NgStyle](https://angular.jp/api/common/NgStyle)
[Angular:Class and style binding](https://angular.jp/guide/class-binding)
[Angular:Renderer2](https://angular.io/api/core/Renderer2)
[Angular:ViewChild](https://angular.jp/api/core/ViewChild)
[Angular:ViewChildren](https://angular.jp/api/core/ViewChildren)
[Angular:ElementRef#properties](https://angular.jp/api/core/ElementRef#properties)
[Angular:QueryList](https://angular.io/api/core/QueryList)
[Angular:Understanding template variables](https://angular.jp/guide/template-reference-variables)