It is not possible to enter a fractional value in a text field with a textChangeTimeout set like this one:
val field: TextField<BigDecimal> = uiComponents.create(TextField.NAME)
field.textChangeTimeout = 300
field.textChangeEventMode = TextInputField.TextChangeEventMode.LAZY
field.setFormatter { null } // makes no difference...
field.valueSource = ContainerValueSource(table.getInstanceContainer(entity), "amount")
“amount” of entity is a BigDecimal field. You would have to be faster than the 300ms with the comma and the value to be able to enter a fractional value. Is there a way around that problem, but still firing the change event after a timeout?
I’d love to be able to set the input type to behave just the way it behaves with normal string input… Validation should work exactly as it is now, but I don’t want the formatter to do anything. That’s not possible right now, because the field with the value source attached always sets the new value to presentation after change.
The field should change its value on load, but not on user change. It would be ideal, if we can have a propert for that.
Extending TextField component. Override componentValueChanged() method and register this component: Component registration.
Using Vaadin TextField. Subscribe on value change event of TextField and ContainerValueSource. As it’s a Vaadin component, you need to wrap it into the Jmix component, e.g CssLayout:
Nr 1 I tried already, but the problem is in the setValue() method. This method is also called when the value changes and the origin of the change can’t be differentiated between a “onLoad change” and a user-originated change.
Could you clarify you extend TextField and there manage updateValueToPresentation option?
If you set value programmatically, the TextField presentation value won’t be updated. But it should work if the value is updated from the client-side, like in your case.
Thanks @pinyazhin and sorry for the late reply. I built my own text field now, the code looks like this:
import io.jmix.ui.component.impl.TextFieldImpl
open class MyTextField<VALUE> : TextFieldImpl<VALUE>() {
companion object {
const val NAME = "myTextField"
}
private var updatedValueFirstTime = false
/** If set to false, only the first value retrieved - the loaded value - will be set to presentation.
* Subsequent changes to the value won't be set to presenatation. */
var updateValueToPresentation = true
override fun setValueToPresentation(value: String?) {
if (hasValidationError()) {
setValidationError(null)
}
if (updateValueToPresentation || !updatedValueFirstTime) {
updatedValueFirstTime = true
component.value = value
}
}
}
This works. It puts the value the first time it is loaded to presentation and then I can update the value eagerly from the text field without interrupting the input experience of the user.