Elastic ion-textarea

@Oldstadt I managed to use an elastic textarea in ion-footer resizing the content when the footer or header height change using a directive that listen to changes in the dimensions of the ion-header and ion-footer components.

Actually you can do this even under other circumstances aside from having a textarea in footer, its a general approach to resize the content without having to explicitly call it every time its height change.

The directive:

import { AfterViewInit, Directive, ElementRef, EventEmitter, OnDestroy, Output } from '@angular/core';

interface Subscription {
	unsubscribe: () => void;
}

@Directive({
	selector: '[myResize]'
})
export class ResizeDirective implements AfterViewInit, OnDestroy {

	@Output('myResizeChange')
	public resizeChange = new EventEmitter<ElementRef>();

	private subscription: Subscription;

	constructor(
		private elementRef: ElementRef,
	) { }

	public ngAfterViewInit(): void {
		let element: HTMLElement = this.elementRef.nativeElement;
		this.subscription = this.subscribe(element, () => {
			this.resizeChange.emit(this.elementRef);
		});
	}

	private subscribe(element: HTMLElement, callback: () => void): Subscription {
		let offsetWidth = element.offsetWidth;
		let offsetHeight = element.offsetHeight;

		let checkForChanges = () => {
			if (
				(offsetWidth !== element.offsetWidth)
				||
				(offsetHeight !== element.offsetHeight)
			) {
				offsetWidth = element.offsetWidth;
				offsetHeight = element.offsetHeight;
				callback();
			}
		};

		let observer = new MutationObserver(() => checkForChanges());
		let config = {
			attributes: true,
			childList: true,
			characterData: true,
			subtree: true,
			attributeFilter: ['style'],
		};
		observer.observe(element, config);

		let subscription: Subscription = {
			unsubscribe: () => observer.disconnect(),
		};

		return subscription;
	}

	public ngOnDestroy(): void {
		this.subscription && this.subscription.unsubscribe();
	}
}

Then in your page HTML just do:

<ion-header myResize (myResizeChange)="onResize()">
	...
</ion-header>

<ion-content>
	...
</ion-content>

<ion-footer myResize (myResizeChange)="onResize()">
	...
</ion-footer>

And in your page .ts file:

import { Component, ViewChild } from '@angular/core';
import { Content } from 'ionic-angular';

@Component({
	selector: 'my-page',
	templateUrl: 'my.page.html',
})
export class MyPage {

	@ViewChild(Content) 
	public content: Content;

	constructor() { }

	public onResize(): void {
		console.log('resize');		
		this.content.resize();
	}
}

(Remember to declare the directive and the page in your module.)

And that’s it! It worked fine for me.