devtools icon indicating copy to clipboard operation
devtools copied to clipboard

Can't Expand Object that Extends EventTarget

Open aronduby opened this issue 4 months ago • 6 comments

I have a js class that extends EventTarget to take advantage of js's built in event handling, but when I view an instance of that item in the component inspector it just says EventTarget and I'm unable to expand it or interact with it in anyway. Is there a way to get this to retain that functionality while extending that class?

Image
class Dialog extends EventTarget {
    // ...
}

class DialogService {

    /**
     * Internal reference to the existing dialogs
     */
    public readonly instanceMap: Map<string, Dialog>;

    constructor() {
        this.instanceMap = reactive(new Map());
    }

    add(dialog: Dialog) {
        this.instanceMap.set(dialog.id, dialog);
        dialog.addEventListener('transitioned', () => this.remove(dialog);
    }

    // ...
}

aronduby avatar Aug 18 '25 14:08 aronduby

As a workaround, you can add

  get [Symbol.toStringTag]() {
    return 'Object'
  }

to your Dialog class

Image

Then it will work fine:

Image

Lootjs avatar Aug 18 '25 21:08 Lootjs

it’s because of a limitation of host objects

Lootjs avatar Aug 18 '25 21:08 Lootjs

@Lootjs that did it, thank you!

aronduby avatar Aug 19 '25 13:08 aronduby

@Lootjs I take that back, it worked to have it workable in devtools, but now trying to dispatch events throws Illegal Invocation errors.

this.dispatchEvent(new CustomEvent('transitioned', { detail: state }));

aronduby avatar Aug 19 '25 18:08 aronduby

I ended up refactoring it to use a private instance of EventTarget instead of extending it and then creating the methods to point to that. Psuedo code example:

class Dialog {
    private eventTarget: EventTarget;

    constructor() {
       this.eventTarget = new EventTarget();
    }

    dispatchEvent(....args) => this.eventTarget.dispatchEvent(...args);
    addEventListener(....args) => this.eventTarget.addEventListener(...args);
    removeEventListener(....args) => this.eventTarget.removeEventListener(...args);
}

aronduby avatar Aug 19 '25 20:08 aronduby

Maybe @webfansplz can suggest a better way to fix this🤔

Lootjs avatar Aug 22 '25 09:08 Lootjs