uosis / laminar-web-components

Web Component definitions for Laminar
MIT License
36 stars 8 forks source link

Complete showcase #5

Open uosis opened 4 years ago

uosis commented 4 years ago

Use all components

mathieuleclaire commented 3 years ago

Hi, I'd like to help to complete the showcase, but I am not sure to understand how the lib works. I tried to add a simple List, inspired by the TabBar example:

 List(
        _.slots.default(
          List.ListItem(_.value :=  "first"),
          List.ListItem(_.value := "second")
        )
      )

but it only produces this html and nothing appears in the browser:

<mwc-list>
   <mwc-list-item slot=""></mwc-list-item>
   <mwc-list-item slot=""></mwc-list-item>
</mwc-list>

Any idea ?

raquo commented 3 years ago

You're rendering empty elements, that's why they don't show up in the browser. According to the documentation for this web component you need to put the name of the item you want to display as a child of that item, e.g. "Item 0". In this library this would be done like this: List.ListItem(_ => "Item 0").

The Laminar intro video talks about using web components at the end. This library follows a similar pattern so the video should help you understand how to express things in Laminar that you see in the documentation for a particular web component.

mathieuleclaire commented 3 years ago

Unfortunately, it leads to very close result.

List(
        _=> activatable := true,
        _.slots.default(
          List.ListItem(_=>  "first"),
          List.ListItem(_=> "second"),
        )
      )

leads to this: Capture d’écran du 2020-12-01 23-01-55

raquo commented 3 years ago

Hm, not sure why the styles aren't being applied. The only suspect thing here is _.slots.default(, this component's documentation does not mention anything about slots. So maybe this should work:

List(
  _=> activatable := true,
  List.ListItem(_ => "first"),
  List.ListItem(_ => "second")
)

If it produces the same HTML as the web component's docs / demos show, it really should behave the same as the styles of web components are self-contained as far as I understand.

mathieuleclaire commented 3 years ago

It has the same effect. I try this too with the same effect:

  List(
        _ => activatable := true,
        _ => List.ListItem(_ => "first"),
        _ => List.ListItem(_ => "second"),
      )

The fact is that, it produces a <mwc-list> tag instead of prducing a <li class="mwc-list"> tag. Idem for the ListItems (no <ul> tags are produced.

raquo commented 3 years ago

The fact is that, it produces a <mwc-list> tag instead of prducing a <li class="mwc-list"> tag. Idem for the ListItems (no <ul> tags are produced.

That's ok and is to be expected. Those web components don't produce <ul> or <li> tags, as you can see on their demo page. When used correctly they produce HTML like:

    <mwc-list>
      <mwc-list-item>first</mwc-list-item>
      <mwc-list-item>second</mwc-list-item>
    </mwc-list>

Now that I think of it, It kinda looks like your problem might be caused by you not importing the required JS dependency. For example, in my laminar-examples repo I have a small interface (Button.scala) for mwc-button, it includes this line:

@js.native
@JSImport("@material/mwc-button", JSImport.Default)

I don't see a similar JSImportfor mwc-list or mwc-list-item anywhere in this project. Do you have it locally? If not, this is why you're not getting the web component. This project is WIP so I don't know, maybe that's one of the missing things. Did you run amm generator/main.sc as mentioned in the readme? Maybe that will generate the right code.

Note: make sure to use JSImport properly, similarly to how it's done in my Button.scala example. Keep in mind that Scala uses dead code elimination, and object-s are lazy. The video mentions that briefly IIRC. Overall I suggest that you look at my Button.scala example because I know that it does work – you can check it out and see it for yourself. And then look at what's missing from the List and ListItem that you're looking at. JsImport is one thing but there could be more issues.

For the sake of completeness – when you add the dependency with JSImport, you will probably get an error about Scala.js being unable to find that dependency. This is to be expected, as you also need to add this dependency to your npmDependencies in build.sbt and install it (see Scala.js docs for that).

mathieuleclaire commented 3 years ago

There is the js.native and JSImport stuff here in material.scala

I tried to regenerate the material from the generator, moving to version 0.19.1, but it still the same result. I am going to investigate other components like Button.

Could it be again an asynchronousity issue ?

raquo commented 3 years ago

Ah, funny that github search doesn't quite find that, but yes, JSImport appears to be in place.

Well, I assume you're not getting any errors in the browser console, so that wouIdn't be another asynchrony issue. I'm out of ideas, sorry.

uosis commented 3 years ago

@mathieuleclaire if you are still playing around with this, I pushed a fix here.

The problem was that for this particular component, NPM package name does not match the required import, so the list item component was not getting imported. My generator doesn't even have support for different npm package vs import, so at this point if you run the generator, you need to edit the output manually to remove unnecessary package from build.sbt.

As you can see, this whole thing is very messy, as is typical in Javascript world - there are no machine readable definitions for any of these web components, so we are stuck parsing READMEs and then manually tweaking things. I wouldn't be surprised if there are more issues like this here.

mathieuleclaire commented 3 years ago

Hi uosis, Thanks for your answer. I tried your fix but it does not seem to display properly a list: image

uosis commented 3 years ago

This looks like the js import is still missing - did you rebuild components package from that branch?

cd material
sbt publishLocal

cd ../examples/showcase
sbt fastOptJS::webpack
mathieuleclaire commented 3 years ago

This works ! Thanks. Could you merge this fix in master ?

image

uosis commented 3 years ago

My generator doesn't even have support for different npm package vs import, so at this point if you run the generator, you need to edit the output manually to remove unnecessary package from build.sbt.

I just manually edited generated output to make this work - I don't really want to merge it to master because it will get overwritten unless generator is updated to support this.

mathieuleclaire commented 3 years ago

OK, so let's fix the generator then. I don't know how it works, but is it enough to switch "list" to "list-item" here ?

uosis commented 3 years ago

No, it's not as simple - we need to add support to the generator and component definitions to specify @JSImport name independently from NPM package name. Currently it assumes that they will always be the same.

So you would have something like this in definitions:

npmPackage = NpmPackage(name = "@material/mwc-list-item", version = "0.18.0"),
jsImport = JSImport(name = "@material/mwc-list/mwc-list-item"),

and the generator would need to use that to emit proper imports and dependencies.

It's not a huge amount of work, but it does require updating all definitions (or perhaps having jsImport default to npmPackage name).

mathieuleclaire commented 3 years ago

Hi, I modified the npmPackage name in the generator, and it works fine: https://github.com/uosis/laminar-web-components/pull/9