【问题标题】:Click outside angular component单击外部角度分量
【发布时间】:2020-04-22 06:10:57
【问题描述】:

我知道这方面有无数的问题,我尝试了所有解决方案,但没有一个适合我的需求。尝试过的指令,直接在我的组件中尝试过,但一次都没有用。

所以我的情况是这样的;我有一个表格视图,在每个表格视图的末尾,您可以通过单击一个图标来打开一个小下拉列表。弹出的下拉菜单是一个小组件。所以在我的父组件中它看起来像这样;

<tbody>
    <tr *ngFor="let rows of subscriptionTable.data; let i = index;">
        <td *ngFor="let cell of subscriptionTable.data[i].data"> 
            <!-- Table actions -->
            <div *ngIf="cell.actions && cell.actions.length > 0">
                <app-dropdown
                    [actions]         = cell.actions
                    (onActionClicked) = "handleSubscriptionAction($event, i)"
                >
                </app-dropdown>
            </div>
        </td>
    </tr>
</tbody>

所以我正在渲染多个看起来像这样的子应用下拉组件;

<div class="fs-action">
  <div class="fs-action__dots" (click)="openActionSheet($event)">
    <span class="fs-action__dot"></span>
    <span class="fs-action__dot"></span>
    <span class="fs-action__dot"></span>
  </div>

  <ul class="fs-action__list">
    <li 
      class="fs-action__item"
      *ngFor="let action of actions; let i = index;" 
      (click)="actionClicked( $event, i )" 
      [ngClass]="{'fs-action__item--danger': action.type === 'destructive' }"
    >
        {{ action.label }}
    </li>
  </ul>
</div>

我现在想要做的是,只要我在 fs-action 元素外部单击,下拉菜单就会消失。我想在app-dropdown 组件中执行此操作,然后与该组件相关的所有内容都在同一个地方。

但是,只要我附加了指令或其他任何内容,hostlistener 就会为每一行添加。然后,每个外部点击都会被触发多次。检查我是否在操作元素之外单击会成为一种负担,因为它会为所有其他 hostlisteners 呈现 false,而对于处于活动状态的元素呈现 true。

这个问题在这个 stackblitz 中得到了说明; https://stackblitz.com/edit/angular-xjdmg4

我评论了导致dropdown.component.ts内部问题的部分;

  public onClickOutside( event ) {
    // It executes 3 times, for each of the items that is added
    // Even when clicking inside the dropdown, it calls this function
    console.log("click")
  }

【问题讨论】:

  • 当然,会在一个小时左右尝试完成!目前不在办公室。
  • 您应该可以使用HostListener 来处理类似的事情并附加相应的事件。
  • 找到了一些时间,这里是一个说明问题的堆栈闪电; stackblitz.com/edit/angular-xjdmg4

标签: javascript angular angular-directive


【解决方案1】:

只需使用 (click) 事件绑定,从组件的实例中传递一个函数,就完成了。

解决方案: 像下面这样声明指令ClickOutside

@Directive({
  selector: '[clickOutside]',
})
export class ClickOutsideDirective {
  @Output('onClickOutside') onClickOutside = new EventEmitter<MouseEvent>();

  constructor(private _eref: ElementRef) {}

  @HostListener('document:click', ['$event', '$event.target'])
  onDocumentClicked(event: MouseEvent, targetElement: HTMLElement) {
    if (targetElement && document.body.contains(targetElement) && !this._eref.nativeElement.contains(targetElement)) {
      this.onClickOutside.emit(event);
      }
    }
  }
}
<div clickOutside (onClickOutside)="onClickOutside()">
...
</div>

并且在一个名为 ng-click-outside 的 npm 模块中有一个指令。

安装npm install --save ng-click-outside

阅读以下链接中的完整文档:

ng-click-outside directive

【讨论】:

  • 这并没有真正按预期工作。请参阅我的 stackblitz.com/edit/angular-xjdmg4。即使在 div 内部单击时,它也会将单击呈现为外部。
【解决方案2】:

我用了一个指令来处理类似的情况。 安装:

npm install --save ng-click-outside

然后导入你的模块

import { ClickOutsideModule } from 'ng-click-outside';

@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule, ClickOutsideModule],
  bootstrap: [AppComponent]
})
class AppModule {}

在你的组件中

@Component({
  selector: 'app',
  template: `
    <div (clickOutside)="onClickedOutside($event)">Click outside this</div>
  `
})
export class AppComponent {
  onClickedOutside(e: Event) {
  console.log('Clicked outside:', e);
  }
}

它有一些选择。你可以在https://www.npmjs.com/package/ng-click-outside看到它

问候

【讨论】:

  • 已经试过这个了。但是如果我在我的子组件中添加它,比如说fs-action,它会被添加 9 次。在外部单击也会执行 9 次。还是我需要将其添加到不同的地方?
  • 尝试添加 [attachOutsideOnClick]="true"
  • 或检查其他选项,如果您将它们结合起来,您可能会得到想要的结果
  • 我认为这并没有按预期工作。请参阅我的 stackblitz.com/edit/angular-xjdmg4。即使在 div 内部单击时,它也会将单击呈现为外部。它会触发 3 次。
  • 啊等一下。我现在正在阅读您对attachOutsideOnClick 的评论。我一定错过了,因为我认为这可以让它发挥作用!
猜你喜欢
  • 2018-09-18
  • 1970-01-01
  • 1970-01-01
  • 2019-02-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多