আমি কৌণিকের কোনও উপাদানগুলির বাইরে ক্লিকগুলি কীভাবে সনাক্ত করতে পারি ?
উত্তর:
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';
}
}
আমাগিয়রের উত্তরের বিকল্প। আপনি যখন কোনও এনজিআইএফ দিয়ে ডোম থেকে সরিয়ে ফেলা উপাদানটিতে ক্লিক করেন তখন এই সংস্করণটি কাজ করে।
http://plnkr.co/edit/4mrn4GjM95uvSbQtxrAS?p= পূর্বরূপ
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;
}
@ হোস্টলিস্টারের মাধ্যমে দস্তাবেজ ক্লিক করতে বাধ্য হওয়া ব্যয়বহুল। যদি আপনি অতিরিক্ত ব্যবহার করেন (উদাহরণস্বরূপ, একটি কাস্টম ড্রপডাউন উপাদান তৈরি করার সময় এবং আপনি কোনও ফর্মে একাধিক উদাহরণ তৈরি করেছেন) এটির দৃশ্যমান পারফরম্যান্সের প্রভাব থাকতে পারে।
আমি কেবলমাত্র আপনার মূল অ্যাপ্লিকেশনের অংশের মধ্যে ডকুমেন্ট ক্লিক ইভেন্টে একটি @ হোস্টলিস্টার () যুক্ত করার পরামর্শ দিচ্ছি। ইভেন্টটি বিশ্বব্যাপী ইউটিলিটি পরিষেবাতে সঞ্চিত কোনও জনসাধারণের ভিতরে ক্লিক করা লক্ষ্য উপাদানটির মানকে চাপ দিতে হবে।
@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;
}
আশা করি এটা তোমাকে সাহায্য করবে। যদি কিছু মিস করে থাকে তবে আমাকে সংশোধন করুন।
জিনালেক্সের উত্তরটি ডিফল্ট এক ইমো হিসাবে সেট করা উচিত: এই পদ্ধতিটি অনেকগুলি অনুকূলিতকরণের জন্য অনুমতি দেয়।
সমস্যাটি
বলুন যে আমাদের আইটেমের একটি তালিকা আছে এবং প্রতিটি আইটেমের উপরে আমরা একটি মেনু অন্তর্ভুক্ত করতে চাই যা টগল করা দরকার। আমরা একটি বোতামে একটি টগল অন্তর্ভুক্ত করি যা 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))
। এইভাবে আপনি আরও বেশি পরিমাণে আরএক্সজে ব্যবহার করতে এবং কিছু সাবস্ক্রিপশন এড়িয়ে যান।
আপনি https://www.npmjs.com/package/ng-click-outside প্যাকেজ থেকে ক্লিক আউটসাইড () পদ্ধতি ব্যবহার করতে পারেন
উন্নতি করা হয়েছে @ জে। ফ্র্যাঙ্কেনস্টাইন উত্তর
@HostListener('click')
clickInside($event) {
this.text = "clicked inside";
$event.stopPropagation();
}
@HostListener('document:click')
clickOutside() {
this.text = "clicked outside";
}
আপনি ইভেন্ট ফাংশনটিকে (ফোকাসআউট) বা (অস্পষ্ট) কল করতে পারেন তারপরে আপনি আপনার কোডটি রেখেছেন
<div tabindex=0 (blur)="outsideClick()">raw data </div>
outsideClick() {
alert('put your condition here');
}