2017-04-05 1 views
0

나는 클릭 할 때 상태를 토글하는 지시문이 있습니다. 상태가 활성화되어 있고 사용자가 페이지의 다른 곳을 클릭하면 상태가 비활성화되어야합니다.각도 4로 @HostListener (클릭 리스너를 동적으로 생성)에서 문서를 클릭 한 다음 캡처

새로운 Renderer2 수신 기능을 사용하여 "다음 클릭"을 잡아내는 수신기를 동적으로 생성하려고 시도했습니다. 여기에서 문제는 청취자가 생성되는 즉시 콜백 기능이 실행된다는 것입니다. 한 번 클릭하면 활성화 된 다음 즉시 요소가 비활성화됩니다. 나는 왜 이런 일이 일어나고 있는지 그리고 내가 그 문제를 해결하기 위해해야 ​​할 일을 이해하는 데 도움을 찾고 있습니다.

지침 : 부모의 자녀에서

import { Directive, ElementRef, Input, Output, HostListener, EventEmitter, Renderer2 } from '@angular/core'; 

@Directive({ 
    selector: '[emClickToClose]' 
}) 
export class ClickToCloseDirective { 
    @Input('emClickToClose') 
    openCtrl: boolean; 

    @Output() 
    ctrlUpdate: EventEmitter<boolean> = new EventEmitter(); 

    @HostListener('click', ['$event']) onClick(e: MouseEvent) { 
    this.openCtrl = !this.openCtrl; 
    this.ctrlUpdate.emit(this.openCtrl); 
    if (this.openCtrl) { 
     const removeRegisteredListener = this.renderer.listen('document', 'click',() => { 
     console.log('the document was clicked', this.openCtrl); 
     this.openCtrl = false; 
     this.ctrlUpdate.emit(this.openCtrl); 
     removeRegisteredListener(); 
     }); 
    } 
    } 

    constructor(private el: ElementRef, private renderer: Renderer2) { 
    } 

} 

답변

1

이벤트 거품까지, 이벤트가 계속 전달되는 동안 이벤트 리스너를 추가하기 때문에, 궁극적 인 부모가되는 문서가 사용자의 클릭 이벤트를 받게됩니다. 를 사용하여 이벤트 전파를 중지해야합니다. 클릭 핸들러에 e.stopPropagation();

+0

신난다, 이것이 문제가되었습니다. 고마워요. –

0
당신은

<demo-component [emitStatus]="false"></demo-component> 

은 입력 변수를 가지고 emitStatus

import { Directive, HostListener, Renderer, ElementRef } from '@angular/core'; 
@Directive({ 
    selector: '[click]' 
}) 
export class ChangeDirective{ 

    constructor(
     private renderer: Renderer, 
     private el: ElementRef 
    ){} 

    @HostListener('click') onClick() { 
     let status = this.el.nativeElement.attributes['emitStatus']; 
     if(status){ 
      doo something 
     } 

    } 
} 
같은 지침을 만들기로 구성 요소를 선언

아래로이를 달성하기위한 지침과 구성 요소를 사용한다

선택기를 구성 요소에 추가하십시오.

<demo-component [emitStatus]="false" click></demo-component> 
+0

안녕하세요, 미안하지만 제안 된 지침이 내가 여기서하려고하는 것을 어떻게 달성하는지 보지 못합니다. 이것은 중요한 문제인 중요한 두 번째 부분을 달성하지 못할 것입니다. –

+0

저를 설명해 주시겠습니까? – Aravind

0

퍼스트 오프하여 @HostListener('click', ...)에서 [emClickToClose] 속성에 적용되는 DOM 요소에 이벤트 리스너에 결합된다. 어떻게 사용하고 있는지 잘 모르겠지만, 닫으려는 요소를 클릭하고 싶은 요소와 같으면 @HostListener('document:click', ...)을 대신 사용하고 싶을 것입니다.

이벤트 핸들러가 바인딩되어 클릭을 포착하고 즉시 창을 닫고 자체를 제거하는 것입니다. 다음과 같이 지시문 요소 외부에서 클릭이 발생하는지 확인해야합니다.

'@ angular/core'의 {Directive, ElementRef, Input, Output, HostListener, EventEmitter, Renderer2}를 가져 오십시오.

@Directive({ 
    selector: '[emClickToClose]' 
}) 
export class ClickToCloseDirective { 
    @HostListener('document:click', ['$event']) documentClick(event) { 
    if (! this.el.nativeElement.contains(event.target) && this.open) { 
     this.openCtrl = false; 
     this.ctrlUpdate.emit(this.openCtrl); 
    } 
    } 

    constructor(private el: ElementRef, private renderer: Renderer2) { 
    } 
} 

또한, 단순히 함수 이름을 지정 "removeRegisteredListener는"실제로 이벤트 리스너를 제거하지 않습니다,하지만 지시어가 파괴 될 때 이벤트 리스너가 제거됩니다. 나는이 도움을 바랍니다.

+0

리스너가 run once 상황이기 때문에 removeRegisteredListener를 호출합니다. 렌더러 리스너에서 반환 된 값을 호출하면 리스너가 제거됩니다. 두 번째 클릭이 요소 자체 내에 있지 않다면 수표를 추가해야합니다. 내 청취에 대한 응답은 새 청취자를 등록한 후에 실제로 청취자에서 문서 수준으로 클릭이 전파되는 것과 관련이 있습니다. 문서 레벨에서 클릭하십시오. 몸소.이 지시문은 페이지에서 여러 번 사용할 수 있기 때문에 각 인스턴스가 문서에 대해 열린 청취자를 가지지 않도록해야합니다. –

관련 문제