Skip to content
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

[declarative-custom-elements] how does the class get associated with the definition #884

Open
trusktr opened this issue Jul 10, 2020 · 8 comments

Comments

@trusktr
Copy link

trusktr commented Jul 10, 2020

In the following,

<definition name="my-element">
    <template>....</template>
    <script type="module">
        class MyElement extends HTMLElement {
            #template;
            constructor(state, ...args) {
                super(state, ...args);
                #template = customElements.attachTemplateAsShadow(this, state);
            }
            render(state) {
                #template.update(state);
            }
        }
    </script>
</definition>

how does the engine know to define the <my-element> element using the MyElement class?

How does type="module" come into play here? What happens if type=module were not included?

What happens if I write two classes in the script tag? F.e.

<definition name="my-element">
    <template>....</template>
    <script type="module">
        class MyElement extends HTMLElement {
            // ...
        }
        class MyOtherElement extends HTMLElement {
            // ...
        }
    </script>
</definition>

Or is the example in the proposal missing an export? Should it be

<definition name="my-element">
    <template>....</template>
    <script type="module">
        export default class MyElement extends HTMLElement {
            // ...
        }
    </script>
</definition>

?

Happy to propose changes to the proposal file once this is cleared up.

@trusktr
Copy link
Author

trusktr commented Jul 10, 2020

I'll assume that the proposal was missing the export part.

What happens if there are multiple script tags?

<definition name="my-element">
    <template>....</template>
    <script type="module">
       export default class MyElement extends HTMLElement {
           // ...
       }
    </script>
    <script type="module">
       export default class MyOtherElement extends HTMLElement {
           // ...
       }
    </script>
</definition>

Should the <definition> accept and execute only the first script tag? Or maybe execute any script tags like normal, but take the export only from the first script tag?

Maybe the following is for another spec, but it seems there should be a way, in general, to grab the exports of a type=module script tag, f.e.

<script type="module">
   export default class MyOtherElement extends HTMLElement {
       // ...
   }
</script>
<script>
  const s = document.querySelector('[type=module]')

  // Similar to ES import():
  s.import().then(m => console.log(m.default)) // logs MyOtherElement class
</script>

Or maybe also something like

<script type="module" name="MyOtherElement">
   export default class MyOtherElement extends HTMLElement {
       // ...
   }
</script>
<script>
  const s = document.querySelector('[type=module]')

  // Using ES import():
  import('script:MyOtherElement').then(m => console.log(m.default)) // logs MyOtherElement class
</script>

@justinfagnani
Copy link
Contributor

The class should indeed be export default.

What happens if there are multiple script tags?

I think we can easily say that only the first of last module is used.

@bahrus
Copy link

bahrus commented Apr 11, 2023

I just wanted to throw out the possibility that we could morph server rendered HTML that is rendered into the live DOM tree into a "template" for a web component that could be used by other single tags. An example of how this could be useful: A server-rendered side nav component used for the hamburger menu. Then it could "progressively" be used to define the web component. Another example would be a slide show web component, where we want to display the initial slide before all the dependencies have been loaded.

POC here.

I think the performance would be better, especially if the JavaScript may have numerous dependencies that need to load before the web component could become active.

@bahrus
Copy link

bahrus commented Apr 11, 2023

It would also allow streaming to be utilized for the first instance of the declarative web component.

@bahrus
Copy link

bahrus commented Apr 11, 2023

Something to note: This solution does not require that the developer write any JavaScript, not even defining a class! Just specify prop names, which can be set via attributes, which template instantiation (especially template instantiation that uses comments for placeholders ) could fill in. Basically, do as much as possible with JSON definitions (which I believe could cover a large chunk of declarative web components).

@sashafirsov
Copy link

sashafirsov commented Apr 16, 2023

DCE does not have to use JS and IMO the "pure" DCE would be JS-less. The class would be created by the browser and use the native templating for content rendering. The element life cycle events and callbacks can be assigned either as inline onxxx or associated by embedded SCRIPT sections, something like

<script type="element/connectedCallback" >... with default export of callback

or

<script type="module" >document.currentScript.getRootNode().connectedCalback = function(){....} But it would require to add currentScript to ES6 module JS API. As of now it is only in ES5 and there is a struggle to get it approved even for inline scripts.

The <script type="module"> is optional in pure declarative case and would be needed only when there is a need to redefine the constructor. Which I hope would be less demanded when pure declarative syntax is fully functional.

@sashafirsov
Copy link

@trusktr ,
Should customElements.attachTemplateAsShadow(this, state) be separate proposal ?
I see the need for such API, but not on customElements . Rather follow the pattern of element.attachShadow

@keithamus
Copy link

keithamus commented Apr 21, 2023

WCCG had their spring F2F in which this was discussed. You can read the full notes of the discussion (WCCG had their spring F2F) in which this was discussed, heading entitled "Declarative Templating & Custom Elements".

This was briefly discussed as part of that topic. The consensus from present members of the WCCG was that more use cases need to be captured around this area, in order to clarify what these proposals solve.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants