Kamil Kiełczewski
Kamil Kiełczewski

Reputation: 92447

Is there a way to emit event inside directive

I use Angular2 and write some @Directive with drag and drop (in some bounded area) and want to emit event when dragging is end - so when dragging is end I invoke method endDragging. 1. how body of this method should look like?, 2. how usage of this directive should look like (especially how to set eventHandler to directive).

@Directive({
    selector: '[draggable]'
})
export class Draggable {
    @Input('draggable') boundary: any;
    ...
    endDraging() {
        // ??? how emit event from here?
    }
}

In html template (???=how set handler for draggable-endDragging event):

<div [draggable]="{x_min:10, x_max:100, y_min:20, y_max:200}" ...???... >
...some content...
</div>

Upvotes: 0

Views: 122

Answers (2)

Kamil Kiełczewski
Kamil Kiełczewski

Reputation: 92447

I found some working solution but unfortunatly is a little bit dirty workaround:

Let say we have component which use draggable div in his template:

@Component({
    selector: 'my-component',
    templateUrl: './my-component.html',
    directives: [ Draggable ],
})
export class MyComponent {

    myVariable = 0;    

    boundary() {
        return {
            x_min:10, 
            x_max:100, 
            y_min:20, 
            y_max:200,
            self: this, 
            onDragEnd: this.onDragEnd,
        };
    }

    onDragEnd(x,y,boundary) {
       // handle drag end event, to get acces to 'this' (instance of MyComponent class use boundary.self)
       boundary.self.myVariable = 1;
    }

}

In template .html we have:

<div [draggable]="boundary()">...</div>

And out directive will look like that:

@Directive({
    selector: '[draggable]'
})
export class Draggable {
    @Input('draggable') boundary: any;
    ...
    endDraging() {
        this.boundary.onDragEnd(this.x,this.y, this.boundary);
    }
}

The dirty thing is that MyComponent.onDragEnd method don't have access to 'this'(!!!) so I must put "this" in 'self' in object retuned by boundary() method. I don't know what is the reason - may be angular causes that, or may be typescript causes that problem... i don't know.

UPDATE:

I think that if we change line onDragEnd: this.onDragEnd, in MyComponent to

onDragEnd: (x,y,boundary) => this.onDragEnd(x,y,boundary),

then we will have normal access to this inside onDragEnd and solution actually will be not "dirty".

Upvotes: 1

Merkury32
Merkury32

Reputation: 72

You can define service with global event and use it in directive

import { Injectable } from '@angular/core';
import { ReplaySubject } from 'rxjs';

@Injectable({ providedIn: 'root' })
export class GlobalEventService {

    private eventSubject = new ReplaySubject<string>(1);

    constructor() { }

    public getEventObservable() {
        return this.eventSubject.asObservable();
    }

    public emitEvent(message) {
        this.eventSubject.next(message);
    }
}

Code is out of head and may contain bugs. From outside someone in service do

globalEventService.getEventObservable().subscribe(message => { … })

while directive use this servis sending event like this

globalEventService.emitEvent('some messsage')

Upvotes: 1

Related Questions