Search code examples
javascriptangulartwitter-bootstraptypescriptngx-bootstrap

Disable Angular component


we are using ngx-bootstrap in our Angular application. More specifically, we are using the tooltip directive. However, we do not want to display tooltips on mobile so we are looking for a way to globally disable the tooltip directive once the screen size falls under a certain threshold.

While there is a way to disable a single tooltip directive via the tooltip-enabled attribute, we are looking for a way to disable all tooltips with a single switch. What would be the best way to achieve this goal?

Many thanks


Solution

  • Here is a generic solution using an angular directive ToggleTooltipDirective that sets the tooltip isDisabled attribute. This directive automatically targets every element with a TooltipDirective.

    The directive is automatically added to the proper elements by angular by declaring it using the '[tooltip]:not([toggleTooltip]),[toggleTooltip]' selector.

    Here is a working demo on StackBlitz

    Using this solution, the tooltip is disabled using the API provided by ngx-bootstrap. Also, the toggling can be easily controlled via a service as shown below.

    import { Directive, OnDestroy } from '@angular/core';
    import { Subscription } from 'rxjs';
    import { TooltipDirective } from 'ngx-bootstrap/tooltip';
    import { TooltipControlService } from './tooltip-control.service';
    
    @Directive({
      selector: '[tooltip]:not([toggleTooltip]),[toggleTooltip]'
    })
    export class ToggleTooltipDirective implements OnDestroy {
      private subscription: Subscription;
    
      constructor(
        private tooltip: TooltipDirective,
        private tooltipControlService: TooltipControlService) {
          this.subscription = this.tooltipControlService.disabled$.subscribe(
            disabled => this.tooltip.isDisabled = disabled
          );
      }
    
      ngOnDestroy(): void {
        this.subscription.unsubscribe();
      }
    }
    

    And here is a service so you can enable/disable from anywhere. The service also uses the LayoutModule from @angular/cdk to detect when the screen dimensions change and do the toggling.

    import { Injectable } from '@angular/core';
    import { BreakpointObserver, BreakpointState } from '@angular/cdk/layout';
    import { BehaviorSubject, Observable } from 'rxjs';
    
    @Injectable({ providedIn: 'root' })
    export class TooltipControlService {
      private disabledSubject = new BehaviorSubject(false);
    
      disabled$: Observable<boolean> = this.disabledSubject.asObservable();
    
      constructor(public breakpointObserver: BreakpointObserver) {
        this.breakpointObserver
          .observe(['(max-width: 1280px)'])
          .subscribe((state: BreakpointState) => {
            if (state.matches) {
              this.disable();
              console.log('Small viewport');
            } else {
              this.enable();
              console.log('Big viewport');
            }
          });
      }
    
      enable(): void {
        this.disabledSubject.next(false);
      }
    
      disable(): void {
        this.disabledSubject.next(true);
      }
    }
    

    Your app module:

    import { NgModule } from '@angular/core';
    import { BrowserModule } from '@angular/platform-browser';
    import { FormsModule } from '@angular/forms';
    import { LayoutModule } from '@angular/cdk/layout';
    import { TooltipModule } from 'ngx-bootstrap/tooltip';
    import { AppComponent } from './app.component';
    import { HelloComponent } from './hello.component';
    import { ToggleTooltipDirective } from './toggle-tooltip.directive';
    
    @NgModule({
      imports:      [ BrowserModule, FormsModule, LayoutModule, TooltipModule.forRoot() ],
      declarations: [ AppComponent, HelloComponent, ToggleTooltipDirective ],
      bootstrap:    [ AppComponent ]
    })
    export class AppModule { }
    
    

    Hope this helps.