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

Allow to specify custom base class for Svelte Components #4168

Open
kmmbvnr opened this issue Dec 26, 2019 · 7 comments · Fixed by #8991
Open

Allow to specify custom base class for Svelte Components #4168

kmmbvnr opened this issue Dec 26, 2019 · 7 comments · Fixed by #8991

Comments

@kmmbvnr
Copy link

kmmbvnr commented Dec 26, 2019

Could we have an option to specify a custom base class for Svelte components?

<script>
import {BaseSvelteComponent} from './base';
</script>

<svelte:options base="BaseSvelteComponent"/>

base.js:

import {SvelteComponent} from 'svelte';

export class BaseSvelteComponent extends SvelteComponent {
 /* or could be completly own custom impl */
}

It would step to make Svelte a more generic compiler and could move many conflict decisions out of the scope of Svelte project.

It allows end-users of the compiler to make own decision. I think it could resolve things like Component inheritance, move towards a solution for Custom element without shadow DOM and Support attachShadow({mode: 'closed'}), handle Native HTML elements and
Form-associated custom elements and minor things like Define some attributes on Custom Elements

And it seems pretty easy to implement - kmmbvnr@4a7f317

@kmmbvnr kmmbvnr changed the title Allow to specify custom base class for Svele Components Allow to specify custom base class for Svelte Components Dec 26, 2019
@TehShrike
Copy link
Member

Why? Inheriting from HTML elements doesn't get us any closer to using vanilla Svelte components inside the shadow dom. Is there any other motivation?

In general, inheritance is bad. We don't want to give people any encouragement to use it. Prefer composition.

@kmmbvnr
Copy link
Author

kmmbvnr commented May 19, 2020

I think commandment about composition vs inheritance more applied to business logic stuff, till there we have mostly technical question.

Svelte may compiles to Web Component, by producing custom subclass of web browser HTMLElement. New Web Component specs includes new form-associated base classes It is the only way to achieve native browser behavior with web component compiled svelte code.

Beyond that, it solves other issues listed by me in the ticket description

Probably, some more compositional approach, would be split svelte and svelte compiler, to allow just compile shadow dom related js code, without other framework-related things

@WillsterJohnson
Copy link

WillsterJohnson commented Oct 30, 2021

+1 to component inheritance (in any form)

I'm currently building a component library and having to redeclare the same few lines of code for every component is going to get old fast and be a huge pain to maintain. The best part is that the result for my components is a pretty basic (but still important) feature.

@pournasserian
Copy link

+1 to component inheritance (in any form)

@baseballyama baseballyama added this to the 4.x milestone Feb 26, 2023
@dummdidumm dummdidumm removed this from the 4.x milestone Jun 19, 2023
dummdidumm added a commit that referenced this issue Jul 18, 2023
This should help everyone who has special needs and use cases around custom elements. Since Svelte components are wrapped and only run on connectedCallback, it makes sense to expose the custom element class for modification before that.
- fixes #8954 - use extend to attach the function manually and save possible values to a prop
- closes #8473 / closes #4168 - use extend to set the proper static attribute and then call attachInternals in the constructor
closes #8472 - use extend to attach anything custom you need
closes #3091 - pass `this` to a prop of your choice and use it inside your component
@willnationsdev
Copy link

Please forgive my JS inexperience. I see how the specified feature (#8991) allows one to extend the SvelteComponent-generated class and customize it, but I don't see how it allows one to specify that it inherits from a particular class (whether that be HTMLElement or some custom BaseSvelteComponent). Am I missing something? Is there some way to use the constructor argument in <svelte:options>'s new extend function to modify the inheritance hierarchy or mix in the members of another class or something? Without an example to demonstrate, I don't see how it implements this feature request.

@dummdidumm
Copy link
Member

Yes this was closed by accident, you're right that it only allows to extend, not set a new base class.

@willnationsdev
Copy link

willnationsdev commented Jul 30, 2023

On a related note, I've been experimenting with using mixins as a workaround, and one issue I've run into is that, when I have a lot of properties added to a mixin that I intend to sync back to the DOM, I have to inline all property definitions in every customElements.props section where it's used because it requires a statically analyzable object literal. You can't just create a const object elsewhere that's imported by a <script context="module"> tag.

For example, I have a ContentElementMixin(Base) that adds a variety of properties intended to be reflected back to the DOM, including displayType, contentType, and contentId. If I then want to create a <content-menu-item> element that uses the mixin, I can't store the props definitions for those base properties in a single location; they must be inlined in the Svelte component options every time I use the mixin somewhere:

<svelte:options customElement={{tag: "content-menu-item", extend: ContentElementMixin, props: {
    displayType: { reflect: true, type: "String", attribute: "display-type" },
    contentType: { reflect: true, type: "String", attribute: "content-type" },
    contentId: { reflect: true, type: "String", attribute: "content-id" },
}} />

<script content="module">
  import { ContentElementMixin } from "./mixins.js";
</script>

Given that I'm able to import ContentElementMixin, might it be possible to at least be able to import an object literal expression from elsewhere as well? Not sure how viable that is given the synchronous & isolated nature of the JS parser, but it's worth mentioning as a pain point anyway.

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

Successfully merging a pull request may close this issue.

9 participants