Skip to content

Instantly share code, notes, and snippets.

@dominik-mrugalski
Forked from Banttu/mq-if.directive.ts
Last active March 23, 2020 22:36
Show Gist options
  • Save dominik-mrugalski/059f1a972ed2b9a0b0c099b6abc5511e to your computer and use it in GitHub Desktop.
Save dominik-mrugalski/059f1a972ed2b9a0b0c099b6abc5511e to your computer and use it in GitHub Desktop.
Angular: Conditional output from media query using a structural directive (fixed problem with no-updating view)
import {
Input,
Directive,
TemplateRef,
ViewContainerRef,
OnDestroy,
ChangeDetectorRef
} from '@angular/core';
/**
* How to use this directive?
*
* ```
* <div *mqIf="'(min-width: 500px)'">
* Div element will exist only when media query matches, and created/destroyed when the viewport size changes.
* </div>
* ```
*/
@Directive({
selector: '[mqIf]'
})
export class MqIfDirective implements OnDestroy {
private prevCondition: boolean = null;
i = 0;
private mql: MediaQueryList;
private mqlListener: (mql: MediaQueryList) => void; // reference kept for cleaning up in ngOnDestroy()
constructor(private viewContainer: ViewContainerRef,
private templateRef: TemplateRef<Object>,
private ref: ChangeDetectorRef) {
}
/**
* Called whenever the media query input value changes.
*/
@Input()
set mqIf(newMediaQuery: string) {
if (!this.mql) {
this.mql = window.matchMedia(newMediaQuery);
/* Register for future events */
this.mqlListener = (mq) => {
this.onMediaMatchChange(mq.matches);
};
this.mql.addListener(this.mqlListener);
}
this.onMediaMatchChange(this.mql.matches);
}
ngOnDestroy() {
this.mql.removeListener(this.mqlListener);
this.mql = this.mqlListener = null;
}
private onMediaMatchChange(matches: boolean) {
if (matches && !this.prevCondition) {
this.prevCondition = true;
this.viewContainer.createEmbeddedView(this.templateRef);
} else if (!matches && this.prevCondition) {
this.prevCondition = false;
this.viewContainer.clear();
}
/**
* Infinitive loop when we fire detectChanges during initialization
* (first run on that func)
*/
if (this.i > 0) {
this.ref.detectChanges();
}
else
this.i++;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment