Implement Web Components and LitElement
bennypowers opened this issue · comments
Hello there!
I'm the maintainer of apollo-elements
I found your project and my interest was piqued. What say you to a custom elements implementation, which could easily be extended to lit-element?
I love the idea! Would you like to implement that?
Indeed I would!
If I have any questions along the way, is there a gitter/slack/discord/hoolichat?
I'll create something like that. I'll let you know.
Make sure to check out our contributing guide!
Hey @bennypowers, how is this going? Since you created the issue I started a slack channel for the project. Here is the address if you want to get an invite: https://grafoo-slack.herokuapp.com/
Thank you! I started a new job this month, which means I haven't had the resources to make a start on this yet, but I do plan on breaking ground soon. The slack invite is well received.
👋 Me again 😄
So, I noticed that your react and preact implementations make use of render props. This pattern maps to any of several others available when we work directly with the DOM -
class mixins
a la @apollo-elements/mixins. A caveat: these aren't the mixins
you know from react land. This kind of class mixin is just function composition.
An example usage:
import { LitElement, html } from "lit-element";
import { QueryMixin } from "@grafoo/lit-element";
import query from './posts-query.graphql'; // use some loader
import style from './posts-element.css'; // use some loader
import client from './client.js';
customElements.define('posts-element', class PostsElement extends QueryMixin(LitElement) {
static styles = [style];
render() {
return html`<ul>${this.data.posts.map(this.postTemplate)}</ul>`
}
postTemplate({ content, author }) {
return html`
<li>
<h2>${author}</h2>
<article>${content}</article>
</li>
`;
}
});
We could just as easily export a base class as a mixin.
Pros | Cons |
---|---|
well worn cowpath in the web components world | FUD in some communities about the words class and mixin ? |
Decorator elements
Not much more than some setters that do Array.from(this.children).forEach(child => child.data = this.data)
;
import '@grafoo/web-components/grafoo-query';
import { LitElement, html } from 'lit-element';
import client from './client.js';
import query from './posts-query.graphql'; // use some loader
import style from './posts-element.css'; // use some loader
import './posts-element.js'; // agnostic of graphql
customElements.define('my-app', class MyApp extends LitElement {
render() {
return html`
<grafoo-query .client="${client}" .query="${query}">
<posts-element></posts-element>
</grafoo-query>
`;
}
});
In this case, GrafooQuery
, when it has a client and a query, will set the data
property on it's children (perhaps checking each that they have a data
setter first) whenever the query resolves.
Pros | Cons |
---|---|
Naive impl is very simple (a rhyme!) | Clutters the DOM |
renderer
property
Takes a function that takes a render root (shadow root or this
depending on config?) and renders to it somehow. vaadin-dialog and other elements from that set use this pattern.
import '@grafoo/web-components/grafoo-query';
import { render, html } from 'lit-html';
import client from './client.js';
import query from './posts-query.graphql'; // use some loader
import './posts-element.js'; // agnostic of graphql
const postsRenderer = ({ renderRoot, data, errors }) => render(
html`<posts-element .data="${data}"></posts-element>`,
renderRoot
);
render(html`
<grafoo-query
.client="${client}"
.query="${query}"
.renderer="${postsRenderer}"
></grafoo-query>`,
document.body
);
Pros | Cons |
---|---|
Agnostic of rendering method. You could use a library like in this example, or you could just use the DOM API. | Like the previous approach, clutters the DOM |
I'm partial to class mixins, but what are your thoughts on the matter. How would you like to do it?
I'm partial to class mixins
It also seems to me that it's the best approach, it looks more self contained. But it's not clear how would grafoo connect. I don't really care about FUD. : )
Also if we want to import graphql queries, we would have to work out a way to incrementing the babel plugin functionality.
Closing this for lack of activity.