I have a question about the angular concept. I ask it with an example.
For example, I have some links similar to these items in my off-canvas menu:
<ul class="my_ul">
<li> <a (click)="do1()">do1</a> </li>
<li> <a (click)="do2()">do2</a> </li>
<li> <a (click)="do3()">do3</a> </li>
...
</ul>
I want to know when user click on ul.my_ul > li > a
then I run closeOffcanvas()
function.
- I don't want to add my
closeOffcanvas()
into thedo1()
ordo2()
or ... - I don't want to create a
directive
. - I don't want to add 2 function like:
(click)="do1(); closeOffcanvas()"
To get what I mean: In jquery
I can do this: (without any html change)
$('ul.my_ul > li > a').click(function(){
//my close off-canvas codes
});
How can I do similar this in Angular?
I want to listen to events of a specific element list in ponent without change HTML.
note: please don't solve the example problem. it isn't my problem. it is only an example to explain my mean.
I have a question about the angular concept. I ask it with an example.
For example, I have some links similar to these items in my off-canvas menu:
<ul class="my_ul">
<li> <a (click)="do1()">do1</a> </li>
<li> <a (click)="do2()">do2</a> </li>
<li> <a (click)="do3()">do3</a> </li>
...
</ul>
I want to know when user click on ul.my_ul > li > a
then I run closeOffcanvas()
function.
- I don't want to add my
closeOffcanvas()
into thedo1()
ordo2()
or ... - I don't want to create a
directive
. - I don't want to add 2 function like:
(click)="do1(); closeOffcanvas()"
To get what I mean: In jquery
I can do this: (without any html change)
$('ul.my_ul > li > a').click(function(){
//my close off-canvas codes
});
How can I do similar this in Angular?
I want to listen to events of a specific element list in ponent without change HTML.
note: please don't solve the example problem. it isn't my problem. it is only an example to explain my mean.
Share Improve this question edited Mar 12, 2020 at 19:40 Saeed sdns asked Mar 12, 2020 at 19:04 Saeed sdnsSaeed sdns 98810 silver badges21 bronze badges 2- You can add the (click) on the ul this way you'd get the event everytime the user clicks on any li. I understand this isn't exactly what you need but it should achieve the same purpose – m_sultan Commented Mar 12, 2020 at 19:08
-
@m_sultan the problem is an example. I want to listen to a specific element event. I want to know the user click on which
a
tag. – Saeed sdns Commented Mar 12, 2020 at 19:13
4 Answers
Reset to default 4Well, I summarize the final and best answer:
First, we access the elements with ElementRef
, like this:
const elements = this.elementRef.nativeElement.querySelectorAll("ul.class_name li > a");
then we listen to element's events with Renderer2
, like this:
elements.forEach( element => {
this.renderer.listen(element, "click", event => {
//do something...
});
});
Don't forget to import these:
import { ElementRef, Renderer2 } from '@angular/core';
and:
constructor( private elementRef:ElementRef, private renderer:Renderer2 ){ }
It seems you can use ElementRef
to select elements in the current ponent, like this:
@Component({
selector: "my-app",
template: `
<ul>
<li><a (click)="do1()">do1</a></li>
<li><a (click)="do2()">do2</a></li>
</ul>
`
})
export class AppComponent implements OnInit, OnDestroy {
constructor(private elementRef: ElementRef) {}
ngOnInit() {
const elements = this.elementRef.nativeElement.querySelectorAll("ul > li > a");
elements.forEach(element => {
element.addEventListener("click", this.doCommon);
});
}
ngOnDestroy() {
const elements = this.elementRef.nativeElement.querySelectorAll("ul > li > a");
elements.forEach(element => {
element.removeEventListener("click", this.doCommon);
});
}
do1() { console.log("do1"); }
do2() { console.log("do2"); }
doCommon() { console.log("mon"); }
}
If you don't want to limit your query to the contents of the current ponent, you can replace this.elementRef.nativeElement
with document
.
I haven't used it in the past, but it works fine in my StackBlitz project.
Maybe this whole ngOnDestroy()
to prevent memory leaks isn't necessary in modern browsers, but I still feel a little safer by doing it :)
You can using HostListener, Renderer2 or you can give the ul-element the click event.
Here is an example for the last solution:
https://stackblitz./edit/angular-gfnohf?file=src%2Fapp%2Fapp.ponent.ts
With the event, you can see, which element was clicked
import { Component } from '@angular/core';
@Component({
selector: 'my-app',
templateUrl: './app.ponent.html',
styleUrls: [ './app.ponent.css' ]
})
export class AppComponent {
do1() {
console.log('do1');
}
do2() {
console.log('do2');
}
do3() {
console.log('do3');
}
closeOffcanvas(event) {
if(event.target.matches('a'))
{
console.log('user clicked on: ', event.target, 'with name: ', event.target.innerHTML);
}
}
}
<ul class="my_ul" (click)="closeOffcanvas($event)">
<li> <a (click)="do1()">do1</a> </li>
<li> <a (click)="do2()">do2</a> </li>
<li> <a (click)="do3()">do3</a> </li>
</ul>
update example without changing html
It is better not binding an event for all list items. The performance is much greater if you only bind a wrapper-element and check if the event.target is the right children-element
https://stackblitz./edit/angular-oqjstq?file=src%2Fapp%2Fapp.ponent.ts
Simply get the parent reference, treat the parent as a collection, iterate over it and assign event listeners. (In Angular syntax you can use HostListener).
Example: https://stackblitz./edit/angular-6fsjhu?file=src%2Fapp%2Fapp.ponent.html
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745111265a4611866.html
评论列表(0条)