Peterlits Zo
Peterlits Zo

Reputation: 536

Add property to HtmlElement

[[WARNING]]: It looks like the question TypeScript: add type property to HtmlElement but I need to add a function to an Element Object but not add an attribute to a Node.

I try to make JavaScript to TypeScript but I am new with TypeScript, I try to add a new function to el.clickOutsideEvent, but ts do not allow me to do like this:

Vue.directive('click-outside', {
  bind: function (el: HTMLElement, binding: Object, vnode: VNode) {
    // stack-overflow: https://stackoverflow.com/a/42389266/13031497
    el.clickOutsideEvent = function (event: MouseEvent): void {
      if (!(el == event.target) ||
            event.target instanceof Node && el.contains(event.target)) {
        vnode.context[binding.expression](event);
      }
    }
    // ugly, but fix the bug:
    // 2020/11/20 - Peterlits Zo
    // When I click the the ellipsis-h buttom, it do not change anything.
    // I find that itself call this function auto, so I add this after times.
    setTimeout(() => {
      document.body.addEventListener('click', el.clickOutsideEvent)
    }, 50)
  },
  unbind: function (el: HTMLElement) {
    document.body.removeEventListener('click', el.clickOutsideEvent)
  },
})

It tell me that: Property 'clickOutsideEvent' does not exist on type 'HTMLElement'. and something else.

What should I do for it?

Upvotes: 5

Views: 4899

Answers (3)

khcpietro
khcpietro

Reputation: 1529

You can declare custom properties on global.

declare global {
    interface HTMLElement {
        clickOutsideEvent: (event: MouseEvent) => void
    }
}

Another bad approach is using @ts-ignore.

// @ts-ignore
el.clickOutsideEvent = clickOutsideEvent

Upvotes: 3

Yom T.
Yom T.

Reputation: 9180

I would create a custom interface extending from HTMLElement.

interface IHTMLElementClicketyClick extends HTMLElement {
  clickOutsideEvent?(event: MouseEvent): void;
}

Vue.directive('click-outside', {
  bind: function (el: IHTMLElementClicketyClick, binding: Object, vnode: VNode) {

  // the rest of the code 

Upvotes: 3

Dafen
Dafen

Reputation: 1150

You will probably have to extent the HTMLElement type using module-augmentation.

tsconfig.json:

{
  "compilerOptions": {
    "target": "es5",
    ...
    "typeRoots": [
      "./src/js/@types"
    ]
  },
  ...
}

src/js/@types/app.d.ts

interface HTMLElement {
    clickOutsideEvent(event: MouseEvent): void
}

Upvotes: 2

Related Questions