将类添加到Angular2指令中的下一个元素

时间:2017-01-24 16:49:27

标签: javascript angular angularjs-directive

我有一个下拉菜单,我想使用angular2指令处理此下拉列表的打开/关闭。 如何将open类添加到latest-notification div。通过知道我的指令应用于button标签!

这是我的HTML代码:

<div class="header-notification" (clickOutside)="showPopupNotification = false">
      <button appDropdown>
        <span [class.has-notification]="hasNotification"></span><icon name="ico_notification"></icon>
      </button>
      <div class="latest-notification">
        <span class="top-pointer"><icon name="arrow-popup"></icon></span>
        <div class="wrap">
          <ul>
            <li *ngFor="let notify of notifications" [class.seen]="notify.seen">
              <a>
                <avatar src="{{notify.userProfileUrl}}" size="35"></avatar>
                <time>{{notify.createAt}}</time>
                <h5>{{notify.name}}</h5>
                <p>{{notify.message}}</p>
              </a>
            </li>
          </ul>
        </div>
      </div>
    </div>

这是我的指示:

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

@Directive({
  selector: '[appDropdown]'
})
export class DropdownDirective {
  private isOpen = false;

  @HostBinding('class.open') get opened() {
    return this.isOpen;
  }

  @HostListener('click') open() {
    this.isOpen = !this.isOpen;
  }
  constructor() { }

}

3 个答案:

答案 0 :(得分:3)

很抱歉迟到了回复。

您可以在指令中使用exportAs元属性来实现您想要的目标。

(我只会向您显示需要进行更改的相关行)

/* #temp is a local template variable */
/* mydir is defined in dropdowndirective as exportAs meta property */

<button #temp=mydir appDropdown>
/* using vc which is defined in dropdown component */
<div class="latest-notification" [class.open]="vc.isOpen" [class.close]="!vc.isOpen">
import {DropdownDirective} from 'path';

export class DropDownComponent{
  @Viewchild('temp') vc:DropdownDirective;  // vc can hold isOpen variable directly defined in Dropdowndirective.
}
@Directive({
  selector: '[appDropdown]'
  exportAs:'myDir'                          // addded this line
})

演示:http://plnkr.co/edit/AE8n4McCez7ioxiTSExL?p=preview

答案 1 :(得分:2)

这是我找到的解决方案。我不这是正确的方式或最好的方式。但至少它正在发挥作用。

现在,通过向按钮指令添加toggle指令将被激活,点击它将名为open的类添加到下一个元素latest-notification。并且当点击按钮外部时,open类将被删除。让我知道你们的想法。

HTML方面:

<div class="header-notification">
  <button toggle>
    ...
  </button>
  <div class="latest-notification">
    ...
  </div>
</div>

这是指令:

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

@Directive({
  selector: '[toggle]'
})
export class DropdownDirective {
  isOpen = false;

  constructor(private el: ElementRef, private renderer: Renderer) {}

  @HostListener('click') open() {
    let nextElement = this.el.nativeElement.nextElementSibling;
    this.isOpen = !this.isOpen;

    if (this.isOpen === true) {
      this.renderer.setElementClass(nextElement, "open", true);
    } else {
      this.renderer.setElementClass(nextElement, "open", false);
    }
  }

  // close dropdown if clicked outside
  public clickOutside = new EventEmitter<MouseEvent>();

  @HostListener('document:click', ['$event', '$event.target'])
  public onClick(event: MouseEvent, targetElement: HTMLElement): void {
    if (!targetElement) {
      return;
    }

    const clickedInside = this.el.nativeElement.contains(targetElement);

    if (!clickedInside) {
      this.clickOutside.emit(event);
      this.isOpen = false;
      let dropdown = this.el.nativeElement.nextElementSibling;
      this.renderer.setElementClass(dropdown,"open", false);
    }
  }


}

答案 2 :(得分:0)

您好,我对@Sajad 的回答进行了改进更新:

  • angular11
  • 引导程序 4
  • 渲染器 2
  • addClass(), removeClass()

HTML

<div class="btn-group">

    <button type="button" class="btn btn-primary dropdown-toggle"
      appDropdown
    >
      Manage Recipe
    </button>

    <div class="dropdown-menu">
      <a class="dropdown-item" href="#">To Shop List</a>
      <a class="dropdown-item" href="#">Edit Recipe</a>
      <a class="dropdown-item" href="#">Delete Recipe</a>
    </div>

  </div>

指令

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

@Directive({
  selector: '[appDropdown]'
})
export class DropdownDirective {

  isOpen:boolean = false;

  constructor( private elRef: ElementRef, private renderer: Renderer2 ) { }

  // TOGGLE dropdownMenu
  @HostListener('click') toggleOpen(): void {

    const dropdownMenu: HTMLElement = this.elRef.nativeElement.nextSibling;

    this.isOpen = !this.isOpen;

    if( this.isOpen ) {
      this.renderer.addClass(dropdownMenu, 'show');
    }
    else{
      this.renderer.removeClass(dropdownMenu, 'show');
    }
    console.log(this.isOpen);
  }

  // CLOSE dropdown if outside click
  clickOutside = new EventEmitter<Event>();

  @HostListener('document:click', ['$event', '$event.target'])
  onClick( event: Event, targetElement: HTMLElement ): void {

    if (!targetElement || this.isOpen === false ) return;

    const dropdownMenu: HTMLElement = this.elRef.nativeElement.nextSibling;
    let clickedInside = this.elRef.nativeElement.contains(targetElement);

    if (!clickedInside) {
      this.clickOutside.emit(event);
      this.renderer.removeClass(dropdownMenu,'show');
      this.isOpen = false;
    }
  }

}