spectrum-web-components icon indicating copy to clipboard operation
spectrum-web-components copied to clipboard

[Bug]: [Slider] editable data-binding breaks when a single sp-slider-handle is slotted

Open Westbrook opened this issue 2 years ago • 6 comments

Code of conduct

  • [X] I agree to follow this project's code of conduct.

Impacted component(s)

sp-slider, sp-number-field

Expected behavior

Number Field shows the normalized value when normalization API is leveraged. This value needs to be "denormalized" on its way back into the component.

Actual behavior

Internal value instead of visible value in currently being applied.

Screenshots

No response

What browsers are you seeing the problem in?

No response

How can we reproduce this issue?

No response

Sample code that illustrates the problem

No response

Logs taken while reproducing problem

No response

Westbrook avatar Sep 08 '21 20:09 Westbrook

Copied from #1782: https://webcomponents.dev/edit/cyjAtZPLG4FTtBW21fhW/src/index.ts

Westbrook avatar Sep 10 '21 18:09 Westbrook

Update: this isn't a normalization issue. It happens whenever an sp-slider-handle is slotted into an editable sp-slider.

Slider itself extends SliderHandle and is used to store handle state whenever one isn't slotted. There are a few codepaths with special cases for handle === host. The Slider's NumberField connects directly to the Slider itself, assuming that it's the primary handle. Whenever that isn't the case, the state between the NumberField, Slider, and actual-primary SliderHandle gets out-of-sync.

I've implemented a preliminary change that fixes the issue, but I'm going to spend a little time looking for a simpler solution that doesn't add yet more state to a component where so many methods already have side-effects.

Longer-term, we may want to consider refactoring Slider into a declarative, hierarchical implementation with one-way binding, so we can minimize and isolate state changes. That would give us the opportunity to merge the "zero handles" and "one handle" special cases into a single codepath, and to get Slider to fulfill the single-responsibility & liskov substitution principles.

hunterloftis avatar Sep 15 '21 14:09 hunterloftis

/cc @spdev3000 for visibility on the original issue

hunterloftis avatar Sep 15 '21 14:09 hunterloftis

This is in fact a bug, but I think identifying that the bug is a Slider-as-handle vs SliderHandle-as-handle conflict can provide a straightforward workaround. I've developed two fixes, both of which increase the complexity of this already-complex component. @Westbrook I'd like to discuss whether they are worthwhile additions, or if it might make sense to fix this and several other issues at the same time with a refactor.

Meanwhile, @spdev3000 can you let me know if this workaround will unblock you? An editable slider with normalization can be achieved by treating the <sp-slider> as if it were the <sp-slider-handle>:

<sp-slider
  label="Slider Label"
  max=1
  min=0
  step=0.1
  value=1
  editable
  .normalization=${{
    toNormalized: (value: number) => { return Math.sqrt(value) },
    fromNormalized: (unit: number) => { return unit * unit},
  }}          
  ></sp-slider>

hunterloftis avatar Sep 15 '21 20:09 hunterloftis

@hunterloftis Yes this seems a great approach, thx for pointing me to this.

spdev3000 avatar Sep 16 '21 12:09 spdev3000

Woot!

Westbrook avatar Sep 16 '21 13:09 Westbrook

@hunterloftis Would it make sense to start a general slider refactor project?

najikahalsema avatar Oct 26 '22 19:10 najikahalsema