-
Notifications
You must be signed in to change notification settings - Fork 319
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
[question/proposal] Scoped Slots #646
Comments
Pease do not copy and add features from vue, react or similar framework. From the Readme.md
Lit is not a framework, it's a tiny library. Keep it simple as much as possible. |
Just a little extended information about this, because I think this request is recurrent and with a reason. You can create webcomponents with lit element without much problems, until you really try to use it in advanced applications, when you try to generate really reusable webcomponents you realize that create a tag that gets a lot of properties and render some fixed stuff is just not enough. the real way to generate reusable components is to leverage the slots, you generate a component that gets some properties and render some combination of html but you allow other users to use his own templates. Polymer 1 and 2 has one of the most powerfull, and sadly little know, behaviour, the templatizer, that allows you to create really reusable components. all the mayor table components in the opensource and in private companies use templatizer to generate a table that can be used in all scenarios, not just because explorer gets out the templates tags from the table, but because is the way of generate real reusable components. when we go to the original examples of components, most of them where leveraging the content, some thing like and thats limit a lot the components reusability, I think it is important to remember that a webcomponent should be able to adapt to multiple scenarios. if you are creating a webcomponent and use it only once you are doing something wrong, and also if every time some one has to use your component need to do a pull request or make changes the you are doing also something wrong. |
@guzmanpaniagua you can offer the following public api which should be even more powerful const messageTemplate = (message) {
return html`<foo>${message}</foo>`
}
// usage
render() {
return html`<my-el .messageTemplate=${messageTemplate}><my-el>`;
} |
@webfolderio Im not trying to suggest lit element gets turned into a framework, providing a feature that "happens" to be invaluable in some popular frameworks i don't think is enough reason to discount it as a valid proposal. I understand the concept of not generating new features everywhere to keep the library focussed, but enhancing an existing feature im struggling to understand the negatives. Slots are crucial to web components, and it would be wrong to assume this idea wasnt at least in part inspired by existing solutions to templating (ie frameworks). Slots and especially scoped slots provide tremendous flexibility and enhance the ability to use component composition to structure your markup. Composition at the html level is much easier to reason about. Its still a hard goal to achieve, but providing better interfaces to do so enabled more rapid development, happier development experience and guides the community to composition over inheritance. Take the following example, a component that loads a list of "things" from an api:
This may render in its shadow root:
What happens when you want to change the markup of the list items in a separate use of the component?
With all of these solutions, you are either making your components more complex, not reusing components, or hiding your markup in javascript and/or away from users. With a scoped slot you could do the following:
And in another location:
Im rambling now, there is most likely better examples to illustrate my point but i hope this could be discussed further and some feedback from the maintainers so it's clear not just for me but others in future. |
@daKmoR your proposal is exactly what I do currently in a 💯 LitElement app with 200+ comps. It works incredibly well, I would even go as far as saying it is more powerful and dynamic than slots from querying to styling to dynamic layouts/polymorphism and more. Just thought I would throw in my two cents. |
Just to clarify im not suggesting @daKmoR solution isnt valid, it is as it stands the correct solution to this problem, my point is that solution enforces the end user to create a new element to use an element. Think from a component library perspective, you're enforcing the user to write their markup in javascript, making distribution more of a burden on the component user. Say a CMS user wants to use a const pointTemplate = (locationName) {
return html`<strong>${locationName}</strong>`
}
// usage
render() {
return html`<g-maps .pointTemplate=${pointTemplate}><g-maps>`;
} With a scoped slot you would simply import the component in your document, and use like this: <g-maps>
<strong slot="pointer">${locationName}</strong>
</g-maps> A full javascript oriented solution like that suggested by @daKmoR is and always will be more flexible, but it puts the burden on end users to understand lit element, compose via javascript and not html markup, which less experienced/confident end users will shy away from. |
@leemason you can use the |
We definitely don't want to start evaluating JavaScript expressions from HTML. That's a huge XSS hole, and a non-starter for this project. There are use cases for passing templates to components to be evaluated by the component. @daKmoR showed the simplest and most powerful solution, which is equivalent to render props in the React ecosystem. The only downside there is that this API is not available from plain HTML. In order to allow templated content from HTML, we really need an HTML-based templating system, and the component's contract needs to specify that system. It's necessarily a tight coupling (until we get Template Instantiation in the browser, at least). This tight coupling is potentially a problem, and one that's not apparent in a framework because everything in the framework is a tight coupling. It doesn't stand out as a problem that Vue scoped slots use Vue template syntax because everything in Vue does. With web components, you'd have to document that your component uses lit-html syntax, while your users should ideally not know or care that the component was even implemented with LitElement. One way forward here would be for lit-html to add an HTML-based template system. There's an issue for that there already. WIth that, components could allow for template children, like: <my-element>
<template>
<strong slot="pointer">{{locationName}}</strong>
</template>
</my-element> This is actually possible today if you bring together the right pieces. For an example see Microsoft's graph toolkit components, which use LitElement: https://github.com/microsoftgraph/microsoft-graph-toolkit/blob/master/docs/templates.md I think we can close this issue for now, as there won't be any work here until we have better options for templating from within HTML itself. In the meantime I recommend the render props pattern. |
Description
Im currently getting my head round lit element coming from a vue background and its all very promising. One thing that i cant settle in my head is scoped slots.
They are a great feature in vue and ive created a crude example which could work.
Asking here first to see if its something worth further investigation and/or a pr.
It appears the slack channel goes to a heroku app so couldn't see a better place to ask.
The idea being you take the content of the slot and evaluate that in the context of the component itself, providing access to the components properties, yet maintaining the flexibility of the slot.
Ive has soo many use cases for this in vue previously.
The demo is far from a pr example, im just trying to show the concept to see if further investigation is warranted.
Live Demo
https://stackblitz.com/edit/pm5bzr
The text was updated successfully, but these errors were encountered: