1.0.1 • Published 2 years ago

ng-media-query-service v1.0.1

Weekly downloads
-
License
MPL-2.0
Repository
github
Last release
2 years ago

MediaQueryService for Angular

Angular MediaQueryService is a lightweight Angular service designed to facilitate accessing media queries programatically and being able to subscribe to these values for responsive props.

This library allows you to leverage the power and flexibility of CSS media queries directly in your TypeScript code. Ir simplifies the process of programatic media queries by providing a way to react to changes in media query match status in real-time, directly in your components. It eliminates the need for manual DOM manipulation or window resize event listeners, making your code cleaner and easier to understand.

I'll be honest. I'm working in an Angular shop after many years of React and I found myself missing the useMediaQuery hook and this was my effort to angularize it.

Installation

$ npm install ng-midia-query-service
$ yarn add ng-midia-query-service
$ pnpm install ng-midia-query-service

Usage

First, add MediaQueryService to the providers array of the module in which you want to consume it.

import {MediaQueryService} from 'ng-media-query-service';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule
  ],
  providers: [MediaQueryService],
  bootstrap: [AppComponent]
})

export class AppModule { }

API Option #1 - Async Pipe

The cleaner option, in my opinion, is to make use of the async pipe in order to avoid manual subscription management in the component file.

Component:

import { Component, OnInit } from '@angular/core';
import { MediaQueryService } from 'ng-media-query-service';
import { Observable } from 'rxjs';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
})
export class AppComponent implements OnInit {
  matchMobile$: Observable<boolean>;
  matchDesktop$: Observable<boolean>;
  matchTablet$: Observable<boolean>;

  constructor(private mediaQueryService: MediaQueryService) {}

  ngOnInit(): void {
    this.matchMobile$ = this.mediaQueryService.match('(max-width: 767px)');
    this.matchTablet$ = this.mediaQueryService.match('(min-width: 768px) and (max-width: 991px)');
    this.matchDesktop$ = this.mediaQueryService.match('(min-width: 992px)');
  }
}

Template:

<div>
  <p *ngIf="matchMobile$ | async">This is a mobile viewport</p>
  <p *ngIf="matchTablet$ | async">This is a tablet viewport</p>
  <p *ngIf="matchDesktop$ | async">This is a desktop viewport</p>
</div>

API Approach 2: Managed Subscriptions

Alternatively, you can also manually subscribe in your component instead of using the async pipe.

Component:

import { Component, OnInit, OnDestroy } from '@angular/core';
import { MediaQueryService } from './path-to-your-media-query-service';
import { Subscription } from 'rxjs';

@Component({
  selector: 'app-viewport-status',
  templateUrl: './viewport-status.component.html'
})
export class ViewportStatusComponent implements OnInit, OnDestroy {
  matchMobile: boolean;
  matchDesktop: boolean;
  matchTablet: boolean;
  private subs: Subscription[] = [];

  constructor(private mediaQueryService: MediaQueryService) {}

  ngOnInit(): void {
    this.subs.push(
      this.mediaQueryService.match('(max-width: 767px)').subscribe(isMatched => {
        this.matchMobile = isMatched;
      })
    );

    this.subs.push(
      this.mediaQueryService.match('(min-width: 768px) and (max-width: 991px)').subscribe(isMatched => {
        this.matchTablet = isMatched;
      })
    );

    this.subs.push(
      this.mediaQueryService.match('(min-width: 992px)').subscribe(isMatched => {
        this.matchDesktop = isMatched;
      })
    );
  }

  ngOnDestroy(): void {
    this.subs.forEach(sub => sub.unsubscribe());
  }
}

Template:

<div>
  <p *ngIf="matchMobile">This is a mobile viewport</p>
  <p *ngIf="matchTablet">This is a tablet viewport</p>
  <p *ngIf="matchDesktop">This is a desktop viewport</p>
</div>
1.0.1

2 years ago

1.0.0

2 years ago