जवाबों:
import { Component, ElementRef, HostListener, Input } from '@angular/core';
@Component({
selector: 'selector',
template: `
<div>
{{text}}
</div>
`
})
export class AnotherComponent {
public text: String;
@HostListener('document:click', ['$event'])
clickout(event) {
if(this.eRef.nativeElement.contains(event.target)) {
this.text = "clicked inside";
} else {
this.text = "clicked outside";
}
}
constructor(private eRef: ElementRef) {
this.text = 'no clicks yet';
}
}
AMagyar के जवाब के लिए एक विकल्प। जब आप DOM से ngIf के साथ हटाए गए तत्व पर क्लिक करते हैं तो यह संस्करण काम करता है।
http://plnkr.co/edit/4mrn4GjM95uvSbQtxrAS?p=preview
private wasInside = false;
@HostListener('click')
clickInside() {
this.text = "clicked inside";
this.wasInside = true;
}
@HostListener('document:click')
clickout() {
if (!this.wasInside) {
this.text = "clicked outside";
}
this.wasInside = false;
}
दस्तावेज़ को @Hostlistener के माध्यम से क्लिक करना महंगा है। यदि आप अधिक उपयोग करते हैं (उदाहरण के लिए, कस्टम ड्रॉपडाउन घटक का निर्माण करते समय और आपके पास एक रूप में निर्मित कई उदाहरण हैं) तो इसका एक दृश्य प्रदर्शन प्रभाव हो सकता है।
मैं सुझाव देता हूं कि अपने मुख्य ऐप घटक के अंदर केवल एक बार दस्तावेज़ क्लिक इवेंट में @Hostlistener () को जोड़ना। घटना को वैश्विक उपयोगिता सेवा में संग्रहीत सार्वजनिक विषय के अंदर क्लिक किए गए लक्ष्य तत्व के मूल्य को धक्का देना चाहिए।
@Component({
selector: 'app-root',
template: '<router-outlet></router-outlet>'
})
export class AppComponent {
constructor(private utilitiesService: UtilitiesService) {}
@HostListener('document:click', ['$event'])
documentClick(event: any): void {
this.utilitiesService.documentClickedTarget.next(event.target)
}
}
@Injectable({ providedIn: 'root' })
export class UtilitiesService {
documentClickedTarget: Subject<HTMLElement> = new Subject<HTMLElement>()
}
जो भी क्लिक किए गए लक्ष्य तत्व के लिए इच्छुक है, उसे हमारी उपयोगिताओं सेवा के सार्वजनिक विषय की सदस्यता लेनी चाहिए और घटक के नष्ट होने पर सदस्यता समाप्त कर देनी चाहिए।
export class AnotherComponent implements OnInit {
@ViewChild('somePopup', { read: ElementRef, static: false }) somePopup: ElementRef
constructor(private utilitiesService: UtilitiesService) { }
ngOnInit() {
this.utilitiesService.documentClickedTarget
.subscribe(target => this.documentClickListener(target))
}
documentClickListener(target: any): void {
if (this.somePopup.nativeElement.contains(target))
// Clicked inside
else
// Clicked outside
}
उपर्युक्त उत्तर सही हैं, लेकिन क्या होगा यदि आप संबंधित घटक से ध्यान हटाने के बाद एक भारी प्रक्रिया कर रहे हैं। उसके लिए, मैं दो झंडे के साथ एक समाधान के साथ आया था, जहां फोकस आउट इवेंट प्रक्रिया केवल प्रासंगिक घटक से फोकस खोने पर होगी।
isFocusInsideComponent = false;
isComponentClicked = false;
@HostListener('click')
clickInside() {
this.isFocusInsideComponent = true;
this.isComponentClicked = true;
}
@HostListener('document:click')
clickout() {
if (!this.isFocusInsideComponent && this.isComponentClicked) {
// do the heavy process
this.isComponentClicked = false;
}
this.isFocusInsideComponent = false;
}
आशा है कि यह आपकी मदद करेगा। मुझे सुधारो अगर कुछ भी याद नहीं है।
आप https://www.npmjs.com/package/ng-click-outside पैकेज से useclickOutside () विधि कर सकते हैं
ginalx के उत्तर को डिफ़ॉल्ट एक imo के रूप में सेट किया जाना चाहिए: यह विधि कई अनुकूलन के लिए अनुमति देती है।
समस्या
यह कहें कि हमारे पास मदों की एक सूची है और प्रत्येक आइटम पर हम एक मेनू को शामिल करना चाहते हैं जिसे टॉगल करने की आवश्यकता है। हम एक बटन पर एक टॉगल शामिल करते हैं जो click
अपने आप में एक घटना के लिए सुनता है (click)="toggle()"
, लेकिन जब भी उपयोगकर्ता इसके बाहर क्लिक करता है तो हम मेनू को भी चालू करना चाहते हैं। यदि आइटम की सूची बढ़ती है और हम @HostListener('document:click')
प्रत्येक मेनू पर संलग्न करते हैं , तो आइटम के भीतर लोड किए गए प्रत्येक मेनू को पूरे दस्तावेज़ पर क्लिक के लिए सुनना शुरू हो जाएगा, तब भी जब मेनू बंद हो जाता है। स्पष्ट प्रदर्शन के मुद्दों के अलावा, यह अनावश्यक है।
उदाहरण के लिए, जब भी पॉपअप एक क्लिक के माध्यम से टॉगल हो जाता है, सदस्यता लें और उसके बाद ही "बाहर के क्लिक" के लिए सुनना शुरू करें।
isActive: boolean = false;
// to prevent memory leaks and improve efficiency, the menu
// gets loaded only when the toggle gets clicked
private _toggleMenuSubject$: BehaviorSubject<boolean>;
private _toggleMenu$: Observable<boolean>;
private _toggleMenuSub: Subscription;
private _clickSub: Subscription = null;
constructor(
...
private _utilitiesService: UtilitiesService,
private _elementRef: ElementRef,
){
...
this._toggleMenuSubject$ = new BehaviorSubject(false);
this._toggleMenu$ = this._toggleMenuSubject$.asObservable();
}
ngOnInit() {
this._toggleMenuSub = this._toggleMenu$.pipe(
tap(isActive => {
logger.debug('Label Menu is active', isActive)
this.isActive = isActive;
// subscribe to the click event only if the menu is Active
// otherwise unsubscribe and save memory
if(isActive === true){
this._clickSub = this._utilitiesService.documentClickedTarget
.subscribe(target => this._documentClickListener(target));
}else if(isActive === false && this._clickSub !== null){
this._clickSub.unsubscribe();
}
}),
// other observable logic
...
).subscribe();
}
toggle() {
this._toggleMenuSubject$.next(!this.isActive);
}
private _documentClickListener(targetElement: HTMLElement): void {
const clickedInside = this._elementRef.nativeElement.contains(targetElement);
if (!clickedInside) {
this._toggleMenuSubject$.next(false);
}
}
ngOnDestroy(){
this._toggleMenuSub.unsubscribe();
}
और, इसमें *.component.html
:
<button (click)="toggle()">Toggle the menu</button>
tap
ऑपरेटर में नहीं भरेंगे । इसके बजाय, उपयोग करें skipWhile(() => !this.isActive), switchMap(() => this._utilitiesService.documentClickedTarget), filter((target) => !this._elementRef.nativeElement.contains(target)), tap(() => this._toggleMenuSubject$.next(false))
। इस तरह से आप RxJs का अधिक उपयोग करते हैं और कुछ सदस्यताएँ छोड़ देते हैं।
@ ज में सुधार। फ्रेंकस्टीन का जवाब
@HostListener('click')
clickInside($event) {
this.text = "clicked inside";
$event.stopPropagation();
}
@HostListener('document:click')
clickout() {
this.text = "clicked outside";
}
यू इवेंट फंक्शन को कॉल कर सकते हैं जैसे (फ़ोकसआउट) या (ब्लर) तो यू अपना कोड डालें
<div tabindex=0 (blur)="outsideClick()">raw data </div>
outsideClick() {
alert('put your condition here');
}