-
-
Notifications
You must be signed in to change notification settings - Fork 54
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
Web Component support #59
Comments
Hey, I don't know much about Web Components other than the general idea, but you're right, they're useful, and this is something that should be documented. I'm up for making the necessary changes and writing a documentation section about this if you can help me figure out how to use this button Web Component. I've just pushed a MwcButton.scala is our wrapper for the @material/mwc-button web component.
WebComponentsPage.scala contains the usage of this component from Laminar: MwcButton(
_.label <-- actionVar.signal,
_.icon := "code"
) This API is just something I came up with without thinking too much. It works but better solutions are possible depending on preferences / requirements. This setup works, however I have no idea how to register a click event listener on this button. If you know how to do this in Javascript, I can translate it into Laminar pretty easily unless we run into scala-js/scala-js-dom#191 or scala-js/scala-js-dom#351 (but worst case we can use js.Dynamic). Also, I'm not sure if there is anything I should be doing to manage the lifecycle of the web component. Do I need to call |
Hey, that branch looks and works great, thanks! The only issue I noticed is that for some reason host page didn't get copied to output dir during build. But it works fine when referenced from Here is relevant summary for using web components:
As you can see, there is not a lot of new concepts that need to be introduced. I don't think those Scalajs issues would affect this either - they are for defining your own Web Components, not for using them. Here is what I think we need to do:
Let me know if you have any other questions or would like to see more examples. I think I will create a dummy web component that exercises all those features, so we can easily test this. |
Thanks for all this info! You're right about the location of html file, I'm not copying it to minimize the build config. I fixed the docs. Turns out event props work as-is indeed, I've added onClick to the demo. Not sure what I did wrong the first time. Regarding reflected properties / attributes: Laminar basically treats those as props, unless you have a specific reason to treat such keys as attributes, this should work just as well in custom elements. I've added an id attribute (actually a prop) to my MwcButton facade to demonstrate. For custom CSS properties, turns out that the way I'm setting CSS props in Laminar, mutating MwcButton doesn't actually have any custom methods so I pretended it has a "doThing" method and showed how you would use it. I'm pretty sure this pattern will work with a different web component that actually has the methods defined. See web-components branch updates for all this and more: raquo/laminar-examples@e14533a More tasks:
|
I've added another commit to demonstrate how slotted children can have reactive contents. There's a memory management caveat here: the lifecycle of the slotted child's subscriptions will match that of the web component root element because Laminar doesn't know what the web component does with those children. So for example if the web component chooses to unmount some of those children, Laminar won't deactivate their subscriptions (until Laminar unmounts the root of the web component). |
This is awesome, thanks! We now have basically all the cases covered. I am still not completely clear on how to deal with properties vs attributes. We have 3 cases:
Is this accurate? Is there a way to define property as read-only? I am also not a huge fan of the underscore syntax to define custom element's attributes, but I also don't have better ideas. Normally builder style would be cleaner I think, but then it would be inconsistent with how built-in elements are defined. I created a dummy web component here that exercises all the APIs, in case you want to play with it. I will also play with it probably tomorrow to make sure all the cases work as expected. |
The three cases are accurate. You can choose to use attributes instead of
props for any custom reflected attribute if Web Components need that, just
instantiate the attr class instead of the prop class.
By read-only do you mean you want to just read the custom properties from
the custom element but not write them? Sounds like you should just add
those properties the same way as I added the doThing custom method.
…--Nikita
On Fri., Aug. 21, 2020, 7:58 p.m. Uosis, ***@***.***> wrote:
This is awesome, thanks! We now have basically all the cases covered.
I am still not completely clear on how to deal with properties vs
attributes. We have 3 cases:
1. Reflected property/attribute - use ReactiveProp
2. Property only - use ReactiveProp
3. Attribute only - use ReactiveHtmlAttr
Is this accurate? Is there a way to define property as read-only?
I am also not a huge fan of the underscore syntax to define custom
element's attributes, but I also don't have better ideas. Normally builder
style would be cleaner I think, but then it would be inconsistent with how
built-in elements are defined.
I created a dummy web component here
<https://gist.github.com/uosis/3e1a41d2f42c3dbda6b94a38c6876ebf> that
exercises all the APIs, in case you want to play with it. I will also play
with it probably tomorrow to make sure all the cases work as expected.
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#59 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAECBMFZHNW26H5HN366QSTSB4X7DANCNFSM4QG5IHMQ>
.
|
Yep, some components expose readonly properties. It makes sense to just add them to the trait together with methods. Thanks. |
I don't really want this template to be part of Laminar itself, it's just an example in the other repo. As you see there isn't much to abstract away, it's only slightly more involved than writing a regular JS facade. If you want to create a different Web Components example with a different approach that would be great, feel free to add it to that branch, laminar-examples is specifically for showcasing a variety of styles and patterns. Anyway stylistics aside, I've published Laminar v0.10.2 that has the |
I played around with my dummy component to exercise all the APIs, and things are working great for the most part. I added a couple new material components to our example to demonstrate usage of actual custom events and methods. I ran into a few minor issues:
Thanks for all your help with this! |
Thanks, those are nice additions! Regarging the failure of layout() {
this.mdcFoundation.layout()
} However, at the moment in time when Laminar has mounted the element and Looking at the implementation of the web component, it has a Bottom line, the web component seems to be initialized at the right time, before onMountCallback is called, however, its initialization is async for some reason, whereas Laminar calls onMountCallback synchronously to prevent flashes of incomplete content. Event target type refinement is typically achieved with Laminar's Regarding All the prop types we have in Scala DOM Types also duplicate the native JS props, it's just that those native props are defined on the js facades like dom.html.Element in scala-js-dom so they're out of view, but fundamentally the duplication is still there. |
Ah, this explains it. That method is just to update/"redraw" the layout of the slider, so it's supposed to return undefined. Looks like everything is working fine here, and that is just a quirk of that component.
Looks great! Yeah I was thinking of just using the node reference that we already have, rather than extracting it from event, but didn't know about inContext that makes it easy.
I agree. I imagine most of the time these definitions would be generated anyway, so duplication doesn't really matter. So I think that branch is now in a pretty good shape - we have several components that cover all the Web Component APIs, and also example usage that also covers all APIs. It should be easy to follow this to define any Web Component. I will update the example if/when Scalajs people respond about imports, but if not, it's not really a big deal to leave it as is. I will also create material component library using this pattern when I get a chance, in a separate repo. Thanks for resolving this so quickly! |
Cool, thanks for your help too, I merged the examples web-components branch into master.
That would be so awesome, people have been asking for this kind of thing forever! It doesn't even need to be comprehensive from the start, I think you'll find contributors for such a project pretty easily if you just start with something. Cheers |
Hi, Thanks for this amazing work ! |
Hi, there is a WIP generator for many material UI web component interfaces
for Laminar, see here: https://github.com/uosis/laminar-web-components
If I understand correctly it can already be used as a decent starting point
but it would be great to implement the missing functionality of the
generator too.
…--Nikita
On Wed., Nov. 25, 2020, 1:32 a.m. Mathieu, ***@***.***> wrote:
Hi,
is there any effort to start a repository with Web Component wrapping so
that they can be directly be used in a web ui construction ? Or is there
only Button, Slider, ProgressBar wrappers so far ?
Thanks for this amazing work !
—
You are receiving this because you modified the open/close state.
Reply to this email directly, view it on GitHub
<#59 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAECBMAAZX4BYESX5O6BRBTSRTFL7ANCNFSM4QG5IHMQ>
.
|
Excellent, thanks for sharing. I will try to work with this. |
The project is not done yet so I can't rely on it. The repo is mentioned in
a few places including the video if I recall correctly.
…--Nikita
On Wed., Nov. 25, 2020, 5:58 a.m. Mathieu, ***@***.***> wrote:
Excellent, thanks for sharing. I will try to work with this.
Peharp's you could mention it on your front web page and/or rely on it in
your laminar example ?
—
You are receiving this because you modified the open/close state.
Reply to this email directly, view it on GitHub
<#59 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAECBMH6MVPZX4OR4ALJ7ZLSRUEPBANCNFSM4QG5IHMQ>
.
|
I was wondering if there is any interest in supporting Web Components in Laminar? I am not sure if there is anything that actually needs to change in the core project, perhaps just having an example of a proper way to add and use Web Components. This would hopefully alleviate the complaint that Laminar has no ready to use components.
I got a proof of concept working as follows:
mwc-button
html tag that behaves just like any other tag. Use it in Laminar (this is just a random button added in TodoMVC example):In summary, the process to add a Web Component is:
What is the best way to do those two things? In particular:
Thanks for making Laminar!
The text was updated successfully, but these errors were encountered: