grafoojs / grafoo

A GraphQL Client and Toolkit

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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.