如何在 angular 中委托点击事件?
How I can delegate a click event in angular?
如何在我的板上委托一个点击事件,我所做的是告诉元素使用 class open-preview 来查找元素而我做不到就像我一样。因为 li 是在 ruby 循环中动态创建的。我不知道如何在 angular 而不是 find.
中委托点击事件
HTML 代码
<ul>
<li open-preview>
<a ng-href="{{product.url}}" title="{{product.brand}}">
<img ng-src="{{product.urlImage}}" alt="{{product.brand}}">
</a>
<div class="descrip-product">
<p>{{product.descriptionExcerpt}}</p>
</div>
<span class="open-preview">Quick view</span>
</li>
</ul>
指令代码
var app = angular.module('productPreview'),
app.directive('openPreview', function($compile, $templateCache, $timeout) {
return {
restrict: 'A',
transclude: false,
templateNamespace: 'html',
scope: true,
link: function(scope, element, attrs) {
element.find('.open-preview').bind('click', function() {
// function here
});
}
}
}):
最好(如果不是完全需要)使用 isolate scope,因为您正在重复使用该指令。
在隔离范围内,您可以定义指令如何调用外部(指令的)函数 - 这是通过 scope: { param: "&" }
完成的
app.directive('openPreview', function() {
return {
restrict: 'A',
scope: {
openPreview: "&"
},
link: function(scope, element, attrs) {
element.find('.open-preview').bind('click', function() {
// invoke the function
scope.openPreview({p1: 'foo', p2: 'bar'});
});
}
}
}):
那么用法是:
<li open-preview="onPreview(p1, 'xyz', p2)">
...
</li>
以防万一有人正在寻找 Angular 8+ 解决方案,这是我使用指令的方法。
import {
Directive,
ElementRef,
EventEmitter,
HostListener,
Input,
Output,
Renderer2
} from '@angular/core';
@Directive({ selector: '[delegateClick]' })
export class DelegateClickDirective {
@Input() delegatedTo: string = '';
@Output() delegateClick: EventEmitter<InnerClickEvent> = new EventEmitter<InnerClickEvent>();
@HostListener('click', ['$event']) onClick(event: MouseEvent) {
const target: HTMLElement = event.target as HTMLElement;
// do nothing if the clicked item is the decorated element itself or delegated not set
if (target === this.elementRef.nativeElement || !this.delegatedTo) {
return;
}
event.preventDefault();
this.handleClick(event.target as HTMLElement);
}
constructor(private elementRef: ElementRef) {}
handleClick(element: HTMLElement) {
if (element.matches(this.delegatedTo)) {
this.delegateClick.next({ detail: element.dataset, target: element });
return;
}
// also stop searching if we reach the container itself
if (element === this.elementRef.nativeElement) {
return;
}
this.handleClick(element.parentElement);
}
}
export interface InnerClickEvent {
target: HTMLElement;
detail: DOMStringMap;
}
像这样在模板中使用它:
<ul (delegateClick)="delegatedClick($event)" delegatedTo="li">
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
如何在我的板上委托一个点击事件,我所做的是告诉元素使用 class open-preview 来查找元素而我做不到就像我一样。因为 li 是在 ruby 循环中动态创建的。我不知道如何在 angular 而不是 find.
中委托点击事件HTML 代码
<ul>
<li open-preview>
<a ng-href="{{product.url}}" title="{{product.brand}}">
<img ng-src="{{product.urlImage}}" alt="{{product.brand}}">
</a>
<div class="descrip-product">
<p>{{product.descriptionExcerpt}}</p>
</div>
<span class="open-preview">Quick view</span>
</li>
</ul>
指令代码
var app = angular.module('productPreview'),
app.directive('openPreview', function($compile, $templateCache, $timeout) {
return {
restrict: 'A',
transclude: false,
templateNamespace: 'html',
scope: true,
link: function(scope, element, attrs) {
element.find('.open-preview').bind('click', function() {
// function here
});
}
}
}):
最好(如果不是完全需要)使用 isolate scope,因为您正在重复使用该指令。
在隔离范围内,您可以定义指令如何调用外部(指令的)函数 - 这是通过 scope: { param: "&" }
app.directive('openPreview', function() {
return {
restrict: 'A',
scope: {
openPreview: "&"
},
link: function(scope, element, attrs) {
element.find('.open-preview').bind('click', function() {
// invoke the function
scope.openPreview({p1: 'foo', p2: 'bar'});
});
}
}
}):
那么用法是:
<li open-preview="onPreview(p1, 'xyz', p2)">
...
</li>
以防万一有人正在寻找 Angular 8+ 解决方案,这是我使用指令的方法。
import {
Directive,
ElementRef,
EventEmitter,
HostListener,
Input,
Output,
Renderer2
} from '@angular/core';
@Directive({ selector: '[delegateClick]' })
export class DelegateClickDirective {
@Input() delegatedTo: string = '';
@Output() delegateClick: EventEmitter<InnerClickEvent> = new EventEmitter<InnerClickEvent>();
@HostListener('click', ['$event']) onClick(event: MouseEvent) {
const target: HTMLElement = event.target as HTMLElement;
// do nothing if the clicked item is the decorated element itself or delegated not set
if (target === this.elementRef.nativeElement || !this.delegatedTo) {
return;
}
event.preventDefault();
this.handleClick(event.target as HTMLElement);
}
constructor(private elementRef: ElementRef) {}
handleClick(element: HTMLElement) {
if (element.matches(this.delegatedTo)) {
this.delegateClick.next({ detail: element.dataset, target: element });
return;
}
// also stop searching if we reach the container itself
if (element === this.elementRef.nativeElement) {
return;
}
this.handleClick(element.parentElement);
}
}
export interface InnerClickEvent {
target: HTMLElement;
detail: DOMStringMap;
}
像这样在模板中使用它:
<ul (delegateClick)="delegatedClick($event)" delegatedTo="li">
<li>1</li>
<li>2</li>
<li>3</li>
</ul>