SAP / ui5-webcomponents

UI5 Web Components - the enterprise-flavored sugar on top of native APIs! Build SAP Fiori user interfaces with the technology of your choice.
https://sap.github.io/ui5-webcomponents/
Apache License 2.0
1.56k stars 267 forks source link

Dispatching `input` event for StepInput component (feature request) #5948

Closed anithegregorian closed 11 months ago

anithegregorian commented 2 years ago

Description

It may sound outlandish, however, I faced a real-world issue when using UI5 with Django and Django-Unicorn. Django-Unicorn is what LiveWire, HTMx, Stimulus or Hotwire is for Laravel and RoR. Unicorn is based on a light-weight library called MorphDom

I went down this rabbit hole to explore a hybrid solution that doesn't involve running a frontend in Node and backend in Django. After exploring several web component libraries like IBM Carbon, Google Material Design, Eva, Fluent, and Ant design system, UI5 was the best fit for my use case, its excellent for building and scaling enterprise-level web apps, has good documentation, above all, it was the easiest to install and configure with Vite. Thanks to the team at UI5 :)

The Rabbit Hole

Django-unicorn has two way bindings with a model, expressively with a Python list, dictionary or QuerySet. The problem with UI5 StepInput is it doesn't emit an input event, so this one fails when binding it with a list model:

<ui5-step-input
  max="100" min="1"
  required=""
  value="{{ iteration.qty }}"
  unicorn:model="items.{{ forloop.counter0 }}.qty"
  class="input-step"></ui5-step-input>

Same with a ui5-input works flawlessly because it emits an input event:

<ui5-input value="{{ iteration.qty }}" unicorn:model="items.{{ forloop.counter0 }}.qty" show-clear-icon></ui5-input>

The reason for this failure is that Django-unicorn directive unicorn:model binds to some specific input events, although some modifiers make it less painful eg. lazy, debounce and defer.

A temporary fix

I was able to pull out the @ui5/webcomponents/dist/StepInput.js file and patch it somehow to emit an input event with the change event which is sort of hackish:

_fireChangeEvent() {
    if (this._previousValue !== this.value) {
        this._previousValue = this.value;
        this.fireEvent("input", { value: this.value });
        this.fireEvent("change", { value: this.value });
    }
}

It would be great to have some of the basic input events emitted from UI5 web components, lest it's an architectural/design system constraint.

kineticjs commented 2 years ago

Hi @anithegregorian,

Thank you for this request and the explanation of the background context! One question please, before I forward this further:

The current "change" event of StepInput fires when the input operation has finished. So a new "input" event would be fired at each keystroke, even before the input operation has finished.

So the issue is that Django needs an earlier notification (earlier than the current "change" event) or that Django expects the event to be named as "input"?

Sorry of the question sounds stupid, I just need to ensure I understood the issue before forwarding to the team.

Thanks, Diana

anithegregorian commented 2 years ago

Hi @kineticjs ,

It's exactly what MDN documentation says:

For elements with type=checkbox or type=radio, the input event should fire whenever a user toggles the control, per the HTML Living Standard specification. However, historically this has not always been the case. Check compatibility, or use the change event instead for elements of these types.

A change event should fire when the element loses focus after its value was changed: for elements where the user's interaction is typing rather than selection, such as a