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

Composite custom element is not defined until the parent element is connected #765

Closed
HitalloExiled opened this issue Sep 7, 2018 · 5 comments

Comments

@HitalloExiled
Copy link

I have a host custom element that receives as dependency another custom element. And still in the host constructor, I need to access some parameterized data from this dependency. However, because the host is not yet connected, the element inserted in the slot has not yet been defined.

I do not know if this is a design decision, but it is particularly annoying. Even more so because there are workarounds not very elegant, such as cloning the dependency, which will return a registered node, and replace the original node by the clone.

@caridy
Copy link

caridy commented Sep 8, 2018

Can you provide more details? What does "receives as dependency another custom element" means?

@rniwa
Copy link
Collaborator

rniwa commented Sep 8, 2018

Yes, this was a deliberate decision.

Basically, a parent node relying on its child nodes' state is never sound because the HTML parser can incrementally insert more child nodes, and there is no callback or notification as to when child nodes had finished parsing. In fact, any access to the custom element's child nodes or parents inside its constructor is unsound as the HTML would invoke the custom element constructor on synchronously constructed (as opposed to upgraded) custom elements before it gets inserted into the tree.

Instead, the encouraged patterned is for those child nodes to notify the parent as they become inserted. An alternative approach is to use MutationObserver and take the action whenever your host's child nodes change.

@rniwa
Copy link
Collaborator

rniwa commented Sep 8, 2018

Note that if we did bottom-up upgrades like you're suggesting, we'd end up with a bunch of unupgraded custom elements all waiting for all its descendents to be fetched & parsed by the HTML parser. In the worst case scenario, the entire page doesn't get renders / doesn't function until everything is fetched & parsed.

We've also considered upgrading elements as they're accessed but this will impose a significant perf cost on every access DOM API imaginable like firstChild, and deemed unacceptable from implementor's perspective. Having said that, if you're so inclined, you can manually invoke customElements.upgrade on all your child nodes manually before accessing them. (I just added the support for it in WebKit/Safari a couple of weeks ago so it's not widely available yet though :()

@HitalloExiled
Copy link
Author

@rniwa

I figured it might be something like that and there could be some downsides.

But the fact that I could get the registered element simply by cloning it deceived me.

@caridy

I'm working on a data-table component that receives as a dependency a data-provider component.

<data-table>
	<data-provider read-url="/user/read" page-size="10"></data-provider>
	<template>
		<column-definition style="width: 50px;" header="Id"       field="id"></column-definition>
		<column-definition                      header="Name"     field="name"></column-definition>
		<column-definition                      header="Email"    field="email"></column-definition>
		<column-definition                      header="Country"  field="country.name"></column-definition>
		<column-definition                      header="Initials" field="country.initials"></column-definition>
		<column-definition                      header="Active"   field="active" field-type="boolean"></column-definition>
	</template>
</data-table>

The data-table is only aware of the data-provider interface, which can have any implementation.

Programmatically, I could simply pass the instance of the provider directly into the component constructor. But I would like to go further and have the option to do the same in a declarative way.

In my first scenario, I needed to call the read method of the data-provider already in the construction of the data-table. Currently this is no longer a problem, the fact that I can not depend on a clean way of a child element already in the constructor is making me review some concepts. But that's what led me to the initial conclusion.

But I can see something like a recurring pattern in composite components.

@rniwa
Copy link
Collaborator

rniwa commented Sep 19, 2018

Closing the issue for now. If you have a further question, we can re-open this issue, or you can file a new issue.

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

No branches or pull requests

3 participants