Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Allow dispatch target type to not be the same as the controller element type #642

@lb-

Description

@lb-

Summary

When using generics to declare a more specific element type on the controller, the dispatch target type is linked to that same type and it is no longer possible (without overrides or type checking warnings) to dispatch against a target of any kind of element.

Not sure if this is a bug but it is probably an unintended side effect of allowing a type signature for controllers via generics completed in #529

Steps to reproduce

  1. Create a new controller (TypeScript) similar to this, where the Controller's type is HTMLInputElement (e.g. not a generic Element or HTMLElement.
import { Controller } from '@hotwired/stimulus';

export class ExampleController extends Controller<HTMLInputElement> {
  connect() {
    const main = document.querySelector('main') as HTMLElement;

    this.dispatch('Connected!', { target: main });
  }
}
  1. Expected: I should be able to use the documented dispatch callback with any target element - as per https://stimulus.hotwired.dev/reference/controllers#cross-controller-coordination-with-events (see dispatch accepts additional options as the second parameter as follows:)

  2. Actual: I get a type error advising that the dispatch target element HTMLElement does not match the HTMLInputElement type.

Type 'HTMLElement' is missing the following properties from type 'HTMLInputElement': accept, align, alt, autocomplete, and 53 more.ts(2740)

A similar issue also happens if we were to pass in something like document to the target.

Screenshots

Screenshot 2023-01-24 at 11 08 17 am

Screenshot 2023-01-24 at 11 10 16 am

Potential solution

Allow the target type to be something like:

target?: ElementType | Element;

{ target = this.element, detail = {}, prefix = this.identifier, bubbles = true, cancelable = true } = {}

 dispatch(
    eventName: string,
    { target = this.element, detail = {}, prefix = this.identifier, bubbles = true, cancelable = true } = {}
  ) {
    const type = prefix ? `${prefix}:${eventName}` : eventName
    const event = new CustomEvent(type, { detail, bubbles, cancelable })
    target.dispatchEvent(event)
    return event
  }

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions