たとえば、子供の要素のリサイズとかはflexboxに任せたいんだけど、リサイズ結果にアクセスしたいので、ネイティブ要素にアクセスしたい、子供の要素のサイズを計算して後から同じにしたい・・・そんなことありますよね?
Angular Materialのmat-button-toggleを使ってボタンを並べているんだけど、幅を統一したいとします。
my-list.component.html
<mat-button-toggle-group [value]="innerValue" (change)="handleChange($event)">
<mat-button-toggle *ngFor="let option of cleanedOptions" [value]="option.value">
{{option.label}}
</mat-button-toggle>
</mat-button-toggle-group>
ふつうに@ViewChildren
を使うと、子供のコンポーネントが取得されて、そのネイティブのエレメントを取得するには_elementRefという非公式なプライベートっぽい属性があったので、これにアクセスしてとってきていたのですが、絶対違うな、と思って調べてみました。
こんな感じで、@ViewChildren
に{read: ElementRef}
をつけると、子供のコンポーネントのElementRefが取得できることがわかりましたので、行儀の悪い方法は使わなくてもすみます。
my-list.component.ts
import {
Component,
AfterViewInit,
ViewChildren,
QueryList,
ElementRef
} from '@angular/core';
import {
MatButtonToggle
} from '@angular/material/button-toggle';
@Component({
selector: 'my-list',
templateUrl: './my-list.component.html',
styleUrls: ['./my-list.component.scss']
})
export class MyListComponent implements AfterViewInit {
@ViewChildren(MatButtonToggle, { read: ElementRef })
children: QueryList<ElementRef>;
ngAfterViewInit() {
let maxWidth = 0;
this.children.forEach(child => {
maxWidth = Math.max(
maxWidth,
child.nativeElement.getBoundingClientRect().width
);
console.log(child.nativeElement.getBoundingClientRect());
});
this.children.forEach(child => {
child.nativeElement.style.width = `${maxWidth}px`;
});
}
}
あとは、ngAfterViewInit()の中で子供の要素のネイティブな属性にアクセスできるので、ここで最大の長さの子供の幅を採ってきて、全部に設定してあげれば、全部の子供の幅を同じにできますね。めでたしめでたい。