Options
All
  • Public
  • Public/Protected
  • All
Menu

Apollo Elements

Apollo Elements

๐Ÿš€ Apollo Elements ๐Ÿ‘ฉโ€๐Ÿš€

๐ŸŒ‘ Custom elements meet Apollo GraphQL ๐ŸŒœ

๐Ÿ‘ฉโ€๐Ÿš€ It's one small step for a dev, one giant leap for the web platform! ๐Ÿ‘จโ€๐Ÿš€

Made with open-wc Contributions Welcome ISC License Maintainability Test Coverage Release

Apollo Elements offers packages based on a variety of underlying web component authoring libraries. You can pick the one that suits your project in order to keep your app sizes small.

npm init @apollo-elements

๐Ÿค– Demos

๐Ÿ—บ Guides and Docs

If you just want to see the API Docs, check them out for all our packages at apolloelements.dev

Works Across Frameworks

Elements created with Apollo Elements work in any framework. Write GraphQL components once and use them in page with ease, even Angular, Preact, React, Svelte, or Vue apps.

๐Ÿ“ฆ Packages

Apollo Elements offers packages based on a variety of underlying web component authoring libraries. You can pick the one that suits your project in order to keep your app sizes small.

๐Ÿงฑ Components

Utility components that help you factor your graphql-based app.

  • <apollo-client> provides all it's children (even across open shadow roots) with a client instance.
  • <apollo-mutation> lets you write declarative mutation components without subclassing.
npm i -S @apollo-elements/components
import '@apollo-elements/components/apollo-client';
import '@apollo-elements/components/apollo-mutation';

๐Ÿ‘‡ Click for Example ๐Ÿ‘‡

<script type="module"
  src="https://unpkg.com/@apollo-elements/components?module"></script>
<script type="module"
  src="https://unpkg.com/@apollo-elements/polymer/apollo-query?module"></script>

<apollo-client uri="/graphql">
  <apollo-query>
    <script type="application/graphql">
      query QuoteQuery($name: String) {
        quote name
      }
    </script>
    <script type="application/json">
      { "name": "Neil Armstrong" }
    </script>
  </apollo-query>

  <apollo-mutation data-type="Quote">
    <script type="application/graphql">
      mutation QuoteMutation($name: String, $quote: String) {
        addQuote(name: $name, quote: $quote) { name quote }
      }
    </script>
    <button slot="trigger">OK</button>
    <label for="name">Name</label>
    <input id="name" slot="variable" data-variable="name" value="Neil"/>
    <label for="comment">Comment</label>
    <textarea id="comment" slot="variable" data-variable="quote"
              value="That's one small step..."></textarea>
  </apollo-mutation>
</apollo-client>

Read More

๐Ÿธ Mixins

These custom element class mixins give you all the features you need to connect your components to your Apollo cache without imposing a specific component library.

npm i -S @apollo-elements/mixins
import { ApolloQueryMixin } from '@apollo-elements/mixins/apollo-query-mixin';
import { ApolloMutationMixin } from '@apollo-elements/mixins/apollo-mutation-mixin';
import { ApolloSubscriptionMixin } from '@apollo-elements/mixins/apollo-subscription-mixin';

๐Ÿ‘‡ Click for Example ๐Ÿ‘‡

import { ApolloQueryMixin } from '@apollo-elements/mixins/apollo-query-mixin';

import HelloQuery from './Hello.query.graphql';

const template = document.createElement('template');
template.innerHTML = `
  <span id="hello"></span>
`;

class HelloElement extends ApolloQueryMixin(HTMLElement) {
  query = HelloQuery;

  #data = null;

  set data(data) { this.render(this.#data = data); }

  get data() { return this.#data; }

  constructor() {
    super();
    this.attachShadow({ mode: 'open' })
      .append(template.content.cloneNode(true));
  }

  render() {
    const greeting = this.data?.greeting ?? 'hello';
    const name = this.data?.name ?? 'world';
    this.shadowRoot.getElementById('hello').textContent =
      `${greeting}, ${name}!`;
  }
}

customElements.define('hello-element', HelloElement);

Read More

๐Ÿ”ฅ lit-apollo

These base classes extend from LitElement, so you can quickly get up and running creating declarative front-ends with Apollo GraphQL.

npm i -S @apollo-elements/lit-apollo
import { ApolloQuery } from '@apollo-elements/lit-apollo/apollo-query';
import { ApolloMutation } from '@apollo-elements/lit-apollo/apollo-mutation';
import { ApolloSubscription } from '@apollo-elements/lit-apollo/apollo-subscription';

๐Ÿ‘‡ Click for Example ๐Ÿ‘‡

import { ApolloQuery, customElement, html } from '@apollo-elements/lit-apollo';

import HelloQuery from './Hello.query.graphql';

@customElement('hello-element')
class HelloElement extends ApolloQuery {
  query = HelloQuery;

  render() {
    const greeting = this.data?.greeting ?? 'hello';
    const name = this.data?.name ?? 'world';
    return html`
      <span id="hello">
        ${greeting}, ${name}!
      </span>
    `;
  }
}

Read More

๐Ÿ FAST

These base classes extend from FASTElement, with all it's ergonomics and reactivity.

npm i -S @apollo-elements/fast
import { ApolloQuery } from '@apollo-elements/fast/apollo-query';
import { ApolloMutation } from '@apollo-elements/fast/apollo-mutation';
import { ApolloSubscription } from '@apollo-elements/fast/apollo-subscription';

๐Ÿ‘‡ Click for Example ๐Ÿ‘‡

import { ApolloQuery, customElement, html } from '@apollo-elements/fast';

import HelloQuery from './Hello.query.graphql';

const getGreeting = x => x.data?.greeting ?? 'hello';
const getName = x => x.data?.name ?? 'world';
const name = 'hello-element';
const template = html<HelloElement>`
  <span id="hello">
    ${getGreeting}, ${getName}!
  </span>
`;

@customElement({ name, template }))
class HelloElement extends ApolloQueryMixin(HTMLElement) {
  query = HelloQuery;
}

Read More

๐Ÿ‘ป Haunted

Apollo hooks for web components, with haunted!

npm i -S @apollo-elements/haunted
import { useQuery } from '@apollo-elements/haunted/useQuery';
import { useMutation } from '@apollo-elements/haunted/useMutation';
import { useSubscription } from '@apollo-elements/haunted/useSubscription';

๐Ÿ‘‡ Click for Example ๐Ÿ‘‡

import { useQuery, component, html } from '@apollo-elements/haunted';

import HelloQuery from './Hello.query.graphql';

function HelloElement() {
  const { data } = useQuery(HelloQuery);

  const greeting = data?.greeting ?? 'hello';
  const name = data?.name ?? 'world';

  return html`
    <span id="hello">
      ${greeting}, ${name}!
    </span>
  `;
}

customElements.define('hello-element', component(HelloElement));

Read More

๐Ÿฆ„ Hybrids

Descriptor factories and object spreads you can roll into your hybrids to make it easier to connect to your Apollo cache.

npm i -S @apollo-elements/hybrids
import { client, query, mutation, subscription } from '@apollo-elements/hybrids';
import { ApolloQuery } from '@apollo-elements/hybrids/apollo-query';
import { ApolloMutation } from '@apollo-elements/hybrids/apollo-mutation';
import { ApolloSubscription } from '@apollo-elements/hybrids/apollo-subscription';

๐Ÿ‘‡ Click for Example ๐Ÿ‘‡

import { client, query, define, html } from '@apollo-elements/hybrids';

import HelloQuery from './Hello.query.graphql';

const getGreeting = x => x.data?.greeting ?? 'hello';
const getName = x => x.data?.name ?? 'world';

const HelloElement = {
  client: client(window.__APOLLO_CLIENT__),
  query: query(HelloQuery),
  render: host => html`
    <span id="hello">
      ${getGreeting(host)}, ${getName(host)}!
    </span>
  `,
};

define('hello-element', HelloElement);

Read More

๐Ÿ‘ฉโ€๐Ÿ”ฌ Gluon

These base classes extend from GluonElement, a simplified wc library that uses lit-html for templating while keeping component state and lifecycle concerns 'close to the metal'.

npm i -S @apollo-elements/gluon
import { ApolloQuery } from '@apollo-elements/gluon/apollo-query';
import { ApolloMutation } from '@apollo-elements/gluon/apollo-mutation';
import { ApolloSubscription } from '@apollo-elements/gluon/apollo-subscription';

๐Ÿ‘‡ Click for Example ๐Ÿ‘‡

import { ApolloQuery, html } from '@apollo-elements/gluon';

import HelloQuery from './Hello.query.graphql';

class HelloElement extends ApolloQuery {
  query = HelloQuery;

  #data = null;

  set data(data) { this.#data = data; this.render(); }

  get data() { return this.#data; }

  get template() {
    const greeting = this.data?.greeting ?? 'hello';
    const name = this.data?.name ?? 'world';
    return html`
      <span id="hello">
        ${greeting}, ${name}!
      </span>
    `;
  }
}

customElements.define('hello-element', HelloElement);

Read More

๐Ÿงฌ Polymer

These custom elements fire polymer-style *-changed events when the Apollo cache updates their state. They extend directly from HTMLElement so they're small in size, and their notifying properties make them perfect for use in Polymer templates.

npm i -S @apollo-elements/polymer
import '@apollo-elements/polymer/apollo-query';
import '@apollo-elements/polymer/apollo-mutation';
import '@apollo-elements/polymer/apollo-subscription';

๐Ÿ‘‡ Click for Example ๐Ÿ‘‡

import { PolymerElement, html } from '@polymer/polymer';
import '@apollo-elements/polymer/apollo-query';

class HelloElement extends PolymerElement {
  static get template() {
    return html`
      <apollo-query data="{{data}}">
        <script type="application/graphql">
          query HelloQuery {
            greeting
            name
          }
        </script>
      </query>

      <span id="hello">
        [[getGreeting(data)]], [[getName(data)]]!
      </span>
    `;
  }

  static get properties() {
    return {
      data: {
        type: Object,
        value: () => null,
      },
    };
  }

  getGreeting(data) {
    return data && data.greeting || 'hello';
  }

  getName(data) {
    return data && data.name || 'world';
  }
}

customElements.define('hello-element', HelloElement);

Read More

โ€๐Ÿ™๏ธ Acknowledgements

apollo-elements is a community project maintained by Benny Powers. We proudly use Open Web Components and Modern Web tools. Thanks to Netlify and Heroku for hosting our documentation and demos.

Contact me on Codementor