Доступ к области действия директивы с помощью обработчика событий элемента HTML - PullRequest
0 голосов
/ 26 октября 2018

Я создал Directive для использования элемента в качестве 'dropzone` с собственным HTML Drag & Drop

Источник директивы

import { Directive, ElementRef, OnInit, Output, EventEmitter, ViewChild } 
from '@angular/core';
import { environment } from 'src/environments/environment';

@Directive({
    selector: '[app-drop-zone]'
})
export class DropzoneDirective implements OnInit {    
    @Output('outbound-listener') outBoundListener = new EventEmitter();    

    constructor(private e: ElementRef) {        
        e.nativeElement.ondrop = this.drop;
        e.nativeElement.ondragover = this.dragOver;
        e.nativeElement.ondragenter = this.dragEnter;
        e.nativeElement.ondragleave = this.dragLeave;            
    }

    ngOnInit(): void { }

    private drop(event: any){ 

        let files: File[] = []; // temprary cache for dropped files

        if (event.stopPropagation) {
           event.stopPropagation(); // Stops some browsers from redirecting.
        }

        event.currentTarget.classList.remove('over');    // remove the 
        dotted background, once user release the content (drop-end)

       // process dropped items
       if(event.dataTransfer.items){
       for(let i = 0; i< event.dataTransfer.items.length; i++){
           if(event.dataTransfer.items[i].kind == "file"){
               files.push(event.dataTransfer.items[i].getAsFile());
           }
       }

       if(files.length > 0){
           this.outBoundListener.emit({ type: 
           environment.component_events.INIT_FILE_UPLOAD, data: files});              
       }
    }
    return false;
 }

 private dragOver(e){
      if(e.preventDefault)
          e.preventDefault();    

      e.dataTransfer.dropEffect = 'move';
      return false;
 }

 private dragEnter(event: any) {     
    event.currentTarget.classList.add('over');    
 }

 private dragLeave(event: any) {    
    event.currentTarget.classList.remove('over');    
 }
}

** Пожалуйста, игнорируйте форматирование кода astheitcs :-(

Проблема здесь, в методе «drop», я хочу получить доступ к классу директивы prop outBoundListener, который является EventEmitter Но я не могу вызвать его через this

Любая помощь по этому вопросу будет оценена ..

1 Ответ

0 голосов
/ 26 октября 2018

То, что у вас есть, должно работать при вызове из кода TypeScript , так как семантика TypeScript / ES6 this немного отличается для функций со стрелками.Вы можете прочитать больше об этом здесь , где есть целый раздел, посвященный горячему беспорядку, который this.

Проблема здесь не в том, что this относится к владельцуили вызываемый, но к элементу DOM.Вы можете убедиться в этом, вызвав console.log(this) вверху вашей drop функции.

Причина, по которой дела идут не так, как надо, состоит в том, что эта функция вызывается не из кода ES6 или TypeScript, а из события DOMобработчики.Чтобы заставить его сохранять this, вы можете использовать функцию bind.

constructor(private e: ElementRef) {        
    e.nativeElement.ondrop = this.drop.bind(this);
    e.nativeElement.ondragover = this.dragOver.bind(this);
    e.nativeElement.ondragenter = this.dragEnter.bind(this);
    e.nativeElement.ondragleave = this.dragLeave.bind(this);
}

Обратите внимание, что this является вашим экземпляром объекта, и теперь вы заставляете это быть так, создавая новыйиспользовать значение this в соответствии с объяснением MDN .

В качестве альтернативы можно использовать встроенную функцию стрелки.

constructor(private e: ElementRef) {        
    e.nativeElement.ondrop = event => this.drop(event);
    e.nativeElement.ondragover = event => this.dragOver(event);
    e.nativeElement.ondragenter = event => this.dragEnter(event);
    e.nativeElement.ondragleave = event => this.dragLeave(event); 
}

Здесь это работаетпотому что функция стрелки сохраняет this, как упоминалось ранее.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...