Skip to content

Refactor two-way data binding using proxy#38

Open
mohamedhyouns wants to merge 26 commits into2.xfrom
mohamedhany/2.x/#32-refactor-two-way-binding
Open

Refactor two-way data binding using proxy#38
mohamedhyouns wants to merge 26 commits into2.xfrom
mohamedhany/2.x/#32-refactor-two-way-binding

Conversation

@mohamedhyouns
Copy link
Copy Markdown
Contributor

- Refactored two-way binding logic to allow number
inputs to remain empty.

- Added `getRangePercent` function to compute slider
percentage values.

- Introduced `updateFieldValue` to handle empty or numeric
inputs gracefully.

- Implemented `sliderStateProxy` to synchronize range and
number inputs.

- Centralized input handling via `handleInputChange` to
simplify event management.

- Removed wired `addEventListener` logic to reduce bugs and
improve maintainability.
- Added `name` attributes to slider inputs in `index.html`
for proxy-based synchronization.
Removed test as the proxy now handles input and range
updates automatically.
The current style of file not consistent with vscode reformating style
@mohamedhyouns
Copy link
Copy Markdown
Contributor Author

After merging this and updating the DXBR builder with the new slider files, this bug will be valid and need to be fixed

@mohamedhyouns
Copy link
Copy Markdown
Contributor Author

Copy link
Copy Markdown
Contributor

@jjroelofs jjroelofs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will also comment on the issue but the bug you found is not a bug but a feature, here is why:

  1. The number input is not a real form element in this use case, it is just a tool that enhances the slider input with the possibility for more accuracy, that is why it also should not have a name attribute, we don't want to submit it separately to the server.
  2. A range element's value cannot be cleared, "empty" is not a valid state for it. That is why allowing the number input to be empty would be a bug.
  3. The default value of a range input is to be in the center. When clearing the number input, it slider goes to the center, and the number input assumes the value corresponding to the middle of range slider. This is expected behavior.

@jjroelofs jjroelofs closed this Dec 12, 2024
@mohamedhyouns mohamedhyouns reopened this Dec 16, 2024
@mohamedhyouns
Copy link
Copy Markdown
Contributor Author

@mohamedhyouns
Copy link
Copy Markdown
Contributor Author

image

@jjroelofs, I got the idea of resetting both inputs to the middle when trying to clear the input of type number. This has been addressed here.

image
@jjroelofs Regarding the current logic that fires two events, I believe it exists as a workaround to avoid incorrect setups of listeners in the live editing manager. Since creating the input of type number in the DXB slider is an async process, this workaround seems to have been added to compensate. However, as a developer, I expect only one event listener to fire when interacting with either the input of type number or type range in the DXB slider. Debugging the code step by step reveals this behavior to be a bug.

image
@jjroelofs I see the issue I’m trying to solve in the current PR is still unclear. First, let me clarify that the current issue is an atomic issue that addresses a flaw in the architecture of how the DXB slider updates values for both inputs. IMHO, we need to adopt the new logic, and it’s not feasible to split this into smaller changes due to the nature of the issue.

Since this is an atomic issue addressing multiple bugs, do you suggest releasing it as 3.x?

I recorded a video to explain why the existing logic is problematic: https://www.youtube.com/watch?v=B8V_Bw9NK44.

Copy link
Copy Markdown
Contributor

@jjroelofs jjroelofs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR is too complicated for me to review without having information about the engineering decisions that were made and why they were made, so I can't accept it without a good commit message and PR description.

Also, I don't like the requirement for a new data attribute. The attribute values added in the examples are identical to the id values with already have so it seems they are redundant. Please see if you can remove this requirement because this change makes implementation more error prone and it is not backwards compatible, meaning we would have to bump the version to 3.x.

Copy link
Copy Markdown

@mhmelshaaerdxpr mhmelshaaerdxpr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new changes introduce new bugs:

  1. Investment Amount slider example is broken.

    image

  2. The input validation is no longer working—i.e., you can set values outside the configured range or fraction of step value.

    image
    image

dxb-slider.js Outdated
return;
}

sliderStateProxy[e.target.dataset["dxbProxyKey"]] = e.target.value;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please be consistent, always use dataset.dxbProxyKey for getting and setting values. Don't mix setAttribute("data-attr-name", value) with dataset.attributeName.
Also, you may put the attribute name in a const variable and use it whenever needed instead of hardcoding the same attribute name in all uses.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dxb-slider.js Outdated
Comment on lines +103 to +105
[rangeInput, numberInput].forEach(input =>
input.addEventListener('input', handleInputChange)
);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if it's a good idea to have the same handler. For instance, we need to separate the numberInput handler and introduce a debounce to invoke the handler only after the user stops writing values—i.e., a 500ms debounce.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a4a1d4c
Adding debounce won't be a good idea, it will affect the UX I tested it with 500 and without denouncing

slider-debouce.mp4

dxb-slider.js Outdated
Comment on lines +100 to +107
// Reset the input value to the previously stored value if it exceeds the maximum allowed value
const newValue = Number(e.target.value);
const max = e.target.max;

if (max && newValue > e.target.max) {
e.target.value = sliderStateProxy[e.target.dataset["dxbProxyKey"]]
}

Copy link
Copy Markdown

@mhmelshaaerdxpr mhmelshaaerdxpr Jan 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please hand this over to the proxy not the event listener handler. This when Javascript Proxy are actually used for—i.e., validation.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown

@mhmelshaaerdxpr mhmelshaaerdxpr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please test your code thoroughly. This is the second instance where easily detectable bugs could have been caught with basic testing.

  • For ranges like [-100, 100] with default step, I cannot add negative values (it resets to mid range).
  • Value resets are confusing: Sometimes reset to max (i.e., when exceed maximum), reset to mid (i.e., on invalid input or on clear).
  • In the 100 step example, putting a fraction of a step value do approximation on the range field while keep the number as is in the input field. Did we decide at some point to do this approximation part? Regardless, there is a mismatch in behavior between the input and range fields.
  • We should provide feedback rather than do corrective actions on validation errors. This is the standard on how input fields behaves.

Although you introduce some code enhancements, I have the feeling that the new logic is a bit messy and results in more bugs. I will have to double check your final implementation after you fix the bugs.

- UPDATED: Enhanced min/max value validation to handle empty
attributes correctly
- UPDATED: Converted `validInput.min` and `validInput.max` to numbers
for consistent comparisons
- ADDED: Allow temporary entry of negative (`"-"`) and floating point
 (`"."`) characters before validation
- FIXED: Prevent premature value correction while the user is
still typing
@mohamedhyouns
Copy link
Copy Markdown
Contributor Author

mohamedhyouns commented Feb 3, 2025

  • For ranges like [-100, 100] with default step, I cannot add negative values (it resets to mid range).

The slider supports negative value: 7a41514

  • Value resets are confusing: Sometimes reset to max (i.e., when exceed maximum), reset to mid (i.e., on invalid input or on clear).

I agree, but not in all mentioned cases.

  • reset to max (i.e., when exceed maximum) -> This is a MUST since the input is bound by the slider. Please take a look at this component.
  • Clear now is allowed: 4e88e93 and 09d663a
  • In the 100 step example, putting a fraction of a step value do approximation on the range field while keep the number as is in the input field. Did we decide at some point to do this approximation part? Regardless, there is a mismatch in behavior between the input and range fields.

Sorry but didn't understand your point.

I asked ChatGPT about the proper Rounding Formula, and it gave me this 🙂
image

image

Seems to work fine for me: 1354a0c

  • We should provide feedback rather than do corrective actions on validation errors. This is the standard on how input fields behaves.

The core implementation doesn't support this at the moment. Adding it would require a new issue, as it involves some complexity and is difficult to incorporate into the current atomic PR.

mohamedhyouns and others added 4 commits February 3, 2025 09:31
- ADDED: `roundToPrecision` function to maintain correct
floating-point precision
- UPDATED: Ensured number input allows empty values without
applying calculations
- UPDATED: Added explicit parsing for `min`, `max`, and `step`
attributes to prevent unintended behavior
- UPDATED: Clamped input values within the allowed range before
applying rounding
- UPDATED: Improved rounding logic to correctly align with
step increments
- FIXED: Ensured precision consistency when updating number input values
@mohamedhyouns
Copy link
Copy Markdown
Contributor Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Buggy behaviors in number input

3 participants