Search code examples
angulardrag-and-dropweb-worker

Drag and drop implementation while running angular app logic in a webworker


Based on Angular CLI 1.7.4 (Ubuntu 17.10) I created a small sample app with

ng new webWorkerTest

and followed the steps at this great guide: Angular with Web Workers: Step by step. Afterwards I created a component DraggableComponent:

ng g c draggable

and tried to register a dragstart listener to that component by adding

this.renderer.listen(this.reference.nativeElement, 'dragstart', (event: Event) => {
  console.log('Element drag start');
});

to the constructor of this component (in fact I tried a lot more, but this is my best guess ;) ).

Unfortunately this doesn't work. It worked with a click or mousemove event, but not with dragstart. Suprisingly onDragStart="alert('This one works!');" in the template worked as well.

Now my question: does anyone know, how I could add a dragstart listener? Or - if so - why this does/cannnot not work?

My aim is to implement a lean drag and drop functionality based on two simple directives without any libraries.

For curiosity I tried ng2-dnd and ng-drag-drop. However, both failed in a webworker as well.


Solution

  • After testing and trying a lot I’m rather sure that drag events simply don‘t work in the way as described above (at least at this point of time).
    The fact that other libraries (ngx-drag-drop, dragular) don’t work in this project setup as well strengthens my assumption. I did not find any explanation why these events do not work at the same time others do.

    Click events and mouse events work quite fine and I was able to build my own drag and drop based on mouse events (with some quirks though).

    Anyway – while playing around with my app I identified several disadvantages of having the whole app in a web worker:

    1. Drag and drop did not work
    2. The Angular Material component framework doesn’t work as well
    3. All components and services run in the same web worker and can potentially block each other

    Therefore, I tried another approach to move my extensive background task into a web worker: webpack. With webpack I was able to bundle concerned TypeScript files into one JavaScript file. The TypeScript files reside in my Angular project and the worker bundle gets created into my assets folder. This way I can reuse the same classes on UI and worker thread.

    So starting from this idea, I was able resolve all of the issues mentioned above. My drag and drop implementation runs on the UI thread. Including Angular Material was no problem and the extensive background task can be executed in a WebWorker. Communication between UI and WebWorker is based on postMessage() commands. That’s it.

    Some interesting links around the web worker topic: