Binding to Element Size
Basic implementation
import { bindable, BindingMode, customAttribute } from 'aurelia';
@customAttribute({
name: 'rectsize',
hasDynamicOptions: true
})
export class RectSize {
public static inject = [INode];
@bindable({ mode: BindingMode.fromView })
public value!: ResizeObserverSize;
@bindable()
public boxSize!: 'border-box' | 'content-box';
private observer!: ResizeObserver;
constructor(
private readonly element: HTMLElement
) {
}
public binding(): void {
let observer = this.observer;
if (observer === void 0) {
observer = this.observer = this.createObserver();
}
observer.observe(this.element, { box: 'border-box' });
}
public unbinding(): void {
this.observer.disconnect();
this.observer = (void 0)!;
}
private createObserver(): ResizeObserver {
return new ResizeObserver((entries) => {
this.handleResize(entries[0]);
});
}
/**
* @internal
*/
private handleResize(entry: ResizeObserverEntry): void {
this.value = this.boxSize === 'content-box' ? entry.contentBoxSize : entry.borderBoxSize;
}
}Working with polyfill
As ResizeObserver is still new and experimental API, it's not widely supported in all browsers. Fortunately there are a few polyfills available. For example:
older spec, with only
contentRect: https://github.com/que-etc/resize-observer-polyfillnewer spec, with supports for box model options: https://github.com/juggle/resize-observer
To make the attribute work seamlessly with any polyfill users want to choose, we can adjust the way we get the ResizeObserver constructor, as shown in the following example:
And now, our user can switch to any polyfill as the following example:
Example usage
For the above implementation, the usage would be:
Special note:
For the polyfill at https://github.com/que-etc/resize-observer-polyfill , you cannot use box-model for observation option, as it follows an older spec of ResizeObserver. Though it is a mature polyfill, and works well so if you want to use it, slightly modify the above implementation:
Last updated
Was this helpful?