简体   繁体   中英

Angular 2 Directive inside html body tag

I am trying to create a directive that I can use inside of the html body element.

The purpose of this directive is to add or remove a class.

There must be a service that determine if the class should be visible or not, because I will need to control this from different components.

Question: How do i toggle the class on my body element with the help of my service.

sticky-search.directive.ts

import { Directive, HostBinding, Inject, HostListener } from '@angular/core';
import { DOCUMENT } from '@angular/platform-browser';

import { SearchService } from '../shared/search.service';

@Directive({
  selector: '[mhStickySearch]'
})
export class StickySearchDirective {

  @HostBinding('class') onStickySearch() {
    return this.searchService.isSearchSticky ? 'search-sticky' : '';
  }

  @HostListener('window:scroll', []) onWindowScroll() {
    let number = this.document.body.scrollTop;

    if (number >= 65) {
      this.searchService.enableStickySearch();
    } else {
      this.searchService.disableStickySearch();
    }
  }

  constructor(private searchService: SearchService, @Inject(DOCUMENT) private document: any) { }
}

The following directive's @Hostlistner is not triggering if i put it inside the body tag. But if i place it as a parent the @HostListner is triggered but no class is displaying.

Here is my body tag that the AppComponent uses as a selector but that lays as a parent of the component

<body class="full-width" mhStickySearch>

search.service.ts

import { Injectable } from '@angular/core';

@Injectable() export class SearchService {

  isSearchSticky: boolean;

  enableStickySearch() {
    this.isSearchSticky = true;   
  }

  disableStickySearch() {
    this.isSearchSticky = false;   
  }

  constructor() { }

}

The SearchService is provided in the AppComponent . The service is executed from my HeaderComponent like this:

import { Component } from '@angular/core';
import { SearchService } from '../../search/shared/search.service';

@Component({
  selector: 'mh-header',
  templateUrl: './header.component.html'
})
export class HeaderComponent {
  constructor(private searchService: SearchService) {}

  openMobileMenu() {
    this.searchService.enableStickySearch();
  }

  closeMobileMenu() {
    this.searchService.disableStickySearch();
  }
}

The problem was that i can't use directives outside of the AppComponent.

So I solved the issue by removing my directive and triggered vanilla javascript from my service.

import { Injectable } from '@angular/core';

@Injectable()
export class SearchService {

  isSearchSticky: boolean;

  enableStickySearch() {
    window.document.body.classList.add('search-sticky');
    this.isSearchSticky = true;
  }

  disableStickySearch() {
    window.document.body.classList.remove('search-sticky');
    this.isSearchSticky = true;
  }

  constructor() {
    const that = this;

    window.onscroll = function () {
      let number = this.document.body.scrollTop;

      if (number >= 65) {
        that.enableStickySearch();
      } else {
        that.disableStickySearch();
      }
    };
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM