Open mathieuleclaire opened 3 years ago
Is this "Textfield" of yours a web component?
Check its docs for what it wants about forms, maybe it needs to be put inside a form element or you need to provide some custom attribute linking to the form or something.
If the error really is related to onMountFocus, make sure your web component produces an input element and not some div wrapper.
--Nikita
On Wed., Nov. 25, 2020, 1:35 p.m. Mathieu, notifications@github.com wrote:
Hi, I am tryiing to reproduce Laminar Hello World example https://laminar.dev/examples/hello-world, but the onMountFocus raises a js exception. Is it an exepected behaviour ?
val component = div( Textfield( => onMountFocus, => value <-- actionVar.signal, => inContext { thisNode => onInput.mapTo(thisNode.ref.value) --> actionVar }, .label := "Name", .outlined := true, .placeholder := "Name" ), span( "Hello, ", child.text <-- actionVar.signal.map(_.toUpperCase) ) )
raises the js exception:
ObserverError: TypeError: this.formElement is null
Thanks, and congrats for this work !
— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/uosis/laminar-web-components/issues/6, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAECBMAHEJPX6G5DVECIUITSRV2APANCNFSM4UC5OB3A .
It is the TextField wrapped in this library: https://github.com/uosis/laminar-web-components/blob/master/material/src/main/scala/material.scala#L3340
The debugger indicates that an input
is produced:
<input aria-labelledby="label" class="mdc-text-field__input" type="text" placeholder="Name">
Laminar's onMountFocus
correctly calls customElement.focus()
after the element is mounted. Specifically, I think that would be this method for this web component: https://github.com/material-components/material-components-web-components/blob/4a5d4eebd1ecf1c54515f7b42c7ec882d4d83470/packages/textfield/mwc-textfield-base.ts#L234
Why this web component's formElement
is null
at this point, I don't know. Maybe it needs more time to initialize after being mounted or something. I don't know much about how web components are implemented.
You're right, a 1ms delay does the trick.
_ => onMountCallback(ctx => {
js.timers.setTimeout(1) {
ctx.thisNode.ref.focus()
}
})
As, it seems to be a recurent issue (like Material UI and Progresse bar here: https://laminar.dev/examples/web-components), what do you think of proposing timer wrappers for all your onMount
methods ? The onMountFocus would become:
val onMountFocus: Modifier[HtmlElement] = onMountFocusAfter(0)
def onMountFocusAfter(delay: Int = 0): Modifier[HtmlElement] = onMountCallback(ctx => {
js.timers.setTimeout(delay) {
ctx.thisNode.ref.focus()
}
})
Or to set a timeout(1) directly in your mount methods, whatever the component used.
You should probably wrap the focus()
call into if (ChildNode.isNodeMounted(ctx.thisNode))
to mitigate the edge case when the component will be unmounted before it has a chance to focus itself. Stuff like this is why I don't like async APIs.
If I were to add these async helpers into Laminar, I'd need a good reason – it's one thing if web components can't possibly be implemented synchronously due to some web platform constraints (and if that's the case, I would need to know what exactly those constraints are so that any potential Laminar helpers would solve the problem in all cases), but if it's just this particular set of web components that are internally poorly implemented, then I'm less inclined to develop ad-hoc helpers for that.
Hi, I am tryiing to reproduce Laminar Hello World example, but the
onMountFocus
raises a js exception. Is it an exepected behaviour ?raises the js exception:
Thanks, and congrats for this work !