N
N
Nikita Sokolov2019-07-13 16:39:15
Angular
Nikita Sokolov, 2019-07-13 16:39:15

What's wrong with my Angular 8 directive?

The essence of the task is to simply show the element (in my case, a drop-down menu) when hovering over a menu item. I understand that this can be done simply with css, but I want to learn how to use custom directives.
In general, this is with-secondary-menu.directive.ts

import { Directive, ElementRef, HostListener } from '@angular/core';

@Directive({
  selector: '[withSecondaryMenu]'
})
export class WithSecondaryMenuDirective {
  
  show: boolean = false;
  constructor(private el: ElementRef) {

    @HostListener('mouseenter') onMouseEnter() {
      this.show = true;
    }
    
    @HostListener('mouseleave') onMouseLeave() {
      this.show = false;
    }

  }

}

app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppRoutingModule, routingComponents } from './app-routing.module';
import { AppComponent } from './app.component';
import { NavbarComponent } from './navbar/navbar.component';
import { FooterComponent } from './footer/footer.component';
import { WithSecondaryMenuDirective } from './with-secondary-menu.directive';

@NgModule({
  declarations: [
    AppComponent,
    NavbarComponent,
    FooterComponent,
    routingComponents,
    WithSecondaryMenuDirective
  ],
  imports: [
    BrowserModule,
    AppRoutingModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

navbar.component.html
<nav>
    <ul>
        <li>
            <a routerLink="" class="bold">Заказать звонок</a>
        </li>
        <li>
            <a routerLink="/contacts">Наши контакты</a>
        </li>
        <li withSecondaryMenu>
            <a routerLink="/products">Прайс</a>
            <ul class="secondary-menu" [ngClass] = "{'show-menu': this.show}">
                <li>
                    <a routerLink="/products">Прайс 1</a>
                </li>
                <li>
                    <a routerLink="/products">Прайс 2</a>
                </li>
                <li>
                    <a routerLink="/products">Прайс 3</a>
                </li>
            </ul>
        </li>
    </ul>
</nav>

Error itself: 11
@HostListener('mouseenter') onMouseEnter() {
src/app/with-secondary-menu.directive.ts:11:48 - error TS1005: ';' expected.
11 @HostListener('mouseenter') onMouseEnter() {
~
src/app/with-secondary-menu.directive.ts:15:32 - error TS1146: Declaration expected.
15 @HostListener('mouseleave') onMouseLeave() {
src/app/with-secondary-menu.directive.ts:15:48 - error TS1005: ';' expected.
15 @HostListener('mouseleave') onMouseLeave() {
~
I abandoned Angular for a long time ... I don’t remember at all how and what works. Yes, I didn't remember at all. So explain, as a teapot, please, what kind of problem I have.

Answer the question

In order to leave comments, you need to log in

1 answer(s)
A
Anton Shvets, 2019-07-13
@wb_by

Your problem is that you are trying to declare object methods inside the constructor. It's not Angular's fault.
Implementation:

import { Directive, TemplateRef, ViewContainerRef, OnInit, ElementRef, HostListener, Renderer2, HostBinding } from '@angular/core';

@Directive({
  selector: '[appHover]',
})
export class HoverDirective implements OnInit {
  content: NodeList;

  constructor(
    private el: ElementRef<HTMLElement>,
    private renderer: Renderer2,
  ) { }

  @HostListener('mouseenter') show() {
    this.content.forEach(node => this.renderer.setStyle(node, 'display', ''));
  }

  @HostListener('mouseleave') hide() {
    this.content.forEach(node => this.renderer.setStyle(node, 'display', 'none'));
  }

  ngOnInit() {
    this.content = this.el.nativeElement.childNodes;
    this.hide();
  }
}

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question