Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

setValue doesn't trigger validation for some TB field elements #3420

Closed
vursen opened this issue Jul 1, 2022 · 5 comments · Fixed by #3490
Closed

setValue doesn't trigger validation for some TB field elements #3420

vursen opened this issue Jul 1, 2022 · 5 comments · Fixed by #3490
Labels
enhancement New feature or request Impact: Low

Comments

@vursen
Copy link
Contributor

vursen commented Jul 1, 2022

Description

Currently, Field TestBench elements trigger blur and change on the component's host rather than the input when setting a value with setValue(), which results in validation not running.

@Override
public void setValue(String string) {
HasStringValueProperty.super.setValue(string);
dispatchEvent("change", Collections.singletonMap("bubbles", true));
dispatchEvent("blur");
}

This is apparently an omission from the a11y slotted refactoring.

Affected components

  • TextFieldElement
  • TextAreaElement
  • EmailFieldElement
  • IntegerFieldElement
  • NumberFieldElement
  • PasswordFieldElement
  • BigDecimalFieldElement

Expected outcome

setValue() of Field TextBench elements should trigger blur and change on the input rather than the host after a new value is set.

Note, if change and blur are triggered on the input, then setValue() should also trigger an input event before the change event as otherwise the input's value won't be synced with the field's value property.

Environment

Vaadin version(s): 21, 22, 23
OS: Mac OS

Browsers

No response

@vursen vursen changed the title The setValue method of Field TestBench elements doesn't trigger validation The setValue method of Field TB elements doesn't trigger validation Jul 1, 2022
@vursen
Copy link
Contributor Author

vursen commented Jul 2, 2022

I wonder if it might be more suitable to have a separate method setInputValue specifically for emulating setting an input value (that would trigger blur, change, and so on) while the existing setValue method would only set the value property on the component without triggering any DOM events.

It is currently confusing that setValue in some TB elements (e.g. DatePickerElement) only sets the value property while in others (e.g. TextFieldElement) also triggers some events.

This ticket is probably a good time to decide whether we want to align that or keep these methods working the old way.

/**
* Sets the selected date as a string.
* <p>
* The value is always in format <code>YYYY-MM-DD</code>.
*
* @param value
* the value to set
*/
protected void setValue(String value) {
setProperty("value", value);
}

/**
* Opens the overlay, sets the value to the inner input element as a string
* and closes the overlay. This simulates the user typing into the input and
* triggering an update of the value property.
*/
public void setInputValue(String value) {
this.open();
setProperty("_inputValue", value);
this.close();
}

UPD: If we trigger change and blur on the input as proposed above, then, in order for the input's value to get synced with the field's value property, we also have to trigger an input event before the change event.

@yuriy-fix yuriy-fix added enhancement New feature or request Impact: High and removed regression labels Jul 5, 2022
@yuriy-fix
Copy link
Contributor

We would probably want to modify setValue to not trigger events (i.e. blur)

@vursen
Copy link
Contributor Author

vursen commented Jul 19, 2022

The alternative way could be to ensure every field component provides a sendKeys method for emulating user input.

It should be said though that using sendKeys can be a bit inconvenient and clunky in the situation when you need to replace the whole value at once which is often the case in tests. The way you would currently do that: select the input value (either with a key shortcut or a JavaScript API), press Backspace and only then you can type a new value. So, at least, it might be useful to have a shorthand method for that purpose to avoid repetition.

public void sendKeys(CharSequence... keysToSend) {
  $("input").first().sendKeys(keysToSend);
}

public void sendKeysClearAll() {
  sendKeys(Keys.SHIFT, Keys.HOME, Keys.BACK_SPACE);
  // or
  // sendKeys(Keys.META, "A", Keys.BACK_SPACE);
}

@vursen
Copy link
Contributor Author

vursen commented Jul 20, 2022

The sendKeys API doesn't suit all the cases.

Example: an input has a maxlength, so you can't enter more than the specified number of characters to it with the keyboard. However, you might still want to set the value to something longer in order to test validation. This is when setInputValue would come in useful.

@vursen
Copy link
Contributor Author

vursen commented Jul 21, 2022

On closer inspection, it turns out that setValue in its default implementation is actually useless at least for components in the text-field package. The reason is ValueChangeMode.ON_CHANGE which is enabled for the components by default so just updating the value property on the client-side doesn't cause it to sync on the server-side unless a change event is fired on the component. But if we trigger that change event, we end up with two methods doing pretty much the same.

So, it seems that the only reasonable option that remains would be to fix setValue to make it set value on the input element and trigger the respective events.

@vursen vursen changed the title The setValue method of Field TB elements doesn't trigger validation setValue doesn't trigger validation for some TB field elements Jul 22, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request Impact: Low
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants