Reputation: 36620
I'm trying to write a appHeaderResize
directive which measures both the height of the <app-online-header>
component and the <app-navigation>
component. Here is the code:
<div class="sticky" appHeaderResize>
<app-online-header></app-online-header>
<app-navigation></app-navigation>
</div>
However I'm stuck at how can I access the height of the two components in the directive. How can I access the height from these components from the directive?
Upvotes: 0
Views: 1400
Reputation: 8306
If you only need the height of the DOM element in your directive, you can inject the ElementRef
and use it to query the DOM children. Then using Renderer2
, you can set styles, attributes, etc for the elements or access their properties:
@Directive({
selector: '[appHeaderResize]'
})
export class AppHeaderResizeDirective {
constructor(
private el: ElementRef,
private renderer: Renderer2
) {}
ngAfterViewInit() {
const arr = Array.from(this.el.nativeElement.childNodes);
const appHeader = arr.find(node => node.tagName === 'APP-HEADER');
this.renderer.setStyle(appHeader, 'display', 'block');
this.renderer.setStyle(appHeader, 'color', 'red');
this.renderer.setStyle(appHeader, 'border', '2px solid red');
this.renderer.setStyle(appHeader, 'height', '200px');
this.renderer.setStyle(appHeader, 'width', '200px');
console.log(appHeader.style.height); // 200px
}
}
(Note: there are other ways to get the node you want besides looking it up based on the tagName
(and those ways don't depend on string pattern matching xD). I just used that approach for proof of concept.)
However, if you want to get the component itself, you'll need to use ViewChild
and nest your elements in a real component.
@Component({
selector: 'app-header-resize',
template: `
<app-header></app-header>
`
})
export class AppHeaderResizeComponent implements AfterViewInit {
@ViewChild(AppHeaderComponent) appHeader: AppHeaderComponent;
@ViewChild(AppHeaderComponent, {read: ElementRef}) appEl: ElementRef;
constructor(private renderer: Renderer2) {}
ngAfterViewInit() {
console.log(this.appHeader);
const height = this.appHeader.height + 'px';
this.renderer.addClass(this.appEl.nativeElement, 'square');
this.renderer.setStyle(this.appEl.nativeElement, 'display', 'block');
this.renderer.setStyle(this.appEl.nativeElement, 'height', height);
this.renderer.setStyle(this.appEl.nativeElement, 'border', '2px solid blue');
}
}
Here is a working app with both approaches: https://stackblitz.com/edit/app-header-child.
Upvotes: 3