Last active
March 26, 2021 05:08
-
-
Save davidmarquis/80e6d1ada3a024022f985a587b587825 to your computer and use it in GitHub Desktop.
Angular 2: Conditional output from media query using a structural directive
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Directive, TemplateRef, ViewContainerRef } from "@angular/core"; | |
import { isBlank } from "@angular/core/src/facade/lang"; | |
/** | |
* How to use this directive? | |
* | |
* ``` | |
* <div *ngIfMediaQuery="'(min-width: 500px)'"> | |
* Div element will exist only when media query matches, and created/destroyed when the viewport size changes. | |
* </div> | |
* ``` | |
*/ | |
@Directive({ | |
selector: '[ngIfMediaQuery]', | |
inputs: ['ngIfMediaQuery'] | |
}) | |
export class NgIfMediaQuery { | |
private prevCondition: boolean = null; | |
private mql: MediaQueryList; | |
private mqlListener: (mql: MediaQueryList) => void; // reference kept for cleaning up in ngOnDestroy() | |
constructor(private viewContainer: ViewContainerRef, private templateRef: TemplateRef<Object>) {} | |
/** | |
* Called whenever the media query input value changes. | |
*/ | |
set ngIfMediaQuery(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) { | |
// this has been taken verbatim from NgIf implementation | |
if (matches && (isBlank(this.prevCondition) || !this.prevCondition)) { | |
this.prevCondition = true; | |
this.viewContainer.createEmbeddedView(this.templateRef); | |
} else if (!matches && (isBlank(this.prevCondition) || this.prevCondition)) { | |
this.prevCondition = false; | |
this.viewContainer.clear(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment