DEV Community

Discussion on: Web Components: from zero to hero

Collapse
 
thepassle profile image
Pascal Schilp • Edited

Hi Neville!

When writing raw web components, you can set the markup of the light DOM like so:

class MyElement extends HTMLElement {
  constructor() {
    super();
    this.innerHTML = '<h1>hello world</h1>';
  }
}

Notice how we omit attaching the shadowroot to our element, making it render to the light DOM instead.

In LitElement you can override the createRenderRoot() and return this to make your element render to light dom instead. You're essentially changing the renderroot from the default shadowroot (LitElement defaults to using shadow DOM), to the light dom. You can see an example of that in action here:
stackblitz.com/edit/create-lit-app...

Furthermore; yes, you are correct; when using shadow DOM, you can use slots to render markup from a parent into a child component. The slot API is part of shadow DOM, so you can't have one without the other. (eg: you can't use the slot API with light DOM).

Here's an example of using slots:
stackblitz.com/edit/create-lit-app...

And here's some recommended reading on using slots (the mozilla docs are an incredible reference for anything web components):
developer.mozilla.org/en-US/docs/W...

I hope that's helpful!

I can also vouch for benny's series, I've read them all, and they're all great and showcase really detailed and diverse examples of different web component technologies. :)

Edit: I'm currently working on part 2 of this series, which will talk more about lit-html/element.

Collapse
 
getclibu profile image
Neville Franks

Hi Pascal,
Thanks for your reply. I have been very successfully using Riot.js for quite a while in our Web App Clibu(clibu.com) and would like to move to using Web Components, hence my interest.

I starting playing with Lit-Element a few days ago and I am impressed so far, however as is often the case it is one step forward, two back. ;-)

I am aware of using Light DOM with lit-element which would be an easier initial transition, however I'm currently stuck on using nested components in Light DOM. I've put a sample at stackblitz.com/edit/create-lit-app... and you'll see that <nested-light-dom> doesn't display any content.

Am I right that this isn't possible without using Slots and therefore Shadow DOM?

Thread Thread
 
thepassle profile image
Pascal Schilp

You are correct, you'd have to use slots and shadow DOM to achieve something like this. Do you mind me asking what your use case for this is though? Generally components that use light DOM are simpler leaf/UI components.

Thread Thread
 
getclibu profile image
Neville Franks

Pascal, thanks for the clarification.

What I find somewhat confusing with custom elements is they don't behave like normal elements. For example:

<div>Hello
  <div>Neville</div>
</div>

displays "Hello Neville" whereas:

<custom-element>Hello
  <custom-element>Neville</custom-element>
</custom-element>

Only displays 'Hello'.

I've put up a sample of what I'm trying to accomplish at: stackblitz.com/edit/create-lit-app...

What I want is to have a Web Component that expands & collapses the Web Components nested inside it.

For some reason I don't yet understand the demo app is not working correctly, ie. there is no animation for the transition specified in card-element and the height doesn't reduce to zero.

The same sample without using card-element works perfectly. ie. Replace <card-element> in <container-element> with <div style="transition-...>

I assume that my current lack of knowledge with Shadow DOM will explain the underlying issue, or not. ;-)

Thread Thread
 
thepassle profile image
Pascal Schilp • Edited

Hi Neville, I quickly hacked together this example for you:
stackblitz.com/edit/create-lit-app...

I hope that helps you :-) Feel free to reach out if you have any more questions.

Thread Thread
 
getclibu profile image
Neville Franks

Hi Pascal, that's great and works perfectly and is simpler. Any idea why my code didn't work, just curious.

Thread Thread
 
thepassle profile image
Pascal Schilp • Edited

in card-element.js, change:

const el = this.querySelector( 'h1' )

to:

const el = this.shadowRoot.querySelector( 'div' );

When querying for DOM in web components, you want to target the shadowRoot. Also, you were querying for and changing the height of the h1, while really, you wanted to change the height of the container div.

And you had a bunch of js you didnt really need 😛LitElement will take care of your properties for you. You can use your own getters and setters, but we didn't really need to here. I'll expand more on LitElement in part two of this blog series.

Thread Thread
 
getclibu profile image
Neville Franks • Edited

Thanks again, much to learn about shadow dom and LitElement. Happy enough though for my first week.

Can I suggest you include some downloadable examples in future articles. Stackblitz is awesome as well.

Often we just get pieces of Javascript which are great at explaining things, but when we try and run something like LitElement for the first time we get stuck with build tools and errors in the Browser until we get everything sorted out.

I hadn't found github.com/thepassle/create-lit-app when I started last Monday, which was a pity. I like Parcel.js which is what I'm using, but it took some time to get code that ran without errors.

I'll look forward to your future articles.

PS. My wife is Dutch. Amsterdam is great. ;-)

Thread Thread
 
thepassle profile image
Pascal Schilp • Edited

Yeah, takes some time to get used to web components, but when everything clicks they're well worth it (especially LitElement).

As for downloadable examples, you can find the source code of this blog over here: github.com/thepassle/webcomponents...
(You can run it locally with python -m SimpleHTTPServer 8000, or any other method of serving)

Feel free to reach out if you have any more questions, you can find me on twitter, and usually on the polymer slack.