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
FromControl label should have "for" attribute #445
Comments
Good catch - we will repair this soon, as we are working on some improvements for the formControl concept currently. So I will integrate this issue when solving #440 issue. |
Ok, this is going to be harder than expected... (so it won't make it into the 0.11.1 version) In order to make this work, we have to determine the ID of the control prior to its rendering. Thus the wrapped factory methods within // get or cerate an ID
protected fun determinedControlId(external: String?, storeId: String?) =
external ?: (storeId ?: "control-${uniqueId()}")
open fun inputField(
styling: BasicParams.() -> Unit = {},
value: Store<String>? = null,
baseClass: StyleClass = StyleClass.None,
id: String? = null,
prefix: String = ControlNames.inputField,
build: InputFieldComponent.() -> Unit = {}
) {
val validationMessagesBuilder = ValidationResult.builderOf(this, value)
// add new ``controlId`` parameter as new second param
registerControl(
ControlNames.inputField,
determinedControlId(id, value?.id), // add determined ID
{
inputField(styling, value, baseClass, id, prefix) {
size { this@FormControlComponent.sizeBuilder(this) }
severity(validationMessagesBuilder().hasSeverity)
build()
}
},
{ this.validationMessagesBuilder = validationMessagesBuilder }
)
} So the protected fun registerControl(
controlName: String,
controlId: String, // new
component: (RenderContext.() -> Unit),
onSuccess: FormControlComponent.() -> Unit = {}
) {
// pass this to control -> make Triple out of Tuple (or custom data class?!)
if (control.set(controlName, controlId, component)) {
onSuccess(this)
}
} Make val control = Control() Now we can access the ID for the control from a renderer: class SingleControlRenderer(private val component: FormControlComponent) : ControlRenderer {
override fun render(
styling: BoxParams.() -> Unit,
baseClass: StyleClass,
id: String?,
prefix: String,
renderContext: RenderContext,
control: RenderContext.() -> Unit
) {
renderContext.stackUp(
{
alignItems { start }
width { full }
component.ownSize()()
styling(this as BoxParams)
},
baseClass = baseClass,
id = id,
prefix = prefix
) {
spacing { tiny }
items {
label({
component.labelStyle.value()
}) {
// here we can finally access the desired ID
component.control.assignee?.let { `for`(it.third) }
className(formGroupElementLabelMarker)
+component.label.value
}
stackUp({
alignItems { start }
width { full }
}) {
spacing { none }
items {
control(this)
component.renderHelperText(this)
component.renderValidationMessages(this)
}
}
}
}.apply {
className(formGroupElementContainerMarker)
}
}
} This all sounds reasonable, but: How do we pass this ID down to the control itself!? There are several solutions to this problem:
This is not trivial to decide, so we must discuss the further approach within a bigger group! SidestepWe should nevertheless and idenpendently from the above feature pass a well defined ID as ID of the control in order to make it plausible for testing to observe a specific control element. |
Why not just nest the |
Because of #440 ;-) We absolutly need two DOM elements on the same level to achieve this. So nesting is no option here. Edit: |
The problems mentioned in #445 (comment) aren't valid: There are several solutions to this problem:
This is quite easy though in combination with the above solution: Juts define a default value for fun RenderContext.inputField(
styling: BasicParams.() -> Unit = {},
value: Store<String>? = null,
baseClass: StyleClass = StyleClass.None,
id: String = value?.id ?: "inputField-${uniqueId()}", // take the store's id if present, if not generate one.
prefix: String = "inputField",
build: InputFieldComponent.() -> Unit = {}
) {
InputFieldComponent(value).apply(build).render(this, styling, baseClass, id, prefix)
} TroubleThe above solutions work well - if the We should consider to apply always a random unique ID per default: open class RootStore<T>(
initialData: T,
override val id: String = "" // This is the problem! ``uniqueId()`` to the rescue?
) : Store<T> {
// and so on
} |
|
- fixes #445 - formControl now determines an ID for each control and makes this available to the renderers, so they can use it as reference for semantically grouped elements like label's ``for`` and some related ``input`` - add default none empty ID to ``RootStore`` and its factory function ``storeOf``.
Describe the bug
FromControl label should have "for" attribute, so when user click on the label, the input gets automaticaly focused.
To Reproduce
Steps to reproduce the behavior:
formControl
withlabel
andinputField
.Expected behavior
Cursor will appear inside the
inputField
(or, in case of chackbox, the checbox is toggled)Additional context
Or, you can nest the
<input
>inside
` to get the same behaviour.https://developer.mozilla.org/en-US/docs/Web/HTML/Element/label
The text was updated successfully, but these errors were encountered: