Search code examples
angularangular-directive

Angular directive for detect screen size


Help me, please, how can I do that?

I want to apply directive to the divs, it will be show or hide content depending of it's value, for example: *ifViewportSize="'mobile'"

<div *ifViewportSize="'large'">PC</div>
<div *ifViewportSize="'small'">Mobile</div>

Directive: (rezult in console.log) https://stackblitz.com/edit/angular-ivy-wdl8ee

@Directive({
  selector: '[ifViewportSize]'
})
export class IfViewportSizeDirective {

size: string;

  config = {
    large: 992,
    medium: 768,
    small: 576
  };

  constructor(
    private elemRef: ElementRef,
    private vcRef: ViewContainerRef,
    private templRef: TemplateRef<any>) {

    window.onresize = (event) => {
      this.showElem();
    };
  }

  @Input() set ifViewportSize(size: string) {
    this.size = size;
  }

  ngOnInit() {
    this.showElem();
  }

  showElem() {
    console.log('size: ',this.size);

    if (this.config[this.size] < window.innerWidth) {
      this.vcRef.clear();
      this.vcRef.createEmbeddedView(this.templRef);
    }
    else this.vcRef.clear();
  }

}

Directive works only in the last div. Please tell me why?

Also I tried to create (right here, on stackblitz) separately directives ifMobile и ifTablet. I implemented there a function window.onresize, but again this function works only on the last div.

How can I fix it? If this is a wrong way to detect the screen size, how can I do this right? Thanks a lot!


Solution

  • You can take advantage of let directive with $implicit context in angular being used with structural directive normally as below,


    <div *ifViewportSize="let view=$implicit"> .... </div>
    

    import { Directive, ElementRef, ViewContainerRef, TemplateRef, OnInit, Input, HostListener } from '@angular/core';
    
    export enum VIEW{
      MOBILE ,
      TABLET ,
      PC 
    }
    
    @Directive({
      selector: '[responsive]'
    })
    export class IfViewportSizeDirective {
    
      view;
    
      config = {
        large: 1200,
        medium: 700,
        small: 500
      };
    
      constructor(private readonly viewRef: ViewContainerRef,
            private readonly templateRef: TemplateRef<any>) {  this.checkView();}
    
      ngOnInit(){
          window.addEventListener('resize', this.checkView.bind(this));
      }
    
     
      checkView() {
        this.viewRef.clear();
    
         console.log(window.innerWidth);
         if((0 < window.innerWidth) && (window.innerWidth < this.config['small'] )){
           
           this.view = VIEW.MOBILE;
           
         } else if((this.config['small'] < window.innerWidth) && (window.innerWidth < this.config['medium'])){
    
           this.view = VIEW.TABLET;
           
         } else if(this.config['medium'] < window.innerWidth){
          
          this.view = VIEW.PC;
         }
         
      
         this.viewRef.createEmbeddedView(this.templateRef,{
                        $implicit: this.view
         });
        }
      
    
    }
    

    FULL DEMO

    NOTE: you can still optimize it.