
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Apollo Elements</title>
    <link>https://apolloelements.dev/</link>
    <description>Build high-performance GraphQL web apps with Apollo Elements</description>
    <generator>Hugo 0.147.7 + Apollo Elements</generator>
    <language>en-us</language>
    
    
    
    <atom:link href="https://apolloelements.dev/index.xml" rel="self" type="application/rss+xml" /><item>
      <title>apollo-client element</title>
      <link>https://apolloelements.dev/guides/usage/apollo-client/html/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/guides/usage/apollo-client/html/</guid>
      <description>&lt;p&gt;When building your GraphQL app using Apollo Elements HTML components, use &lt;code&gt;&amp;lt;apollo-client&amp;gt;&lt;/code&gt; to set up the client instance. You can mix-and-match, using the same client element with &lt;code&gt;&amp;lt;apollo-query&amp;gt;&lt;/code&gt; or mutation elements, or with your own custom query elements.&lt;/p&gt;
&lt;inline-notification type=&#34;tip&#34;&gt;
&lt;p&gt;This page is a HOW-TO guide. For detailed docs on &lt;code&gt;&amp;lt;apollo-client&amp;gt;&lt;/code&gt; element&amp;rsquo;s API, see the &lt;a href=&#34;https://apolloelements.dev/api/components/apollo-query/&#34;&gt;API docs&lt;/a&gt;&lt;/p&gt;
&lt;/inline-notification&gt;
&lt;p&gt;The element&amp;rsquo;s main job is to manage it&amp;rsquo;s children&amp;rsquo;s &lt;code&gt;ApolloClient&lt;/code&gt; instance. Every Apollo Element that&amp;rsquo;s a child of an &lt;code&gt;&amp;lt;apollo-client&amp;gt;&lt;/code&gt; element will share it&amp;rsquo;s client instance, even across deeply nested (open) shadow roots.&lt;/p&gt;</description>
      
      <content:encoded><![CDATA[<p>When building your GraphQL app using Apollo Elements HTML components, use <code>&lt;apollo-client&gt;</code> to set up the client instance. You can mix-and-match, using the same client element with <code>&lt;apollo-query&gt;</code> or mutation elements, or with your own custom query elements.</p>
<inline-notification type="tip">
<p>This page is a HOW-TO guide. For detailed docs on <code>&lt;apollo-client&gt;</code> element&rsquo;s API, see the <a href="/api/components/apollo-query/">API docs</a></p>
</inline-notification>
<p>The element&rsquo;s main job is to manage it&rsquo;s children&rsquo;s <code>ApolloClient</code> instance. Every Apollo Element that&rsquo;s a child of an <code>&lt;apollo-client&gt;</code> element will share it&rsquo;s client instance, even across deeply nested (open) shadow roots.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">apollo-client</span> <span class="na">id</span><span class="o">=</span><span class="s">&#34;client-a&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="p">&lt;</span><span class="nt">query-a</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">    #shadow-root
</span></span><span class="line"><span class="cl">      <span class="p">&lt;</span><span class="nt">query-b</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">        #shadow-root
</span></span><span class="line"><span class="cl">          <span class="p">&lt;</span><span class="nt">mutation-a</span><span class="p">&gt;&lt;/</span><span class="nt">mutation-a</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">          <span class="p">&lt;</span><span class="nt">apollo-client</span> <span class="na">id</span><span class="o">=</span><span class="s">&#34;client-b&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">            <span class="p">&lt;</span><span class="nt">query-c</span><span class="p">&gt;&lt;</span><span class="nt">query-c</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">          <span class="p">&lt;/</span><span class="nt">apollo-client</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="p">&lt;/</span><span class="nt">query-b</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="p">&lt;/</span><span class="nt">query-a</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="p">&lt;/</span><span class="nt">apollo-client</span><span class="p">&gt;</span>
</span></span></code></pre></div><p>In the above example, queries A and B, and mutation A all share a client instance, but query C has its own client instance.</p>
<h2 id="configuring">Configuring</h2>
<p>There are two ways to use <code>&lt;apollo-client&gt;</code>, automatic and manual. Automatic mode creates a basic Apollo client instance, while manual mode lets you customize the client with links and other options. If you&rsquo;re not sure which mode to use, start with automatic mode - you can always switch to manual mode later on.</p>
<h2 id="automatic-mode">Automatic Mode</h2>
<p>When setting the <code>uri</code> attribute on the <code>&lt;apollo-client&gt;</code> element, it creates a basic Apollo client instance directed at the given GraphQL server URI. At that point, any existing Apollo Element children receive the client instance on their <code>client</code> DOM property.</p>
<p>In the following example, an <code>&lt;apollo-query&gt;</code> element queries for <code>user</code> via an Apollo client pointed at a graphql server running at <code>/graphql</code> (i.e. on the same origin as the page). Later, JavaScript imports a <a href="/guides/usage/queries/html/">custom Apollo query element</a> called <code>&lt;custom-query&gt;</code>, then appends it to the existing Apollo client element. Both query elements have the same <code>client</code> reference, and both will automatically query for data.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">apollo-client</span> <span class="na">uri</span><span class="o">=</span><span class="s">&#34;/graphql&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="p">&lt;</span><span class="nt">apollo-query</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;</span><span class="nt">script</span> <span class="na">type</span><span class="o">=</span><span class="s">&#34;application/graphql&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="nx">query</span> <span class="nx">User</span><span class="p">(</span><span class="nx">$userId</span><span class="o">:</span> <span class="nx">ID</span><span class="o">!</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nx">user</span><span class="p">(</span><span class="nx">userId</span><span class="o">:</span> <span class="nx">$userId</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">          <span class="nx">name</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">      <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;/</span><span class="nt">script</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;</span><span class="nt">template</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="p">&lt;</span><span class="nt">style</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="p">.</span><span class="nc">loading</span> <span class="p">{</span> <span class="k">opacity</span><span class="p">:</span> <span class="mi">0</span><span class="p">;</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl">      <span class="p">&lt;/</span><span class="nt">style</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="p">&lt;</span><span class="nt">p</span> <span class="na">class</span><span class="o">=</span><span class="s">&#34;{{ loading ? &#39;loading&#39; : &#39;&#39; }}&#34;</span><span class="p">&gt;</span>Hi, {{ data.user.name }}<span class="p">&lt;/</span><span class="nt">p</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;/</span><span class="nt">template</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="p">&lt;/</span><span class="nt">apollo-query</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="p">&lt;/</span><span class="nt">apollo-client</span><span class="p">&gt;</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl"><span class="kr">import</span> <span class="s1">&#39;../components/custom-query&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="nb">document</span>
</span></span><span class="line"><span class="cl">  <span class="p">.</span><span class="nx">querySelector</span><span class="p">(</span><span class="s1">&#39;apollo-client&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="p">.</span><span class="nx">appendChild</span><span class="p">(</span><span class="nb">document</span>
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="nx">createElement</span><span class="p">(</span><span class="s1">&#39;custom-query&#39;</span><span class="p">))</span>
</span></span></code></pre></div><h3 id="customizing-automatic-mode-clients">Customizing Automatic Mode Clients</h3>
<p><code>&lt;apollo-client&gt;</code> uses the <code>createApolloClient</code> helper from <code>@apollo-elements/core/lib/create-apollo-client</code> under the hood, and it comes with some options for customizing the automatic-mode client. You can set the <code>validate-variables</code> attribute to try to prevent fetching operations that don&rsquo;t have all their required top-level variables.</p>
<inline-notification type="warning">
<p><code>validate-variables</code> isn&rsquo;t foolproof. If your operation uses input variables (i.e. objects as variables), the client doesn&rsquo;t introspect the schema to see whether or not the required properties of the required inputs are there.</p>
<p>For example, if an <code>UpdateUser</code> mutation requires an <code>$input</code> variable of type <code>UserInput!</code>, and <code>UserInput</code> has a non-nullable property <code>userId</code>, the client will still attempt to fetch a mutation with variables <code>{ input: { name: 'username' } }</code></p>
</inline-notification>
<p>You can also set a <code>typePolicies</code> DOM property on <code>&lt;apollo-client&gt;</code> using JavaScript in order to apply some default <a href="https://www.apollographql.com/docs/react/caching/cache-configuration/#typepolicy-fields">type policies</a>.</p>
<h2 id="manual-mode">Manual Mode</h2>
<p>If you need more control over the client, for example to configure the links, use manual mode leaving out the <code>uri</code> attribute or DOM property on <code>&lt;apollo-client&gt;</code>. Instead, create your own <code>ApolloClient</code> instance, and assign it to the element&rsquo;s <code>client</code> DOM property.</p>
<p>To construct an instance, import from <code>@apollo/client/core</code> (<em>note</em>: <code>@apollo/client</code> exports a bunch of react code, so if you leave off the <code>/core</code>, you might experience TypeScript compilation errors, or larger bundle sizes)</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">ApolloClient</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nx">ApolloLink</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nx">HttpLink</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nx">InMemoryCache</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span> <span class="nx">from</span> <span class="s1">&#39;@apollo/client/core&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">CustomLink</span> <span class="p">}</span> <span class="nx">from</span> <span class="s1">&#39;./my-custom-link&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">cache</span> <span class="o">=</span>
</span></span><span class="line"><span class="cl">  <span class="k">new</span> <span class="nx">InMemoryCache</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// Configure with a URL to your GraphQL endpoint
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kr">const</span> <span class="nx">link</span> <span class="o">=</span> <span class="nx">ApolloLink</span><span class="p">.</span><span class="nx">from</span><span class="p">([</span>
</span></span><span class="line"><span class="cl">  <span class="k">new</span> <span class="nx">CustomLink</span><span class="p">(),</span>
</span></span><span class="line"><span class="cl">  <span class="k">new</span> <span class="nx">HttpLink</span><span class="p">({</span> <span class="nx">uri</span><span class="o">:</span> <span class="s1">&#39;/graphql&#39;</span> <span class="p">}),</span>
</span></span><span class="line"><span class="cl"><span class="p">])</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">document</span><span class="p">.</span><span class="nx">querySelector</span><span class="p">(</span><span class="s1">&#39;apollo-client&#39;</span><span class="p">).</span><span class="nx">client</span> <span class="o">=</span>
</span></span><span class="line"><span class="cl">  <span class="k">new</span> <span class="nx">ApolloClient</span><span class="p">({</span> <span class="nx">cache</span><span class="p">,</span> <span class="nx">link</span> <span class="p">});</span>
</span></span></code></pre></div><p>Once set, the element will ensure that all it&rsquo;s children, even across open shadow roots, receive the instance on their <code>client</code> property.</p>
<h2 id="next-steps">Next Steps</h2>
<ul>
<li>Learn how to write <a href="../../queries/">query components</a></li>
</ul>
]]></content:encoded>
    </item><item>
      <title>ApolloController</title>
      <link>https://apolloelements.dev/api/core/controllers/controller/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/api/core/controllers/controller/</guid>
      <description>Core Controllers for Apollo Elements</description>
      
      <content:encoded><![CDATA[<!-- ----------------------------------------------------------------------------------------
     Welcome! This file includes automatically generated API documentation.
     To edit the docs that appear within, find the original source file under `packages/*`,
     corresponding to the package name and module in this YAML front-matter block.
     Thank you for your interest in Apollo Elements 😁
------------------------------------------------------------------------------------------ -->
<p><code>ApolloController</code> is the abstract base class at the heart of Apollo Elements. You should not import <code>ApolloController</code> directly, instead use the subclasses: <a href="/api/core/controllers/query/"><code>ApolloQueryController</code></a>, <a href="/api/core/controllers/mutation/"><code>ApolloMutationController</code></a>, and <a href="/api/core/controllers/subscription/"><code>ApolloSubscriptionController</code></a>.</p>
]]></content:encoded>
    </item><item>
      <title>Component</title>
      <link>https://apolloelements.dev/api/create/component/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/api/create/component/</guid>
      <description>&lt;p&gt;Generate an Apollo Element&lt;/p&gt;
&lt;h2 id=&#34;example&#34;&gt;Example&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;npm init @apollo-elements -- &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;  component &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;    --type mutation &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;    --name x-user-profile &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;    --operation-name UpdateProfile
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    --variables &lt;span class=&#34;s1&#34;&gt;&amp;#39;$input: UpdateProfileInput!&amp;#39;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;    --fields &lt;span class=&#34;s1&#34;&gt;&amp;#39;updateProfile(input: $input) { id }&amp;#39;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;    --subdir user &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;    --schema-path &lt;span class=&#34;s1&#34;&gt;&amp;#39;#schema&amp;#39;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;    --shared-css-path &lt;span class=&#34;s1&#34;&gt;&amp;#39;#components/shared.css&amp;#39;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;    --no-codegen
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    --overwrite
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;options&#34;&gt;Options&lt;/h2&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Flag&lt;/th&gt;
          &lt;th&gt;Description&lt;/th&gt;
          &lt;th&gt;Type&lt;/th&gt;
          &lt;th&gt;Default&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;--help&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;Show help&lt;/td&gt;
          &lt;td&gt;boolean&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;--version&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;Show version number&lt;/td&gt;
          &lt;td&gt;boolean&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;--pkg-manager&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;Preferred package manager&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;npm&lt;/code&gt;|&lt;code&gt;yarn&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;npm&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;--type&lt;/code&gt;, &lt;code&gt;-t&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;Element type&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;query&lt;/code&gt;|&lt;code&gt;mutation&lt;/code&gt;| &lt;code&gt;subscription&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;query&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;--name&lt;/code&gt;, &lt;code&gt;-n&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;Custom element tag name&lt;/td&gt;
          &lt;td&gt;string&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;--subdir&lt;/code&gt;, &lt;code&gt;-d&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;Optional subdir under src/components&lt;/td&gt;
          &lt;td&gt;string&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;--overwrite&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;Overwrite existing files&lt;/td&gt;
          &lt;td&gt;boolean&lt;/td&gt;
          &lt;td&gt;false&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;--codegen&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;Run codegen after scaffolding files&lt;/td&gt;
          &lt;td&gt;boolean&lt;/td&gt;
          &lt;td&gt;true&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;--schema-path&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;Optional custom path to schema types file&lt;/td&gt;
          &lt;td&gt;string&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;--shared-css-path&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;Optional custom path to shared component styles file&lt;/td&gt;
          &lt;td&gt;string&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;--variables&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;Optional custom variables e.g. &lt;code&gt;input: $UpdateUserInput&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;string&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;--fields&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;Optional custom fields e.g. &lt;code&gt;id name picture { alt url }&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;string&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;</description>
      
      <content:encoded><![CDATA[<p>Generate an Apollo Element</p>
<h2 id="example">Example</h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">npm init @apollo-elements -- <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>  component <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>    --type mutation <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>    --name x-user-profile <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>    --operation-name UpdateProfile
</span></span><span class="line"><span class="cl">    --variables <span class="s1">&#39;$input: UpdateProfileInput!&#39;</span> <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>    --fields <span class="s1">&#39;updateProfile(input: $input) { id }&#39;</span> <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>    --subdir user <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>    --schema-path <span class="s1">&#39;#schema&#39;</span> <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>    --shared-css-path <span class="s1">&#39;#components/shared.css&#39;</span> <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>    --no-codegen
</span></span><span class="line"><span class="cl">    --overwrite
</span></span></code></pre></div><h2 id="options">Options</h2>
<table>
  <thead>
      <tr>
          <th>Flag</th>
          <th>Description</th>
          <th>Type</th>
          <th>Default</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>--help</code></td>
          <td>Show help</td>
          <td>boolean</td>
          <td></td>
      </tr>
      <tr>
          <td><code>--version</code></td>
          <td>Show version number</td>
          <td>boolean</td>
          <td></td>
      </tr>
      <tr>
          <td><code>--pkg-manager</code></td>
          <td>Preferred package manager</td>
          <td><code>npm</code>|<code>yarn</code></td>
          <td><code>npm</code></td>
      </tr>
      <tr>
          <td><code>--type</code>, <code>-t</code></td>
          <td>Element type</td>
          <td><code>query</code>|<code>mutation</code>| <code>subscription</code></td>
          <td><code>query</code></td>
      </tr>
      <tr>
          <td><code>--name</code>, <code>-n</code></td>
          <td>Custom element tag name</td>
          <td>string</td>
          <td></td>
      </tr>
      <tr>
          <td><code>--subdir</code>, <code>-d</code></td>
          <td>Optional subdir under src/components</td>
          <td>string</td>
          <td></td>
      </tr>
      <tr>
          <td><code>--overwrite</code></td>
          <td>Overwrite existing files</td>
          <td>boolean</td>
          <td>false</td>
      </tr>
      <tr>
          <td><code>--codegen</code></td>
          <td>Run codegen after scaffolding files</td>
          <td>boolean</td>
          <td>true</td>
      </tr>
      <tr>
          <td><code>--schema-path</code></td>
          <td>Optional custom path to schema types file</td>
          <td>string</td>
          <td></td>
      </tr>
      <tr>
          <td><code>--shared-css-path</code></td>
          <td>Optional custom path to shared component styles file</td>
          <td>string</td>
          <td></td>
      </tr>
      <tr>
          <td><code>--variables</code></td>
          <td>Optional custom variables e.g. <code>input: $UpdateUserInput</code></td>
          <td>string</td>
          <td></td>
      </tr>
      <tr>
          <td><code>--fields</code></td>
          <td>Optional custom fields e.g. <code>id name picture { alt url }</code></td>
          <td>string</td>
          <td></td>
      </tr>
  </tbody>
</table>
]]></content:encoded>
    </item><item>
      <title>Query Factory</title>
      <link>https://apolloelements.dev/api/libraries/hybrids/query/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/api/libraries/hybrids/query/</guid>
      <description>&lt;!-- ----------------------------------------------------------------------------------------
     Welcome! This file includes automatically generated API documentation.
     To edit the docs that appear within, find the original source file under `packages/*`,
     corresponding to the package name and module in this YAML front-matter block.
     Thank you for your interest in Apollo Elements 😁
------------------------------------------------------------------------------------------ --&gt;
&lt;docs-playground id=&#34;hybrids-query&#34;&gt;
  &lt;template shadowrootmode=&#34;open&#34;&gt;
    &lt;style&gt;
      :host {
        display: block;
        box-sizing: border-box;
        position: relative;
        width: 100%;
        height: auto;
      }

      playground-ide {
        display: none;
        border: 0;
        overflow: hidden;

        --playground-code-font-family: monospace;
        --playground-code-font-size: 14px;
        --playground-border: none;
      }

      #snippet,
      playground-ide {
        width: 100%;
        height: 100%;
        border-radius: var(--playground-snippet-border-radius, 6px);
      }

      #snippet {
        display: block;
        box-sizing: border-box;
      }

      #snippet,
      button {
        border: 1px solid var(--playground-snippet-border-color, transparent);
        transition: border-color 0.2s ease-in-out;
        will-change: border-color;
      }

      :host([show]) playground-ide {
        display: flex;
        width: var(--playground-ide-width, 100%);
        height: var(--playground-ide-height, 600px);
      }

      button {
        background: var(--playground-snippet-button-background);
        border-end-end-radius: 6px;
        border-start-start-radius: 6px;
        color: inherit;
        cursor: pointer;
        display: block;
        font-size: 16px;
        outline: none;
        padding: 9px 16px;
        position: absolute;
        bottom: 0;
        right: -2px;
        transition:
          border-color 0.2s ease-in-out,
          background 0.1s ease,
          color 0.1s ease;
      }

      button:focus,
      button:hover {
        color: var(--playground-snippet-button-focus-color, var(--code-button-focus-color));
        background: var(--playground-snippet-button-focus-background, var(--code-button-focus-background));
        border-bottom-color: var(--playground-snippet-button-focus-background, var(--code-button-focus-background)) !important;
        border-right-color: var(--playground-snippet-button-focus-background, var(--code-button-focus-background)) !important;
      }

      :host([show]) #snippet,
      :host([show]) button {
        display: none;
      }

      :host(:not([show]):focus-within) #snippet,
      :host(:not([show]):hover) #snippet {
        border-color: var(--playground-snippet-focus-border-color, black);
      }

      :host(:not([show]):focus-within) button,
      :host(:not([show]):hover) button {
        border-top-color: var(--playground-snippet-focus-border-color, black);
        border-left-color: var(--playground-snippet-focus-border-color, black);
        border-bottom-color: var(--playground-snippet-outer-background-color, var(--page-background));
        border-right-color: var(--playground-snippet-outer-background-color, var(--page-background));
      }

      #snippet ::slotted(pre) {
        margin-bottom: 0 !important;
      }

      :host([loading]) #edit,
      #loading {
        display: none;
      }

      :host([loading]) #loading {
        display: inline-block;
      }
    &lt;/style&gt;

    &lt;div id=&#34;snippet&#34;&gt;&lt;slot&gt;&lt;/slot&gt;&lt;/div&gt;

    &lt;playground-ide part=&#34;playground-ide&#34; exportparts=&#34;lhs,rhs&#34;&gt;&lt;/playground-ide&gt;

    &lt;button part=&#34;button&#34;&gt;
      &lt;span id=&#34;edit&#34;&gt;▶️ Edit Live&lt;/span&gt;

      &lt;slot name=&#34;loader&#34;&gt;
        
        &lt;svg id=&#34;loading&#34; width=&#34;90&#34; height=&#34;20&#34; viewBox=&#34;0 0 120 30&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34; fill=&#34;var(--primary-text-color)&#34;&gt;
            &lt;circle cx=&#34;15&#34; cy=&#34;15&#34; r=&#34;15&#34;&gt;
                &lt;animate attributeName=&#34;r&#34; from=&#34;15&#34; to=&#34;15&#34;
                         begin=&#34;0s&#34; dur=&#34;0.8s&#34;
                         values=&#34;15;9;15&#34; calcMode=&#34;linear&#34;
                         repeatCount=&#34;indefinite&#34; /&gt;
                &lt;animate attributeName=&#34;fill-opacity&#34; from=&#34;1&#34; to=&#34;1&#34;
                         begin=&#34;0s&#34; dur=&#34;0.8s&#34;
                         values=&#34;1;.5;1&#34; calcMode=&#34;linear&#34;
                         repeatCount=&#34;indefinite&#34; /&gt;
            &lt;/circle&gt;
            &lt;circle cx=&#34;60&#34; cy=&#34;15&#34; r=&#34;9&#34; fill-opacity=&#34;0.3&#34;&gt;
                &lt;animate attributeName=&#34;r&#34; from=&#34;9&#34; to=&#34;9&#34;
                         begin=&#34;0s&#34; dur=&#34;0.8s&#34;
                         values=&#34;9;15;9&#34; calcMode=&#34;linear&#34;
                         repeatCount=&#34;indefinite&#34; /&gt;
                &lt;animate attributeName=&#34;fill-opacity&#34; from=&#34;0.5&#34; to=&#34;0.5&#34;
                         begin=&#34;0s&#34; dur=&#34;0.8s&#34;
                         values=&#34;.5;1;.5&#34; calcMode=&#34;linear&#34;
                         repeatCount=&#34;indefinite&#34; /&gt;
            &lt;/circle&gt;
            &lt;circle cx=&#34;105&#34; cy=&#34;15&#34; r=&#34;15&#34;&gt;
                &lt;animate attributeName=&#34;r&#34; from=&#34;15&#34; to=&#34;15&#34;
                         begin=&#34;0s&#34; dur=&#34;0.8s&#34;
                         values=&#34;15;9;15&#34; calcMode=&#34;linear&#34;
                         repeatCount=&#34;indefinite&#34; /&gt;
                &lt;animate attributeName=&#34;fill-opacity&#34; from=&#34;1&#34; to=&#34;1&#34;
                         begin=&#34;0s&#34; dur=&#34;0.8s&#34;
                         values=&#34;1;.5;1&#34; calcMode=&#34;linear&#34;
                         repeatCount=&#34;indefinite&#34; /&gt;
            &lt;/circle&gt;
        &lt;/svg&gt;
      &lt;/slot&gt;
    &lt;/button&gt;
  &lt;/template&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ts&#34; data-lang=&#34;ts&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;mutation&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;query&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;define&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;html&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;kr&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;@apollo-elements/hybrids&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;UsersQuery&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;kr&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;./Users.query.graphql.js&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;AddUserMutation&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;kr&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;./AddUser.mutation.graphql.js&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;RemoveUserMutation&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;kr&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;./RemoveUser.mutation.graphql.js&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;refetchQueries&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[{&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;query&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;UsersQuery&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;onRemoveUser&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;host&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;e&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;e&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;preventDefault&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;id&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;e&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;target&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;closest&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;[data-id]&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;dataset&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;host&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;removeUser&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;mutate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;({&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;variables&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;id&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;onSubmitForm&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;host&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;e&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;e&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;preventDefault&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;host&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;addUser&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;mutate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;({&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nx&#34;&gt;variables&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nx&#34;&gt;name&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;host.shadowRoot.getElementById&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;name&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;define&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;users-list&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;users&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;query&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;UsersQuery&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;removeUser&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;mutation&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;RemoveUserMutation&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;refetchQueries&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;awaitRefetchQueries&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;true&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;addUser&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;mutation&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;AddUserMutation&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;refetchQueries&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;awaitRefetchQueries&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;true&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;render&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;({&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;users&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;addUser&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;removeUser&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;})&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;html&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;`
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;    &amp;lt;link rel=&amp;#34;stylesheet&amp;#34; href=&amp;#34;users-list.css&amp;#34;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;    &amp;lt;ol&amp;gt;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;users&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;?&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;users&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;??&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[]).&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;map&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;html&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;`
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;      &amp;lt;li data-id=&amp;#34;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;&amp;#34;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;        &amp;lt;button aria-label=&amp;#34;Remove&amp;#34; disabled=&amp;#34;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;removeUser&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;loading&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;&amp;#34; onclick=&amp;#34;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;onRemoveUser&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;&amp;#34;&amp;gt;x&amp;lt;/button&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;      &amp;lt;/li&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;    `&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;&amp;lt;/ol&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;    &amp;lt;form onsubmit=&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;onSubmitForm&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;      &amp;lt;label&amp;gt;Name &amp;lt;input id=&amp;#34;name&amp;#34; disabled=&amp;#34;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;addUser&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;loading&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;&amp;#34;&amp;gt;&amp;lt;/label&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;      &amp;lt;button disabled=&amp;#34;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;addUser&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;loading&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;removeUser&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;loading&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;&amp;#34;&amp;gt;Submit&amp;lt;/button&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;    &amp;lt;/form&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;  `&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;template data-playground-id=&#34;hybrids-query&#34;
            data-filename=&#34;users-list.ts&#34;&gt;import { mutation, query, define, html } from &amp;#39;@apollo-elements/hybrids&amp;#39;;
  
  import { UsersQuery } from &amp;#39;./Users.query.graphql.js&amp;#39;;
  import { AddUserMutation } from &amp;#39;./AddUser.mutation.graphql.js&amp;#39;;
  import { RemoveUserMutation } from &amp;#39;./RemoveUser.mutation.graphql.js&amp;#39;;
  
  const refetchQueries = [{ query: UsersQuery }];
  
  const onRemoveUser = (host, e) =&amp;gt; {
    e.preventDefault();
    const { id } = e.target.closest(&amp;#39;[data-id]&amp;#39;).dataset;
    host.removeUser.mutate({ variables: { id }})
  }
  
  const onSubmitForm = (host, e) =&amp;gt; {
    e.preventDefault();
    host.addUser.mutate({
      variables: {
        name: host.shadowRoot.getElementById(&amp;#39;name&amp;#39;).value,
      },
    });
  }
  
  define(&amp;#39;users-list&amp;#39;, {
    users: query(UsersQuery),
    removeUser: mutation(RemoveUserMutation, { refetchQueries, awaitRefetchQueries: true }),
    addUser: mutation(AddUserMutation, { refetchQueries, awaitRefetchQueries: true }),
    render: ({ users, addUser, removeUser }) =&amp;gt; html`
      &amp;lt;link rel=&amp;#34;stylesheet&amp;#34; href=&amp;#34;users-list.css&amp;#34;&amp;gt;
      &amp;lt;ol&amp;gt;${(users.data?.users??[]).map(x =&amp;gt; html`
        &amp;lt;li data-id=&amp;#34;${x.id}&amp;#34;&amp;gt;
          ${x.name}
          &amp;lt;button aria-label=&amp;#34;Remove&amp;#34; disabled=&amp;#34;${removeUser.loading}&amp;#34; onclick=&amp;#34;${onRemoveUser}&amp;#34;&amp;gt;x&amp;lt;/button&amp;gt;
        &amp;lt;/li&amp;gt;
      `)}&amp;lt;/ol&amp;gt;
      &amp;lt;form onsubmit=${onSubmitForm}&amp;gt;
        &amp;lt;label&amp;gt;Name &amp;lt;input id=&amp;#34;name&amp;#34; disabled=&amp;#34;${addUser.loading}&amp;#34;&amp;gt;&amp;lt;/label&amp;gt;
        &amp;lt;button disabled=&amp;#34;${addUser.loading || removeUser.loading}&amp;#34;&amp;gt;Submit&amp;lt;/button&amp;gt;
      &amp;lt;/form&amp;gt;
    `,
  });&lt;/template&gt;

  &lt;template data-playground-id=&#34;hybrids-query&#34;
            data-filename=&#34;users-list.css&#34;&gt;:host {
    display: block;
    counter-reset: item;
  }
  
  form {
    display: grid;
    grid-template-columns: auto min-content;
  }
  
  label {
    display: contents;
  }
  
  ol {
    padding: 0;
  }
  
  li {
    display: flex;
    justify-content: space-between;
    counter-increment: item;
  }
  
  li::before {
    content: counter(item);
    margin-inline-end: 4px;
  }
  
  li button {
    margin-inline-start: auto;
  }&lt;/template&gt;


  &lt;template data-playground-id=&#34;hybrids-query&#34;
            data-filename=&#34;Users.query.graphql.ts&#34;&gt;import type { User } from &amp;#39;./client&amp;#39;;
  import type { TypedDocumentNode } from &amp;#39;@apollo/client/core&amp;#39;;
  import { gql } from &amp;#39;@apollo/client/core&amp;#39;;
  export const UsersQuery: TypedDocumentNode&amp;lt;{ users: User[] }&amp;gt; =  gql`
    query UsersQuery {
      users {
        id
        name
      }
    }
  `;&lt;/template&gt;


  &lt;template data-playground-id=&#34;hybrids-query&#34;
            data-filename=&#34;index.html&#34;&gt;&amp;lt;script type=&amp;#34;module&amp;#34; src=&amp;#34;client.js&amp;#34;&amp;gt;&amp;lt;/script&amp;gt;
  &amp;lt;script type=&amp;#34;module&amp;#34; src=&amp;#34;users-list.js&amp;#34;&amp;gt;&amp;lt;/script&amp;gt;
  &amp;lt;users-list&amp;gt;&amp;lt;/users-list&amp;gt;&lt;/template&gt;


  &lt;template data-playground-id=&#34;hybrids-query&#34;
            data-filename=&#34;client.ts&#34;&gt;import type { InMemoryCacheConfig, NormalizedCacheObject } from &amp;#39;@apollo/client/core&amp;#39;;
  
  import { SchemaLink } from &amp;#39;@apollo/client/link/schema&amp;#39;;
  import { makeExecutableSchema } from &amp;#39;@graphql-tools/schema&amp;#39;;
  import { addMocksToSchema } from &amp;#39;@graphql-tools/mock&amp;#39;;
  
  import { ApolloClient, InMemoryCache, HttpLink } from &amp;#39;@apollo/client/core&amp;#39;;
  
  export interface User {
    id: string;
    name: string;
    status?: &amp;#39;DELETED&amp;#39;;
  };
  
  const typeDefs = `
    type User {
      name: String
      id: ID
    }
  
    type Query {
      users: [User]
    }
  
    type Mutation {
      addUser(name: String): User
      removeUser(id: ID): User
    }
  `;
  
  const USERS = [
    { id: 1, name: &amp;#39;Neil&amp;#39; }
  ];
  
  const randomDelay = () =&amp;gt;  new Promise(r =&amp;gt; setTimeout(r, Math.random() * 500));
  
  export const client = new ApolloClient({
    cache: new InMemoryCache(),
    link: new SchemaLink({
      schema: makeExecutableSchema({
        typeDefs,
        resolvers: {
          Query: {
            users() {
              return USERS.filter(x =&amp;gt; x.status !== &amp;#39;DELETED&amp;#39;);
            }
          },
          Mutation: {
            async addUser(_, { name }) {
              const user = { name, id: Math.max(...USERS.map(x =&amp;gt; x.id)) &amp;#43; 1 };
              USERS.push(user);
              await randomDelay()
              return user;
            },
            async removeUser(_, { id }) {
              const user = USERS.find(x =&amp;gt; x.id == parseInt(id));
              user.status = &amp;#39;DELETED&amp;#39;;
              await randomDelay();
              return user;
            }
          }
        }
      }),
    }),
  });
  
  window.__APOLLO_CLIENT__ = client;&lt;/template&gt;

&lt;/docs-playground&gt;</description>
      
      <content:encoded><![CDATA[<!-- ----------------------------------------------------------------------------------------
     Welcome! This file includes automatically generated API documentation.
     To edit the docs that appear within, find the original source file under `packages/*`,
     corresponding to the package name and module in this YAML front-matter block.
     Thank you for your interest in Apollo Elements 😁
------------------------------------------------------------------------------------------ -->
<docs-playground id="hybrids-query">
  <template shadowrootmode="open">
    <style>
      :host {
        display: block;
        box-sizing: border-box;
        position: relative;
        width: 100%;
        height: auto;
      }

      playground-ide {
        display: none;
        border: 0;
        overflow: hidden;

        --playground-code-font-family: monospace;
        --playground-code-font-size: 14px;
        --playground-border: none;
      }

      #snippet,
      playground-ide {
        width: 100%;
        height: 100%;
        border-radius: var(--playground-snippet-border-radius, 6px);
      }

      #snippet {
        display: block;
        box-sizing: border-box;
      }

      #snippet,
      button {
        border: 1px solid var(--playground-snippet-border-color, transparent);
        transition: border-color 0.2s ease-in-out;
        will-change: border-color;
      }

      :host([show]) playground-ide {
        display: flex;
        width: var(--playground-ide-width, 100%);
        height: var(--playground-ide-height, 600px);
      }

      button {
        background: var(--playground-snippet-button-background);
        border-end-end-radius: 6px;
        border-start-start-radius: 6px;
        color: inherit;
        cursor: pointer;
        display: block;
        font-size: 16px;
        outline: none;
        padding: 9px 16px;
        position: absolute;
        bottom: 0;
        right: -2px;
        transition:
          border-color 0.2s ease-in-out,
          background 0.1s ease,
          color 0.1s ease;
      }

      button:focus,
      button:hover {
        color: var(--playground-snippet-button-focus-color, var(--code-button-focus-color));
        background: var(--playground-snippet-button-focus-background, var(--code-button-focus-background));
        border-bottom-color: var(--playground-snippet-button-focus-background, var(--code-button-focus-background)) !important;
        border-right-color: var(--playground-snippet-button-focus-background, var(--code-button-focus-background)) !important;
      }

      :host([show]) #snippet,
      :host([show]) button {
        display: none;
      }

      :host(:not([show]):focus-within) #snippet,
      :host(:not([show]):hover) #snippet {
        border-color: var(--playground-snippet-focus-border-color, black);
      }

      :host(:not([show]):focus-within) button,
      :host(:not([show]):hover) button {
        border-top-color: var(--playground-snippet-focus-border-color, black);
        border-left-color: var(--playground-snippet-focus-border-color, black);
        border-bottom-color: var(--playground-snippet-outer-background-color, var(--page-background));
        border-right-color: var(--playground-snippet-outer-background-color, var(--page-background));
      }

      #snippet ::slotted(pre) {
        margin-bottom: 0 !important;
      }

      :host([loading]) #edit,
      #loading {
        display: none;
      }

      :host([loading]) #loading {
        display: inline-block;
      }
    </style>

    <div id="snippet"><slot></slot></div>

    <playground-ide part="playground-ide" exportparts="lhs,rhs"></playground-ide>

    <button part="button">
      <span id="edit">▶️ Edit Live</span>

      <slot name="loader">
        
        <svg id="loading" width="90" height="20" viewBox="0 0 120 30" xmlns="http://www.w3.org/2000/svg" fill="var(--primary-text-color)">
            <circle cx="15" cy="15" r="15">
                <animate attributeName="r" from="15" to="15"
                         begin="0s" dur="0.8s"
                         values="15;9;15" calcMode="linear"
                         repeatCount="indefinite" />
                <animate attributeName="fill-opacity" from="1" to="1"
                         begin="0s" dur="0.8s"
                         values="1;.5;1" calcMode="linear"
                         repeatCount="indefinite" />
            </circle>
            <circle cx="60" cy="15" r="9" fill-opacity="0.3">
                <animate attributeName="r" from="9" to="9"
                         begin="0s" dur="0.8s"
                         values="9;15;9" calcMode="linear"
                         repeatCount="indefinite" />
                <animate attributeName="fill-opacity" from="0.5" to="0.5"
                         begin="0s" dur="0.8s"
                         values=".5;1;.5" calcMode="linear"
                         repeatCount="indefinite" />
            </circle>
            <circle cx="105" cy="15" r="15">
                <animate attributeName="r" from="15" to="15"
                         begin="0s" dur="0.8s"
                         values="15;9;15" calcMode="linear"
                         repeatCount="indefinite" />
                <animate attributeName="fill-opacity" from="1" to="1"
                         begin="0s" dur="0.8s"
                         values="1;.5;1" calcMode="linear"
                         repeatCount="indefinite" />
            </circle>
        </svg>
      </slot>
    </button>
  </template><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ts" data-lang="ts"><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">mutation</span><span class="p">,</span> <span class="nx">query</span><span class="p">,</span> <span class="nx">define</span><span class="p">,</span> <span class="nx">html</span> <span class="p">}</span> <span class="kr">from</span> <span class="s1">&#39;@apollo-elements/hybrids&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">UsersQuery</span> <span class="p">}</span> <span class="kr">from</span> <span class="s1">&#39;./Users.query.graphql.js&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">AddUserMutation</span> <span class="p">}</span> <span class="kr">from</span> <span class="s1">&#39;./AddUser.mutation.graphql.js&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">RemoveUserMutation</span> <span class="p">}</span> <span class="kr">from</span> <span class="s1">&#39;./RemoveUser.mutation.graphql.js&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">refetchQueries</span> <span class="o">=</span> <span class="p">[{</span> <span class="nx">query</span>: <span class="kt">UsersQuery</span> <span class="p">}];</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">onRemoveUser</span> <span class="o">=</span> <span class="p">(</span><span class="nx">host</span><span class="p">,</span> <span class="nx">e</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">e</span><span class="p">.</span><span class="nx">preventDefault</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">  <span class="kr">const</span> <span class="p">{</span> <span class="nx">id</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">e</span><span class="p">.</span><span class="nx">target</span><span class="p">.</span><span class="nx">closest</span><span class="p">(</span><span class="s1">&#39;[data-id]&#39;</span><span class="p">).</span><span class="nx">dataset</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="nx">host</span><span class="p">.</span><span class="nx">removeUser</span><span class="p">.</span><span class="nx">mutate</span><span class="p">({</span> <span class="nx">variables</span><span class="o">:</span> <span class="p">{</span> <span class="nx">id</span> <span class="p">}})</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">onSubmitForm</span> <span class="o">=</span> <span class="p">(</span><span class="nx">host</span><span class="p">,</span> <span class="nx">e</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">e</span><span class="p">.</span><span class="nx">preventDefault</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">  <span class="nx">host</span><span class="p">.</span><span class="nx">addUser</span><span class="p">.</span><span class="nx">mutate</span><span class="p">({</span>
</span></span><span class="line"><span class="cl">    <span class="nx">variables</span><span class="o">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nx">name</span>: <span class="kt">host.shadowRoot.getElementById</span><span class="p">(</span><span class="s1">&#39;name&#39;</span><span class="p">).</span><span class="nx">value</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="p">});</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nx">define</span><span class="p">(</span><span class="s1">&#39;users-list&#39;</span><span class="p">,</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">users</span>: <span class="kt">query</span><span class="p">(</span><span class="nx">UsersQuery</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">  <span class="nx">removeUser</span>: <span class="kt">mutation</span><span class="p">(</span><span class="nx">RemoveUserMutation</span><span class="p">,</span> <span class="p">{</span> <span class="nx">refetchQueries</span><span class="p">,</span> <span class="nx">awaitRefetchQueries</span>: <span class="kt">true</span> <span class="p">}),</span>
</span></span><span class="line"><span class="cl">  <span class="nx">addUser</span>: <span class="kt">mutation</span><span class="p">(</span><span class="nx">AddUserMutation</span><span class="p">,</span> <span class="p">{</span> <span class="nx">refetchQueries</span><span class="p">,</span> <span class="nx">awaitRefetchQueries</span>: <span class="kt">true</span> <span class="p">}),</span>
</span></span><span class="line"><span class="cl">  <span class="nx">render</span><span class="o">:</span> <span class="p">({</span> <span class="nx">users</span><span class="p">,</span> <span class="nx">addUser</span><span class="p">,</span> <span class="nx">removeUser</span> <span class="p">})</span> <span class="o">=&gt;</span> <span class="nx">html</span><span class="sb">`
</span></span></span><span class="line"><span class="cl"><span class="sb">    &lt;link rel=&#34;stylesheet&#34; href=&#34;users-list.css&#34;&gt;
</span></span></span><span class="line"><span class="cl"><span class="sb">    &lt;ol&gt;</span><span class="si">${</span><span class="p">(</span><span class="nx">users</span><span class="p">.</span><span class="nx">data</span><span class="o">?</span><span class="p">.</span><span class="nx">users</span><span class="o">??</span><span class="p">[]).</span><span class="nx">map</span><span class="p">(</span><span class="nx">x</span> <span class="o">=&gt;</span> <span class="nx">html</span><span class="sb">`
</span></span></span><span class="line"><span class="cl"><span class="sb">      &lt;li data-id=&#34;</span><span class="si">${</span><span class="nx">x</span><span class="p">.</span><span class="nx">id</span><span class="si">}</span><span class="sb">&#34;&gt;
</span></span></span><span class="line"><span class="cl"><span class="sb">        </span><span class="si">${</span><span class="nx">x</span><span class="p">.</span><span class="nx">name</span><span class="si">}</span><span class="sb">
</span></span></span><span class="line"><span class="cl"><span class="sb">        &lt;button aria-label=&#34;Remove&#34; disabled=&#34;</span><span class="si">${</span><span class="nx">removeUser</span><span class="p">.</span><span class="nx">loading</span><span class="si">}</span><span class="sb">&#34; onclick=&#34;</span><span class="si">${</span><span class="nx">onRemoveUser</span><span class="si">}</span><span class="sb">&#34;&gt;x&lt;/button&gt;
</span></span></span><span class="line"><span class="cl"><span class="sb">      &lt;/li&gt;
</span></span></span><span class="line"><span class="cl"><span class="sb">    `</span><span class="p">)</span><span class="si">}</span><span class="sb">&lt;/ol&gt;
</span></span></span><span class="line"><span class="cl"><span class="sb">    &lt;form onsubmit=</span><span class="si">${</span><span class="nx">onSubmitForm</span><span class="si">}</span><span class="sb">&gt;
</span></span></span><span class="line"><span class="cl"><span class="sb">      &lt;label&gt;Name &lt;input id=&#34;name&#34; disabled=&#34;</span><span class="si">${</span><span class="nx">addUser</span><span class="p">.</span><span class="nx">loading</span><span class="si">}</span><span class="sb">&#34;&gt;&lt;/label&gt;
</span></span></span><span class="line"><span class="cl"><span class="sb">      &lt;button disabled=&#34;</span><span class="si">${</span><span class="nx">addUser</span><span class="p">.</span><span class="nx">loading</span> <span class="o">||</span> <span class="nx">removeUser</span><span class="p">.</span><span class="nx">loading</span><span class="si">}</span><span class="sb">&#34;&gt;Submit&lt;/button&gt;
</span></span></span><span class="line"><span class="cl"><span class="sb">    &lt;/form&gt;
</span></span></span><span class="line"><span class="cl"><span class="sb">  `</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"><span class="p">});</span></span></span></code></pre></div>
  <template data-playground-id="hybrids-query"
            data-filename="users-list.ts">import { mutation, query, define, html } from &#39;@apollo-elements/hybrids&#39;;
  
  import { UsersQuery } from &#39;./Users.query.graphql.js&#39;;
  import { AddUserMutation } from &#39;./AddUser.mutation.graphql.js&#39;;
  import { RemoveUserMutation } from &#39;./RemoveUser.mutation.graphql.js&#39;;
  
  const refetchQueries = [{ query: UsersQuery }];
  
  const onRemoveUser = (host, e) =&gt; {
    e.preventDefault();
    const { id } = e.target.closest(&#39;[data-id]&#39;).dataset;
    host.removeUser.mutate({ variables: { id }})
  }
  
  const onSubmitForm = (host, e) =&gt; {
    e.preventDefault();
    host.addUser.mutate({
      variables: {
        name: host.shadowRoot.getElementById(&#39;name&#39;).value,
      },
    });
  }
  
  define(&#39;users-list&#39;, {
    users: query(UsersQuery),
    removeUser: mutation(RemoveUserMutation, { refetchQueries, awaitRefetchQueries: true }),
    addUser: mutation(AddUserMutation, { refetchQueries, awaitRefetchQueries: true }),
    render: ({ users, addUser, removeUser }) =&gt; html`
      &lt;link rel=&#34;stylesheet&#34; href=&#34;users-list.css&#34;&gt;
      &lt;ol&gt;${(users.data?.users??[]).map(x =&gt; html`
        &lt;li data-id=&#34;${x.id}&#34;&gt;
          ${x.name}
          &lt;button aria-label=&#34;Remove&#34; disabled=&#34;${removeUser.loading}&#34; onclick=&#34;${onRemoveUser}&#34;&gt;x&lt;/button&gt;
        &lt;/li&gt;
      `)}&lt;/ol&gt;
      &lt;form onsubmit=${onSubmitForm}&gt;
        &lt;label&gt;Name &lt;input id=&#34;name&#34; disabled=&#34;${addUser.loading}&#34;&gt;&lt;/label&gt;
        &lt;button disabled=&#34;${addUser.loading || removeUser.loading}&#34;&gt;Submit&lt;/button&gt;
      &lt;/form&gt;
    `,
  });</template>

  <template data-playground-id="hybrids-query"
            data-filename="users-list.css">:host {
    display: block;
    counter-reset: item;
  }
  
  form {
    display: grid;
    grid-template-columns: auto min-content;
  }
  
  label {
    display: contents;
  }
  
  ol {
    padding: 0;
  }
  
  li {
    display: flex;
    justify-content: space-between;
    counter-increment: item;
  }
  
  li::before {
    content: counter(item);
    margin-inline-end: 4px;
  }
  
  li button {
    margin-inline-start: auto;
  }</template>


  <template data-playground-id="hybrids-query"
            data-filename="Users.query.graphql.ts">import type { User } from &#39;./client&#39;;
  import type { TypedDocumentNode } from &#39;@apollo/client/core&#39;;
  import { gql } from &#39;@apollo/client/core&#39;;
  export const UsersQuery: TypedDocumentNode&lt;{ users: User[] }&gt; =  gql`
    query UsersQuery {
      users {
        id
        name
      }
    }
  `;</template>


  <template data-playground-id="hybrids-query"
            data-filename="index.html">&lt;script type=&#34;module&#34; src=&#34;client.js&#34;&gt;&lt;/script&gt;
  &lt;script type=&#34;module&#34; src=&#34;users-list.js&#34;&gt;&lt;/script&gt;
  &lt;users-list&gt;&lt;/users-list&gt;</template>


  <template data-playground-id="hybrids-query"
            data-filename="client.ts">import type { InMemoryCacheConfig, NormalizedCacheObject } from &#39;@apollo/client/core&#39;;
  
  import { SchemaLink } from &#39;@apollo/client/link/schema&#39;;
  import { makeExecutableSchema } from &#39;@graphql-tools/schema&#39;;
  import { addMocksToSchema } from &#39;@graphql-tools/mock&#39;;
  
  import { ApolloClient, InMemoryCache, HttpLink } from &#39;@apollo/client/core&#39;;
  
  export interface User {
    id: string;
    name: string;
    status?: &#39;DELETED&#39;;
  };
  
  const typeDefs = `
    type User {
      name: String
      id: ID
    }
  
    type Query {
      users: [User]
    }
  
    type Mutation {
      addUser(name: String): User
      removeUser(id: ID): User
    }
  `;
  
  const USERS = [
    { id: 1, name: &#39;Neil&#39; }
  ];
  
  const randomDelay = () =&gt;  new Promise(r =&gt; setTimeout(r, Math.random() * 500));
  
  export const client = new ApolloClient({
    cache: new InMemoryCache(),
    link: new SchemaLink({
      schema: makeExecutableSchema({
        typeDefs,
        resolvers: {
          Query: {
            users() {
              return USERS.filter(x =&gt; x.status !== &#39;DELETED&#39;);
            }
          },
          Mutation: {
            async addUser(_, { name }) {
              const user = { name, id: Math.max(...USERS.map(x =&gt; x.id)) &#43; 1 };
              USERS.push(user);
              await randomDelay()
              return user;
            },
            async removeUser(_, { id }) {
              const user = USERS.find(x =&gt; x.id == parseInt(id));
              user.status = &#39;DELETED&#39;;
              await randomDelay();
              return user;
            }
          }
        }
      }),
    }),
  });
  
  window.__APOLLO_CLIENT__ = client;</template>

</docs-playground>

]]></content:encoded>
    </item><item>
      <title>Subscription Factory</title>
      <link>https://apolloelements.dev/api/libraries/hybrids/subscription/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/api/libraries/hybrids/subscription/</guid>
      <description>&lt;!-- ----------------------------------------------------------------------------------------
     Welcome! This file includes automatically generated API documentation.
     To edit the docs that appear within, find the original source file under `packages/*`,
     corresponding to the package name and module in this YAML front-matter block.
     Thank you for your interest in Apollo Elements 😁
------------------------------------------------------------------------------------------ --&gt;
&lt;p&gt;Use the &lt;code&gt;subscription&lt;/code&gt; factory to add a GraphQL subscription to you hybrids element.&lt;/p&gt;
&lt;docs-playground id=&#34;subscription-factory&#34;&gt;
  &lt;template shadowrootmode=&#34;open&#34;&gt;
    &lt;style&gt;
      :host {
        display: block;
        box-sizing: border-box;
        position: relative;
        width: 100%;
        height: auto;
      }

      playground-ide {
        display: none;
        border: 0;
        overflow: hidden;

        --playground-code-font-family: monospace;
        --playground-code-font-size: 14px;
        --playground-border: none;
      }

      #snippet,
      playground-ide {
        width: 100%;
        height: 100%;
        border-radius: var(--playground-snippet-border-radius, 6px);
      }

      #snippet {
        display: block;
        box-sizing: border-box;
      }

      #snippet,
      button {
        border: 1px solid var(--playground-snippet-border-color, transparent);
        transition: border-color 0.2s ease-in-out;
        will-change: border-color;
      }

      :host([show]) playground-ide {
        display: flex;
        width: var(--playground-ide-width, 100%);
        height: var(--playground-ide-height, 600px);
      }

      button {
        background: var(--playground-snippet-button-background);
        border-end-end-radius: 6px;
        border-start-start-radius: 6px;
        color: inherit;
        cursor: pointer;
        display: block;
        font-size: 16px;
        outline: none;
        padding: 9px 16px;
        position: absolute;
        bottom: 0;
        right: -2px;
        transition:
          border-color 0.2s ease-in-out,
          background 0.1s ease,
          color 0.1s ease;
      }

      button:focus,
      button:hover {
        color: var(--playground-snippet-button-focus-color, var(--code-button-focus-color));
        background: var(--playground-snippet-button-focus-background, var(--code-button-focus-background));
        border-bottom-color: var(--playground-snippet-button-focus-background, var(--code-button-focus-background)) !important;
        border-right-color: var(--playground-snippet-button-focus-background, var(--code-button-focus-background)) !important;
      }

      :host([show]) #snippet,
      :host([show]) button {
        display: none;
      }

      :host(:not([show]):focus-within) #snippet,
      :host(:not([show]):hover) #snippet {
        border-color: var(--playground-snippet-focus-border-color, black);
      }

      :host(:not([show]):focus-within) button,
      :host(:not([show]):hover) button {
        border-top-color: var(--playground-snippet-focus-border-color, black);
        border-left-color: var(--playground-snippet-focus-border-color, black);
        border-bottom-color: var(--playground-snippet-outer-background-color, var(--page-background));
        border-right-color: var(--playground-snippet-outer-background-color, var(--page-background));
      }

      #snippet ::slotted(pre) {
        margin-bottom: 0 !important;
      }

      :host([loading]) #edit,
      #loading {
        display: none;
      }

      :host([loading]) #loading {
        display: inline-block;
      }
    &lt;/style&gt;

    &lt;div id=&#34;snippet&#34;&gt;&lt;slot&gt;&lt;/slot&gt;&lt;/div&gt;

    &lt;playground-ide part=&#34;playground-ide&#34; exportparts=&#34;lhs,rhs&#34;&gt;&lt;/playground-ide&gt;

    &lt;button part=&#34;button&#34;&gt;
      &lt;span id=&#34;edit&#34;&gt;▶️ Edit Live&lt;/span&gt;

      &lt;slot name=&#34;loader&#34;&gt;
        
        &lt;svg id=&#34;loading&#34; width=&#34;90&#34; height=&#34;20&#34; viewBox=&#34;0 0 120 30&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34; fill=&#34;var(--primary-text-color)&#34;&gt;
            &lt;circle cx=&#34;15&#34; cy=&#34;15&#34; r=&#34;15&#34;&gt;
                &lt;animate attributeName=&#34;r&#34; from=&#34;15&#34; to=&#34;15&#34;
                         begin=&#34;0s&#34; dur=&#34;0.8s&#34;
                         values=&#34;15;9;15&#34; calcMode=&#34;linear&#34;
                         repeatCount=&#34;indefinite&#34; /&gt;
                &lt;animate attributeName=&#34;fill-opacity&#34; from=&#34;1&#34; to=&#34;1&#34;
                         begin=&#34;0s&#34; dur=&#34;0.8s&#34;
                         values=&#34;1;.5;1&#34; calcMode=&#34;linear&#34;
                         repeatCount=&#34;indefinite&#34; /&gt;
            &lt;/circle&gt;
            &lt;circle cx=&#34;60&#34; cy=&#34;15&#34; r=&#34;9&#34; fill-opacity=&#34;0.3&#34;&gt;
                &lt;animate attributeName=&#34;r&#34; from=&#34;9&#34; to=&#34;9&#34;
                         begin=&#34;0s&#34; dur=&#34;0.8s&#34;
                         values=&#34;9;15;9&#34; calcMode=&#34;linear&#34;
                         repeatCount=&#34;indefinite&#34; /&gt;
                &lt;animate attributeName=&#34;fill-opacity&#34; from=&#34;0.5&#34; to=&#34;0.5&#34;
                         begin=&#34;0s&#34; dur=&#34;0.8s&#34;
                         values=&#34;.5;1;.5&#34; calcMode=&#34;linear&#34;
                         repeatCount=&#34;indefinite&#34; /&gt;
            &lt;/circle&gt;
            &lt;circle cx=&#34;105&#34; cy=&#34;15&#34; r=&#34;15&#34;&gt;
                &lt;animate attributeName=&#34;r&#34; from=&#34;15&#34; to=&#34;15&#34;
                         begin=&#34;0s&#34; dur=&#34;0.8s&#34;
                         values=&#34;15;9;15&#34; calcMode=&#34;linear&#34;
                         repeatCount=&#34;indefinite&#34; /&gt;
                &lt;animate attributeName=&#34;fill-opacity&#34; from=&#34;1&#34; to=&#34;1&#34;
                         begin=&#34;0s&#34; dur=&#34;0.8s&#34;
                         values=&#34;1;.5;1&#34; calcMode=&#34;linear&#34;
                         repeatCount=&#34;indefinite&#34; /&gt;
            &lt;/circle&gt;
        &lt;/svg&gt;
      &lt;/slot&gt;
    &lt;/button&gt;
  &lt;/template&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ts&#34; data-lang=&#34;ts&#34;&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;template data-playground-id=&#34;subscription-factory&#34;
            data-filename=&#34;user-added.ts&#34;&gt;&lt;/template&gt;

  &lt;template data-playground-id=&#34;subscription-factory&#34;
            data-filename=&#34;user-added.css&#34;&gt;&lt;/template&gt;


  &lt;template data-playground-id=&#34;subscription-factory&#34;
            data-filename=&#34;UserAdded.subscription.graphql.ts&#34;&gt;&lt;/template&gt;


  &lt;template data-playground-id=&#34;subscription-factory&#34;
            data-filename=&#34;index.html&#34;&gt;&amp;lt;script type=&amp;#34;module&amp;#34; src=&amp;#34;client.js&amp;#34;&amp;gt;&amp;lt;/script&amp;gt;
  &amp;lt;script type=&amp;#34;module&amp;#34; src=&amp;#34;users-list.js&amp;#34;&amp;gt;&amp;lt;/script&amp;gt;
  &amp;lt;users-list&amp;gt;&amp;lt;/users-list&amp;gt;&lt;/template&gt;


  &lt;template data-playground-id=&#34;subscription-factory&#34;
            data-filename=&#34;client.ts&#34;&gt;import type { InMemoryCacheConfig, NormalizedCacheObject } from &amp;#39;@apollo/client/core&amp;#39;;
  
  import { SchemaLink } from &amp;#39;@apollo/client/link/schema&amp;#39;;
  import { makeExecutableSchema } from &amp;#39;@graphql-tools/schema&amp;#39;;
  import { addMocksToSchema } from &amp;#39;@graphql-tools/mock&amp;#39;;
  
  import { ApolloClient, InMemoryCache, HttpLink } from &amp;#39;@apollo/client/core&amp;#39;;
  
  export interface User {
    id: string;
    name: string;
    status?: &amp;#39;DELETED&amp;#39;;
  };
  
  const typeDefs = `
    type User {
      name: String
      id: ID
    }
  
    type Query {
      users: [User]
    }
  
    type Mutation {
      addUser(name: String): User
      removeUser(id: ID): User
    }
  `;
  
  const USERS = [
    { id: 1, name: &amp;#39;Neil&amp;#39; }
  ];
  
  const randomDelay = () =&amp;gt;  new Promise(r =&amp;gt; setTimeout(r, Math.random() * 500));
  
  export const client = new ApolloClient({
    cache: new InMemoryCache(),
    link: new SchemaLink({
      schema: makeExecutableSchema({
        typeDefs,
        resolvers: {
          Query: {
            users() {
              return USERS.filter(x =&amp;gt; x.status !== &amp;#39;DELETED&amp;#39;);
            }
          },
          Mutation: {
            async addUser(_, { name }) {
              const user = { name, id: Math.max(...USERS.map(x =&amp;gt; x.id)) &amp;#43; 1 };
              USERS.push(user);
              await randomDelay()
              return user;
            },
            async removeUser(_, { id }) {
              const user = USERS.find(x =&amp;gt; x.id == parseInt(id));
              user.status = &amp;#39;DELETED&amp;#39;;
              await randomDelay();
              return user;
            }
          }
        }
      }),
    }),
  });
  
  window.__APOLLO_CLIENT__ = client;&lt;/template&gt;

&lt;/docs-playground&gt;</description>
      
      <content:encoded><![CDATA[<!-- ----------------------------------------------------------------------------------------
     Welcome! This file includes automatically generated API documentation.
     To edit the docs that appear within, find the original source file under `packages/*`,
     corresponding to the package name and module in this YAML front-matter block.
     Thank you for your interest in Apollo Elements 😁
------------------------------------------------------------------------------------------ -->
<p>Use the <code>subscription</code> factory to add a GraphQL subscription to you hybrids element.</p>
<docs-playground id="subscription-factory">
  <template shadowrootmode="open">
    <style>
      :host {
        display: block;
        box-sizing: border-box;
        position: relative;
        width: 100%;
        height: auto;
      }

      playground-ide {
        display: none;
        border: 0;
        overflow: hidden;

        --playground-code-font-family: monospace;
        --playground-code-font-size: 14px;
        --playground-border: none;
      }

      #snippet,
      playground-ide {
        width: 100%;
        height: 100%;
        border-radius: var(--playground-snippet-border-radius, 6px);
      }

      #snippet {
        display: block;
        box-sizing: border-box;
      }

      #snippet,
      button {
        border: 1px solid var(--playground-snippet-border-color, transparent);
        transition: border-color 0.2s ease-in-out;
        will-change: border-color;
      }

      :host([show]) playground-ide {
        display: flex;
        width: var(--playground-ide-width, 100%);
        height: var(--playground-ide-height, 600px);
      }

      button {
        background: var(--playground-snippet-button-background);
        border-end-end-radius: 6px;
        border-start-start-radius: 6px;
        color: inherit;
        cursor: pointer;
        display: block;
        font-size: 16px;
        outline: none;
        padding: 9px 16px;
        position: absolute;
        bottom: 0;
        right: -2px;
        transition:
          border-color 0.2s ease-in-out,
          background 0.1s ease,
          color 0.1s ease;
      }

      button:focus,
      button:hover {
        color: var(--playground-snippet-button-focus-color, var(--code-button-focus-color));
        background: var(--playground-snippet-button-focus-background, var(--code-button-focus-background));
        border-bottom-color: var(--playground-snippet-button-focus-background, var(--code-button-focus-background)) !important;
        border-right-color: var(--playground-snippet-button-focus-background, var(--code-button-focus-background)) !important;
      }

      :host([show]) #snippet,
      :host([show]) button {
        display: none;
      }

      :host(:not([show]):focus-within) #snippet,
      :host(:not([show]):hover) #snippet {
        border-color: var(--playground-snippet-focus-border-color, black);
      }

      :host(:not([show]):focus-within) button,
      :host(:not([show]):hover) button {
        border-top-color: var(--playground-snippet-focus-border-color, black);
        border-left-color: var(--playground-snippet-focus-border-color, black);
        border-bottom-color: var(--playground-snippet-outer-background-color, var(--page-background));
        border-right-color: var(--playground-snippet-outer-background-color, var(--page-background));
      }

      #snippet ::slotted(pre) {
        margin-bottom: 0 !important;
      }

      :host([loading]) #edit,
      #loading {
        display: none;
      }

      :host([loading]) #loading {
        display: inline-block;
      }
    </style>

    <div id="snippet"><slot></slot></div>

    <playground-ide part="playground-ide" exportparts="lhs,rhs"></playground-ide>

    <button part="button">
      <span id="edit">▶️ Edit Live</span>

      <slot name="loader">
        
        <svg id="loading" width="90" height="20" viewBox="0 0 120 30" xmlns="http://www.w3.org/2000/svg" fill="var(--primary-text-color)">
            <circle cx="15" cy="15" r="15">
                <animate attributeName="r" from="15" to="15"
                         begin="0s" dur="0.8s"
                         values="15;9;15" calcMode="linear"
                         repeatCount="indefinite" />
                <animate attributeName="fill-opacity" from="1" to="1"
                         begin="0s" dur="0.8s"
                         values="1;.5;1" calcMode="linear"
                         repeatCount="indefinite" />
            </circle>
            <circle cx="60" cy="15" r="9" fill-opacity="0.3">
                <animate attributeName="r" from="9" to="9"
                         begin="0s" dur="0.8s"
                         values="9;15;9" calcMode="linear"
                         repeatCount="indefinite" />
                <animate attributeName="fill-opacity" from="0.5" to="0.5"
                         begin="0s" dur="0.8s"
                         values=".5;1;.5" calcMode="linear"
                         repeatCount="indefinite" />
            </circle>
            <circle cx="105" cy="15" r="15">
                <animate attributeName="r" from="15" to="15"
                         begin="0s" dur="0.8s"
                         values="15;9;15" calcMode="linear"
                         repeatCount="indefinite" />
                <animate attributeName="fill-opacity" from="1" to="1"
                         begin="0s" dur="0.8s"
                         values="1;.5;1" calcMode="linear"
                         repeatCount="indefinite" />
            </circle>
        </svg>
      </slot>
    </button>
  </template><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ts" data-lang="ts"></code></pre></div>
  <template data-playground-id="subscription-factory"
            data-filename="user-added.ts"></template>

  <template data-playground-id="subscription-factory"
            data-filename="user-added.css"></template>


  <template data-playground-id="subscription-factory"
            data-filename="UserAdded.subscription.graphql.ts"></template>


  <template data-playground-id="subscription-factory"
            data-filename="index.html">&lt;script type=&#34;module&#34; src=&#34;client.js&#34;&gt;&lt;/script&gt;
  &lt;script type=&#34;module&#34; src=&#34;users-list.js&#34;&gt;&lt;/script&gt;
  &lt;users-list&gt;&lt;/users-list&gt;</template>


  <template data-playground-id="subscription-factory"
            data-filename="client.ts">import type { InMemoryCacheConfig, NormalizedCacheObject } from &#39;@apollo/client/core&#39;;
  
  import { SchemaLink } from &#39;@apollo/client/link/schema&#39;;
  import { makeExecutableSchema } from &#39;@graphql-tools/schema&#39;;
  import { addMocksToSchema } from &#39;@graphql-tools/mock&#39;;
  
  import { ApolloClient, InMemoryCache, HttpLink } from &#39;@apollo/client/core&#39;;
  
  export interface User {
    id: string;
    name: string;
    status?: &#39;DELETED&#39;;
  };
  
  const typeDefs = `
    type User {
      name: String
      id: ID
    }
  
    type Query {
      users: [User]
    }
  
    type Mutation {
      addUser(name: String): User
      removeUser(id: ID): User
    }
  `;
  
  const USERS = [
    { id: 1, name: &#39;Neil&#39; }
  ];
  
  const randomDelay = () =&gt;  new Promise(r =&gt; setTimeout(r, Math.random() * 500));
  
  export const client = new ApolloClient({
    cache: new InMemoryCache(),
    link: new SchemaLink({
      schema: makeExecutableSchema({
        typeDefs,
        resolvers: {
          Query: {
            users() {
              return USERS.filter(x =&gt; x.status !== &#39;DELETED&#39;);
            }
          },
          Mutation: {
            async addUser(_, { name }) {
              const user = { name, id: Math.max(...USERS.map(x =&gt; x.id)) &#43; 1 };
              USERS.push(user);
              await randomDelay()
              return user;
            },
            async removeUser(_, { id }) {
              const user = USERS.find(x =&gt; x.id == parseInt(id));
              user.status = &#39;DELETED&#39;;
              await randomDelay();
              return user;
            }
          }
        }
      }),
    }),
  });
  
  window.__APOLLO_CLIENT__ = client;</template>

</docs-playground>

]]></content:encoded>
    </item><item>
      <title>apollo-query Element</title>
      <link>https://apolloelements.dev/guides/usage/queries/html/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/guides/usage/queries/html/</guid>
      <description>&lt;p&gt;Use the &lt;code&gt;&amp;lt;apollo-query&amp;gt;&lt;/code&gt; element from &lt;code&gt;@apollo-elements/components&lt;/code&gt; to write declarative query elements in HTML. You can mix-and-match these elements in your app, e.g. writing some query components using JavaScript and various web components libraries, and other components using &lt;code&gt;&amp;lt;apollo-query&amp;gt;&lt;/code&gt; and HTML templates.&lt;/p&gt;
&lt;inline-notification type=&#34;tip&#34;&gt;
&lt;p&gt;This page is a HOW-TO guide. For detailed docs on the &lt;code&gt;&amp;lt;apollo-query&amp;gt;&lt;/code&gt; element&amp;rsquo;s API, see the &lt;a href=&#34;https://apolloelements.dev/api/components/apollo-query/&#34;&gt;API docs&lt;/a&gt;&lt;/p&gt;
&lt;/inline-notification&gt;
&lt;p&gt;Templates use &lt;a href=&#34;https://npm.im/stampino&#34;&gt;stampino&lt;/a&gt; and &lt;a href=&#34;https://npm.im/jexpr&#34;&gt;jexpr&lt;/a&gt; for efficiently updating data expressions. See their respective READMEs for more information.&lt;/p&gt;</description>
      
      <content:encoded><![CDATA[<p>Use the <code>&lt;apollo-query&gt;</code> element from <code>@apollo-elements/components</code> to write declarative query elements in HTML. You can mix-and-match these elements in your app, e.g. writing some query components using JavaScript and various web components libraries, and other components using <code>&lt;apollo-query&gt;</code> and HTML templates.</p>
<inline-notification type="tip">
<p>This page is a HOW-TO guide. For detailed docs on the <code>&lt;apollo-query&gt;</code> element&rsquo;s API, see the <a href="/api/components/apollo-query/">API docs</a></p>
</inline-notification>
<p>Templates use <a href="https://npm.im/stampino">stampino</a> and <a href="https://npm.im/jexpr">jexpr</a> for efficiently updating data expressions. See their respective READMEs for more information.</p>
<p>What that means is you can define the element&rsquo;s dynamic template using good-old HTML:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">apollo-query</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="p">&lt;</span><span class="nt">script</span> <span class="na">type</span><span class="o">=</span><span class="s">&#34;application/json&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nx">query</span> <span class="nx">Notifications</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nx">me</span> <span class="p">{</span> <span class="nx">id</span> <span class="nx">name</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl">      <span class="nx">notifications</span> <span class="p">{</span> <span class="nx">href</span> <span class="nx">title</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">  <span class="p">&lt;/</span><span class="nt">script</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="p">&lt;</span><span class="nt">template</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;</span><span class="nt">style</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="p">:</span><span class="nd">host</span><span class="o">([</span><span class="nt">loading</span><span class="o">])</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">opacity</span><span class="p">:</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;/</span><span class="nt">style</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="p">&lt;</span><span class="nt">link</span> <span class="na">rel</span><span class="o">=</span><span class="s">&#34;stylesheet&#34;</span> <span class="na">href</span><span class="o">=</span><span class="s">&#34;/components/notifications.css&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="p">&lt;</span><span class="nt">h2</span><span class="p">&gt;</span>Welcome, {{ data.me.name }}!<span class="p">&lt;/</span><span class="nt">h2</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;</span><span class="nt">p</span><span class="p">&gt;</span>You have {{ data.notifications.length }} notifications.<span class="p">&lt;/</span><span class="nt">p</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;</span><span class="nt">ol</span> <span class="na">class</span><span class="o">=</span><span class="s">&#34;notifications-list&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="p">&lt;</span><span class="nt">template</span> <span class="na">type</span><span class="o">=</span><span class="s">&#34;repeat&#34;</span> <span class="na">repeat</span><span class="o">=</span><span class="s">&#34;{{ data.notifications }}&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="p">&lt;</span><span class="nt">li</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">          <span class="p">&lt;</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">&#34;{{ item.href }}&#34;</span><span class="p">&gt;</span>{{ item.title }}<span class="p">&lt;/</span><span class="nt">a</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="p">&lt;/</span><span class="nt">li</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="p">&lt;/</span><span class="nt">template</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;</span><span class="nt">ol</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="p">&lt;/</span><span class="nt">template</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="p">&lt;/</span><span class="nt">apollo-query</span><span class="p">&gt;</span>
</span></span></code></pre></div><h2 id="template-expressions">Template Expressions</h2>
<p><code>jexpr</code> expressions are like handlebars, nunjucks, polymer, etc. expressions. You can do most things you can do in JavaScript using <code>jexpr</code>. Read more at the <a href="https://github.com/justinfagnani/jexpr">jexpr README</a> or try it out for yourself on the <a href="https://github.com/justinfagnani/stampino/issues/14">Stampino REPL</a></p>
<h2 id="template-bindings">Template Bindings</h2>
<p>Template bindings follow similar conventions to <a href="https://lit.dev/guide/template-reference#binding-types">lit-html</a>. You can bind to nodes or element children, attributes, DOM properties, or even event listeners.</p>
<h3 id="content-binding">Content Binding</h3>
<p>Bind to element content by adding an expression as a child of the element.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">apollo-query</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="p">&lt;</span><span class="nt">template</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;</span><span class="nt">samp</span><span class="p">&gt;</span>{{ data.content }}<span class="p">&lt;</span><span class="nt">samp</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="p">&lt;/</span><span class="nt">template</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="p">&lt;/</span><span class="nt">apollo-query</span><span class="p">&gt;</span>
</span></span></code></pre></div><h3 id="attribute-binding">Attribute Binding</h3>
<p>You can bind to attributes by adding an expression in an attribute position. For boolean attributes (where their presence indicates <code>true</code> and their absence <code>false</code>), prefix a <code>?</code> to the attribute name.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">apollo-query</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="p">&lt;</span><span class="nt">template</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;</span><span class="nt">label</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">      Message
</span></span><span class="line"><span class="cl">      <span class="p">&lt;</span><span class="nt">input</span> <span class="na">value</span><span class="o">=</span><span class="s">&#34;{{ data.message.content }}&#34;</span><span class="p">/&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;/</span><span class="nt">label</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;</span><span class="nt">button</span> <span class="err">?</span><span class="na">hidden</span><span class="o">=</span><span class="s">&#34;{{ data.isEditing }}&#34;</span><span class="p">&gt;</span>Edit<span class="p">&lt;/</span><span class="nt">button</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="p">&lt;/</span><span class="nt">template</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="p">&lt;/</span><span class="nt">apollo-query</span><span class="p">&gt;</span>
</span></span></code></pre></div><h3 id="property-binding">Property Binding</h3>
<p>Bind to DOM properties by prefixing <code>.</code> to the property name.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">apollo-query</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="p">&lt;</span><span class="nt">template</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;</span><span class="nt">figure</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="p">&lt;</span><span class="nt">img</span> <span class="err">.</span><span class="na">src</span><span class="o">=</span><span class="s">&#34;{{ data.user.avatar }}&#34;</span> <span class="na">alt</span><span class="o">=</span><span class="s">&#34;avatar&#34;</span><span class="p">/&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;/</span><span class="nt">figure</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="p">&lt;/</span><span class="nt">template</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="p">&lt;/</span><span class="nt">apollo-query</span><span class="p">&gt;</span>
</span></span></code></pre></div><h3 id="event-binding">Event Binding</h3>
<p>If you pass a method to your model (e.g. by passing extra model content in the element&rsquo;s <code>extras</code> DOM property), you can add event listeners to elements by prefixing <code>@</code> to the event name in an attribute position.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">apollo-query</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="p">&lt;</span><span class="nt">template</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;</span><span class="nt">button</span> <span class="err">@</span><span class="na">click</span><span class="o">=</span><span class="s">&#34;{{ onClick }}&#34;</span><span class="p">&gt;</span>Ping<span class="p">&lt;/</span><span class="nt">button</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="p">&lt;/</span><span class="nt">template</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="p">&lt;/</span><span class="nt">apollo-query</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">script</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kr">const</span> <span class="nx">queryEl</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">currentScript</span><span class="p">.</span><span class="nx">getRootNode</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">      <span class="p">.</span><span class="nx">querySelector</span><span class="p">(</span><span class="s1">&#39;apollo-query&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="nx">queryEl</span><span class="p">.</span><span class="nx">extras</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nx">onClick</span><span class="p">(</span><span class="nx">event</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nx">fetch</span><span class="p">(</span><span class="sb">`/ping?user=</span><span class="si">${</span><span class="nx">queryEl</span><span class="p">.</span><span class="nx">data</span><span class="p">.</span><span class="nx">userId</span><span class="si">}</span><span class="sb">`</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">      <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">&lt;/</span><span class="nt">script</span><span class="p">&gt;</span>
</span></span></code></pre></div><h2 id="custom-template-handlers">Custom Template Handlers</h2>
<p>You can set the <code>templateHanders</code> property on an <code>&lt;apollo-query&gt;</code> element to customize rendering behaviour by adding your own custom template types.</p>
<inline-notification type="warning">
  <p>The Stampino API is still undergoing revision. For advanced usages, we recommend writing a custom element class for now.</p>
</inline-notification>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">apollo-query</span> <span class="na">no-auto-subscribe</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="p">&lt;</span><span class="nt">template</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;</span><span class="nt">template</span> <span class="na">type</span><span class="o">=</span><span class="s">&#34;flashy&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="p">&lt;</span><span class="nt">samp</span><span class="p">&gt;</span>{{ data.content }}<span class="p">&lt;</span><span class="nt">samp</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;/</span><span class="nt">template</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="p">&lt;/</span><span class="nt">template</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="p">&lt;/</span><span class="nt">apollo-query</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">script</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="kr">async</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="kr">import</span><span class="p">(</span><span class="s1">&#39;lit&#39;</span><span class="p">).</span><span class="nx">then</span><span class="p">(({</span> <span class="nx">html</span> <span class="p">})</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nb">document</span><span class="p">.</span><span class="nx">currentScript</span><span class="p">.</span><span class="nx">getRootNode</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">      <span class="p">.</span><span class="nx">querySelector</span><span class="p">(</span><span class="s1">&#39;apollo-query&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">      <span class="p">.</span><span class="nx">templateHandlers</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nx">flashy</span><span class="p">(</span><span class="nx">template</span><span class="p">,</span> <span class="nx">model</span><span class="p">,</span> <span class="nx">handlers</span><span class="p">,</span> <span class="nx">renderers</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">          <span class="k">return</span> <span class="nx">html</span><span class="sb">`
</span></span></span><span class="line"><span class="cl"><span class="sb">            &lt;blink&gt;
</span></span></span><span class="line"><span class="cl"><span class="sb">              </span><span class="si">${</span><span class="nx">evaluateTemplate</span><span class="p">(</span><span class="nx">template</span><span class="p">,</span> <span class="nx">model</span><span class="p">,</span> <span class="nx">handlers</span><span class="p">,</span> <span class="nx">renderers</span><span class="p">)</span><span class="si">}</span><span class="sb">
</span></span></span><span class="line"><span class="cl"><span class="sb">            &lt;/blink&gt;
</span></span></span><span class="line"><span class="cl"><span class="sb">          `</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="p">},</span>
</span></span><span class="line"><span class="cl">      <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="nb">document</span><span class="p">.</span><span class="nx">currentScript</span><span class="p">.</span><span class="nx">getRootNode</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">      <span class="p">.</span><span class="nx">querySelector</span><span class="p">(</span><span class="s1">&#39;apollo-query&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">      <span class="p">.</span><span class="nx">subscribe</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">  <span class="p">});</span>
</span></span><span class="line"><span class="cl"><span class="p">})();</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">&lt;/</span><span class="nt">script</span><span class="p">&gt;</span>
</span></span></code></pre></div><h2 id="next-steps">Next Steps</h2>
<ul>
<li>Read the <a href="/api/components/apollo-query/"><code>&lt;apollo-query&gt;</code> API docs</a></li>
<li>Learn how to write <a href="/guides/usage/mutations/">mutation components</a></li>
</ul>
]]></content:encoded>
    </item><item>
      <title>apollo-subscription Element</title>
      <link>https://apolloelements.dev/guides/usage/subscriptions/html/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/guides/usage/subscriptions/html/</guid>
      <description>&lt;p&gt;Use the &lt;code&gt;&amp;lt;apollo-subscription&amp;gt;&lt;/code&gt; element from &lt;code&gt;@apollo-elements/components&lt;/code&gt; to write declarative subscription elements in HTML. You can mix-and-match these elements in your app, e.g. writing some subscription components using JavaScript and various web components libraries, and other components using &lt;code&gt;&amp;lt;apollo-subscription&amp;gt;&lt;/code&gt; and HTML templates.&lt;/p&gt;
&lt;inline-notification type=&#34;tip&#34;&gt;
&lt;p&gt;This page is a HOW-TO guide. For detailed docs on the &lt;code&gt;&amp;lt;apollo-subscription&amp;gt;&lt;/code&gt; element&amp;rsquo;s API, see the &lt;a href=&#34;https://apolloelements.dev/api/components/apollo-subscription/&#34;&gt;API docs&lt;/a&gt;&lt;/p&gt;
&lt;/inline-notification&gt;
&lt;p&gt;Templates use &lt;a href=&#34;https://npm.im/stampino&#34;&gt;stampino&lt;/a&gt; and &lt;a href=&#34;https://npm.im/jexpr&#34;&gt;jexpr&lt;/a&gt; for efficiently updating data expressions. See their respective READMEs for more information.&lt;/p&gt;</description>
      
      <content:encoded><![CDATA[<p>Use the <code>&lt;apollo-subscription&gt;</code> element from <code>@apollo-elements/components</code> to write declarative subscription elements in HTML. You can mix-and-match these elements in your app, e.g. writing some subscription components using JavaScript and various web components libraries, and other components using <code>&lt;apollo-subscription&gt;</code> and HTML templates.</p>
<inline-notification type="tip">
<p>This page is a HOW-TO guide. For detailed docs on the <code>&lt;apollo-subscription&gt;</code> element&rsquo;s API, see the <a href="/api/components/apollo-subscription/">API docs</a></p>
</inline-notification>
<p>Templates use <a href="https://npm.im/stampino">stampino</a> and <a href="https://npm.im/jexpr">jexpr</a> for efficiently updating data expressions. See their respective READMEs for more information.</p>
<inline-notification type="tip">
<p><code>jexpr</code> expressions are like handlebars, nunjucks, polymer, etc. expressions. You can do most things you can do in JavaScript using <code>jexpr</code>. Try it out for yourself on the <a href="https://github.com/justinfagnani/stampino/issues/14">Stampino REPL</a></p>
</inline-notification>
<p>What that means is you can define the element&rsquo;s dynamic template using good-old HTML:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">apollo-subscription</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="p">&lt;</span><span class="nt">script</span> <span class="na">type</span><span class="o">=</span><span class="s">&#34;application/json&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nx">subscription</span> <span class="nx">Notifications</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nx">newNotifications</span> <span class="p">{</span> <span class="nx">href</span> <span class="nx">title</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">  <span class="p">&lt;/</span><span class="nt">script</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="p">&lt;</span><span class="nt">template</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;</span><span class="nt">style</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="p">:</span><span class="nd">host</span><span class="o">([</span><span class="nt">loading</span><span class="o">])</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">opacity</span><span class="p">:</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;/</span><span class="nt">style</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="p">&lt;</span><span class="nt">link</span> <span class="na">rel</span><span class="o">=</span><span class="s">&#34;stylesheet&#34;</span> <span class="na">href</span><span class="o">=</span><span class="s">&#34;/components/notifications.css&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="p">&lt;</span><span class="nt">ol</span> <span class="na">class</span><span class="o">=</span><span class="s">&#34;notifications-list&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="p">&lt;</span><span class="nt">template</span> <span class="na">type</span><span class="o">=</span><span class="s">&#34;repeat&#34;</span> <span class="na">repeat</span><span class="o">=</span><span class="s">&#34;{{ data.notifications }}&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="p">&lt;</span><span class="nt">li</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">          <span class="p">&lt;</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">&#34;{{ item.href }}&#34;</span><span class="p">&gt;</span>{{ item.title }}<span class="p">&lt;/</span><span class="nt">a</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="p">&lt;/</span><span class="nt">li</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="p">&lt;/</span><span class="nt">template</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;</span><span class="nt">ol</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="p">&lt;/</span><span class="nt">template</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="p">&lt;/</span><span class="nt">apollo-subscription</span><span class="p">&gt;</span>
</span></span></code></pre></div><h2 id="data-templates">Data Templates</h2>
<p>Learn more about template expressions and bindings in the <a href="/guides/usage/queries/html/#template-expressions"><code>&lt;apollo-query&gt;</code> HTML element guide</a></p>
<h2 id="next-steps">Next Steps</h2>
<ul>
<li>Learn how to <a href="/guides/usage/local-state/">manage client-side state using Apollo Elements</a></li>
</ul>
]]></content:encoded>
    </item><item>
      <title>Buildless Development</title>
      <link>https://apolloelements.dev/guides/getting-started/buildless-development/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/guides/getting-started/buildless-development/</guid>
      <description>How to use Apollo Elements with @web/dev-server to develop your GraphQL-based app without a build step.</description>
      
      <content:encoded><![CDATA[<p>You can run your apollo-elements app without using a build step with the <a href="https://modern-web.dev/docs/dev-server/overview/">web dev server</a>.</p>
<p>This sample config lets you also import css and graphql into your lit-apollo components written in TypeScript:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">esbuildPlugin</span> <span class="p">}</span> <span class="nx">from</span> <span class="s1">&#39;@web/dev-server-esbuild&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">fromRollup</span> <span class="p">}</span> <span class="nx">from</span> <span class="s1">&#39;@web/dev-server-rollup&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="nx">rollupCommonjs</span> <span class="nx">from</span> <span class="s1">&#39;@rollup/plugin-commonjs&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="nx">rollupLitcss</span> <span class="nx">from</span> <span class="s1">&#39;rollup-plugin-lit-css&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="nx">rollupGraphQL</span> <span class="nx">from</span> <span class="s1">&#39;@rollup/plugin-graphql&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">litcss</span> <span class="o">=</span> <span class="nx">fromRollup</span><span class="p">(</span><span class="nx">rollupLitcss</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">graphql</span> <span class="o">=</span> <span class="nx">fromRollup</span><span class="p">(</span><span class="nx">rollupGraphQL</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">commonjs</span> <span class="o">=</span> <span class="nx">fromRollup</span><span class="p">(</span><span class="nx">rollupCommonjs</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="cm">/**
</span></span></span><span class="line"><span class="cl"><span class="cm"> * These are the CSS files you directly import into components
</span></span></span><span class="line"><span class="cl"><span class="cm"> * Transform these files into Lit `CSSResult` modules
</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span>
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">componentCSS</span> <span class="o">=</span>
</span></span><span class="line"><span class="cl">  <span class="s1">&#39;src/components/**/*.css&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="cm">/**
</span></span></span><span class="line"><span class="cl"><span class="cm"> * These are the CSS files you load globally in `index.html`.
</span></span></span><span class="line"><span class="cl"><span class="cm"> * Serve these as regular stylesheets
</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span>
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">globalCSS</span> <span class="o">=</span>
</span></span><span class="line"><span class="cl">  <span class="s1">&#39;examples/spacex/style.css&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">export</span> <span class="k">default</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">nodeResolve</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nx">watch</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nx">rootDir</span><span class="o">:</span> <span class="s1">&#39;.&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nx">port</span><span class="o">:</span> <span class="mi">8090</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nx">appIndex</span><span class="o">:</span> <span class="s1">&#39;src/index.html&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nx">mimeTypes</span><span class="o">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;src/components/**/*.css&#39;</span><span class="o">:</span> <span class="s1">&#39;js&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;src/**/*.graphql&#39;</span><span class="o">:</span> <span class="s1">&#39;js&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="nx">plugins</span><span class="o">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">    <span class="nx">litcss</span><span class="p">({</span> <span class="nx">include</span><span class="o">:</span> <span class="nx">componentCSS</span><span class="p">,</span> <span class="nx">exclude</span><span class="o">:</span> <span class="nx">globalCSS</span> <span class="p">}),</span>
</span></span><span class="line"><span class="cl">    <span class="nx">graphql</span><span class="p">(),</span>
</span></span><span class="line"><span class="cl">    <span class="nx">commonjs</span><span class="p">(),</span>
</span></span><span class="line"><span class="cl">    <span class="nx">esbuildPlugin</span><span class="p">({</span> <span class="nx">ts</span><span class="o">:</span> <span class="kc">true</span> <span class="p">}),</span>
</span></span><span class="line"><span class="cl">  <span class="p">],</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span></code></pre></div><p>If you&rsquo;re using TypeScript and importing CSS and GraphQL files with the rollup plugins, make sure to add this declaration somewhere in a <code>.d.ts</code> file in your project:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ts" data-lang="ts"><span class="line"><span class="cl"><span class="kr">declare</span> <span class="nx">module</span> <span class="s1">&#39;*.graphql&#39;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="kr">import</span> <span class="p">{</span> <span class="nx">DocumentNode</span> <span class="p">}</span> <span class="kr">from</span> <span class="s1">&#39;@apollo/client/core&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="kr">const</span> <span class="nx">defaultDocument</span>: <span class="kt">DocumentNode</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="kr">export</span> <span class="k">default</span> <span class="nx">defaultDocument</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">declare</span> <span class="nx">module</span> <span class="s1">&#39;*.css&#39;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="kr">import</span> <span class="p">{</span> <span class="nx">CSSResult</span> <span class="p">}</span> <span class="kr">from</span> <span class="s1">&#39;lit&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="kr">const</span> <span class="nx">css</span>: <span class="kt">CSSResult</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="kr">export</span> <span class="k">default</span> <span class="nx">css</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><h2 id="recommended-optimizations">Recommended Optimizations</h2>
<p>Apply these plugins to further reduce your bundle sizes.</p>
<ul>
<li><a href="https://www.npmjs.com/package/@rollup/plugin-terser">@rollup/plugin-terser</a></li>
<li><a href="https://npm.im/rollup-plugin-minify-html-literals">rollup-plugin-minify-html-literals</a></li>
<li><a href="https://npm.im/@open-wc/rollup-plugin-html">@open-wc/rollup-plugin-html</a></li>
</ul>
]]></content:encoded>
    </item><item>
      <title>Component Lifecycle</title>
      <link>https://apolloelements.dev/api/core/interfaces/mutation/lifecycle/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/api/core/interfaces/mutation/lifecycle/</guid>
      <description>Details on how to Apollo Elements GraphQL mutation components work.</description>
      
      <content:encoded><![CDATA[<h2 id="connectedcallback"><code>connectedCallback</code></h2>
<p>On connecting to the DOM, the element reads it&rsquo;s mutation and variable properties either from JavaScript, or from it&rsquo;s <a href="/guides/cool-tricks/inline-graphql-scripts/">script children</a>, and initializes a <a href="https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver">MutationObserver</a> to watch for changes to those children.</p>
<h2 id="mutate"><code>mutate</code></h2>
<p>Call this method to initiate the mutation. You can call it without arguments, or with a partial <a href="https://github.com/apollographql/apollo-client/blob/29d41eb590157777f8a65554698fcef4d757a691/src/core/watchQueryOptions.ts#L247-L276"><code>MutationOptions</code></a> object. The rest of the mutation options will fall back to the corresponding instance properties.</p>
<p>In other words, the following two snippets are equivalent:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ts" data-lang="ts"><span class="line"><span class="cl"><span class="nx">element</span><span class="p">.</span><span class="nx">optimisticResponse</span> <span class="o">=</span> <span class="p">({</span> <span class="nx">name</span> <span class="p">})</span> <span class="o">=&gt;</span> <span class="p">({</span> <span class="nx">__typename</span><span class="o">:</span> <span class="s1">&#39;Mutation&#39;</span><span class="p">,</span> <span class="nx">addUser</span><span class="o">:</span> <span class="p">{</span> <span class="nx">name</span> <span class="p">}</span> <span class="p">});</span>
</span></span><span class="line"><span class="cl"><span class="nx">element</span><span class="p">.</span><span class="nx">variables</span> <span class="o">=</span> <span class="p">{</span> <span class="nx">name</span><span class="o">:</span> <span class="s1">&#39;Hulda&#39;</span> <span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="nx">element</span><span class="p">.</span><span class="nx">mutate</span><span class="p">();</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ts" data-lang="ts"><span class="line"><span class="cl"><span class="nx">element</span><span class="p">.</span><span class="nx">mutate</span><span class="p">({</span>
</span></span><span class="line"><span class="cl">  <span class="nx">optimisticResponse</span><span class="o">:</span> <span class="p">({</span> <span class="nx">name</span> <span class="p">})</span> <span class="o">=&gt;</span> <span class="p">({</span> <span class="nx">__typename</span><span class="o">:</span> <span class="s1">&#39;Mutation&#39;</span><span class="p">,</span> <span class="nx">addUser</span><span class="o">:</span> <span class="p">{</span> <span class="nx">name</span> <span class="p">}</span> <span class="p">}),</span>
</span></span><span class="line"><span class="cl">  <span class="nx">variables</span><span class="o">:</span> <span class="p">{</span> <span class="nx">name</span><span class="o">:</span> <span class="s1">&#39;Hulda&#39;</span> <span class="p">},</span>
</span></span><span class="line"><span class="cl"><span class="p">});</span>
</span></span></code></pre></div><p>If another call is made to <code>mutate</code> before the first resolves, only the final call will set element instance properties.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ts" data-lang="ts"><span class="line"><span class="cl"><span class="nx">element</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="s1">&#39;apollo-mutation-result&#39;</span><span class="p">,</span> <span class="nx">event</span> <span class="o">=&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">event</span><span class="p">.</span><span class="nx">detail</span><span class="p">.</span><span class="nx">data</span><span class="p">.</span><span class="nx">addUser</span><span class="p">.</span><span class="nx">name</span><span class="p">));</span>
</span></span><span class="line"><span class="cl"><span class="nx">element</span><span class="p">.</span><span class="nx">mutate</span><span class="p">({</span> <span class="nx">variables</span><span class="o">:</span> <span class="p">{</span> <span class="nx">name</span><span class="o">:</span> <span class="s1">&#39;Miriam&#39;</span> <span class="p">}</span> <span class="p">});</span>
</span></span><span class="line"><span class="cl"><span class="nx">element</span><span class="p">.</span><span class="nx">mutate</span><span class="p">({</span> <span class="nx">variables</span><span class="o">:</span> <span class="p">{</span> <span class="nx">name</span><span class="o">:</span> <span class="s1">&#39;Devorah&#39;</span> <span class="p">}</span> <span class="p">});</span>
</span></span><span class="line"><span class="cl"><span class="nx">element</span><span class="p">.</span><span class="nx">mutate</span><span class="p">({</span> <span class="nx">variables</span><span class="o">:</span> <span class="p">{</span> <span class="nx">name</span><span class="o">:</span> <span class="s1">&#39;Yael&#39;</span> <span class="p">}</span> <span class="p">});</span>
</span></span><span class="line"><span class="cl"><span class="c1">// =&gt; logs: &#39;Yael&#39;
</span></span></span></code></pre></div><h2 id="updater"><code>updater</code></h2>
<p>Function which defines how to integrate the mutation result into the cache. For some simple cases Apollo can do this automatically, but for others you will need or want to control the process, for example, an <code>AddPostMutation</code> which adds a post to an array of Posts.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ts" data-lang="ts"><span class="line"><span class="cl"><span class="nx">element.updater</span>: <span class="kt">MutationUpdaterFn</span><span class="p">&lt;</span><span class="nt">AddPostsMutationData</span><span class="p">,</span> <span class="na">AddPostsMutationVariables</span><span class="p">&gt;</span> <span class="o">=</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nx">cache</span><span class="p">,</span> <span class="nx">result</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kr">const</span> <span class="nx">query</span> <span class="o">=</span> <span class="nx">LatestPostsQuery</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="kr">const</span> <span class="nx">cached</span> <span class="o">=</span> <span class="nx">cache</span><span class="p">.</span><span class="nx">readQuery</span><span class="p">({</span> <span class="nx">query</span>: <span class="kt">LatestPostsQuery</span> <span class="p">});</span>
</span></span><span class="line"><span class="cl">    <span class="kr">const</span> <span class="nx">data</span> <span class="o">=</span> <span class="p">{</span> <span class="nx">posts</span><span class="o">:</span> <span class="p">[</span><span class="nx">result</span><span class="p">.</span><span class="nx">data</span><span class="p">.</span><span class="nx">postBlogPost</span><span class="p">,</span> <span class="p">...</span><span class="nx">cached</span><span class="p">.</span><span class="nx">posts</span><span class="p">]</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="nx">cache</span><span class="p">.</span><span class="nx">writeQuery</span><span class="p">({</span> <span class="nx">query</span><span class="p">,</span> <span class="nx">data</span> <span class="p">});</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span></code></pre></div><h2 id="oncompleted"><code>onCompleted</code></h2>
<p>The <a href="/api/core/interfaces/mutation/#oncompleted"><code>onCompleted</code></a> callback is a unary function that takes a <a href="https://github.com/apollographql/apollo-client/blob/d470c964db46728d8a5dfc63990859c550fa1656/src/link/core/types.ts#L24-L32"><code>FetchResult</code></a>.</p>
<p><code>onCompleted</code> is called <em>after</em> the element instance&rsquo; properties are set.</p>
<h2 id="onerror"><code>onError</code></h2>
<p>The <a href="/api/core/interfaces/mutation/#onerror"><code>onError</code></a> callback is a unary function that takes an <code>Error</code> or <code>ApolloError</code>.</p>
<p><code>onError</code> is called <em>after</em> the element instance&rsquo; properties are set.</p>
<h2 id="events">Events</h2>
<p>Listen for the <code>apollo-mutation-result</code> and <code>apollo-error</code> <a href="/api/core/interfaces/mutation/#events">events</a> to react to changes. They fire <em>before</em> the element instance&rsquo; properties are set.</p>
<h3 id="apollo-mutation-result"><code>apollo-mutation-result</code></h3>
<p>Detail is an <a href="https://github.com/apollographql/apollo-client/blob/d470c964db46728d8a5dfc63990859c550fa1656/src/link/core/types.ts#L24-L32"><code>FetchResult</code></a> object.</p>
]]></content:encoded>
    </item><item>
      <title>Component Lifecycle</title>
      <link>https://apolloelements.dev/api/core/interfaces/query/lifecycle/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/api/core/interfaces/query/lifecycle/</guid>
      <description>Details on how to Apollo Elements GraphQL query components work.</description>
      
      <content:encoded><![CDATA[<h2 id="connectedcallback"><code>connectedCallback</code></h2>
<p>On connecting to the DOM, the element reads it&rsquo;s query and variable properties either from JavaScript, or from it&rsquo;s <a href="/guides/cool-tricks/inline-graphql-scripts/">script children</a>, and initializes a <a href="https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver">MutationObserver</a> to watch for changes to those children.</p>
<h2 id="documentchanged"><code>documentChanged</code></h2>
<p>When the <code>query</code> property changes (via JavaScript assignment, or when the GraphQL script child changes) the element sets up its <code>ObservableQuery</code> and begins fetching data (unless <a href="/guides/usage/queries/#preventing-automatic-subscription">configured otherwise</a>).</p>
<p>If both a GraphQL script child and a JavaScript property are present, JavaScript takes precedence.</p>
<h2 id="variableschanged"><code>variablesChanged</code></h2>
<p>When the <code>variables</code> property changes (via JavaScript assignment or when the JSON script child changes) the element either refetches the existing <code>ObservableQuery</code> or attempts to initialize a new one and fetch.</p>
<p>If both a JSON script child and a JavaScript property are present, JavaScript takes precedence.</p>
<h2 id="shouldsubscribe"><code>shouldSubscribe</code></h2>
<p>Called synchronously before all automatic attempts to subscribe. If it returns true, the element will subscribe and begin fetching. Returns <code>true</code> by default, Override to <a href="/guides/usage/queries/#preventing-automatic-subscription">prevent automatic subscription</a>.</p>
<h2 id="subscribe"><code>subscribe</code></h2>
<p>When called automatically (via <code>documentChanged</code> or <code>variablesChanged</code>) or explicitly, it stops any existing <code>ObservableQuery</code>, then initializes a new one and begins fetching.</p>
<h2 id="executequery"><code>executeQuery</code></h2>
<p>If you want to explicitly run a query and receive a promise of the result, then <code>await element.executeQuery()</code>. The promise will resolve when the query does, and <em>after</em> the element instances&rsquo; properties are set.</p>
<h2 id="options"><code>options</code></h2>
<p>Set this property at any point to reobserve the <code>ObservableQuery</code>.</p>
<h2 id="ondata"><code>onData</code></h2>
<p>The <a href="/api/core/interfaces/query/#ondata"><code>onData</code></a> callback is a unary function that takes an <code>ApolloQueryResult</code> containing <code>data</code>, <code>loading</code>, <code>error</code>, etc.</p>
<p><code>onData</code> is called <em>after</em> the element instance&rsquo; properties are set.</p>
<h2 id="onerror"><code>onError</code></h2>
<p>The <a href="/api/core/interfaces/query/#onerror"><code>onError</code></a> callback is a unary function that takes an <code>Error</code> or <code>ApolloError</code>.</p>
<p><code>onError</code> is called <em>after</em> the element instance&rsquo; properties are set.</p>
<h2 id="events">Events</h2>
<p>Listen for the <code>apollo-query-result</code> and <code>apollo-error</code> <a href="/api/core/interfaces/query/#events">events</a> to react to changes. They fire <em>before</em> the element instance&rsquo; properties are set.</p>
<h3 id="apollo-query-result"><code>apollo-query-result</code></h3>
<p>Detail is an <code>ApolloQueryResult</code> object.</p>
<table>
  <thead>
      <tr>
          <th>Property</th>
          <th>Type</th>
          <th>Description</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>data</td>
          <td><code>Data&lt;D&gt;</code></td>
          <td>If the query resolved, the data.</td>
      </tr>
      <tr>
          <td>error</td>
          <td><code>ApolloError</code></td>
          <td>If the query rejected, the error.</td>
      </tr>
      <tr>
          <td>errors</td>
          <td><code>readonly GraphQLError[]</code></td>
          <td>If the query returned partials results, and some were errors, the list of errors.</td>
      </tr>
      <tr>
          <td>loading</td>
          <td><code>boolean</code></td>
          <td>Whether the operation is in-flight.</td>
      </tr>
      <tr>
          <td>partial</td>
          <td><code>boolean</code></td>
          <td>Whether the query returned partial data.</td>
      </tr>
      <tr>
          <td>networkStatus</td>
          <td><code>NetworkStatus</code></td>
          <td>See <a href="/api/core/interfaces/query/#networkstatus">NetworkStatus</a>.</td>
      </tr>
  </tbody>
</table>
]]></content:encoded>
    </item><item>
      <title>Component Lifecycle</title>
      <link>https://apolloelements.dev/api/core/interfaces/subscription/lifecycle/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/api/core/interfaces/subscription/lifecycle/</guid>
      <description>Details on how to Apollo Elements GraphQL subscription components work.</description>
      
      <content:encoded><![CDATA[<h2 id="connectedcallback"><code>connectedCallback</code></h2>
<p>On connecting to the DOM, the element reads it&rsquo;s <code>subscription</code> and <code>variables</code> properties either from JavaScript, or from it&rsquo;s <a href="/guides/cool-tricks/inline-graphql-scripts/">script children</a>, and initializes a <a href="https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver">MutationObserver</a> to watch for changes to those children.</p>
<h2 id="documentchanged"><code>documentChanged</code></h2>
<p>When the <code>subscription</code> property changes (via JavaScript assignment, or when the GraphQL script child changes) the element sets up its <code>Observable</code> and begins fetching data (unless <a href="/guides/usage/queries/#preventing-automatic-subscription">configured otherwise</a>).</p>
<p>If both a GraphQL script child and a JavaScript property are present, JavaScript takes precedence.</p>
<h2 id="variableschanged"><code>variablesChanged</code></h2>
<p>When the <code>variables</code> property changes (via JavaScript assignment or when the JSON script child changes) the element either refetches the existing <code>Observable</code> or attempts to initialize a new one and fetch.</p>
<p>If both a JSON script child and a JavaScript property are present, JavaScript takes precedence.</p>
<h2 id="shouldsubscribe"><code>shouldSubscribe</code></h2>
<p>Called synchronously before all automatic attempts to subscribe. If it returns true, the element will subscribe and begin fetching. Returns <code>true</code> by default, Override to <a href="/guides/usage/queries/#preventing-automatic-subscription">prevent automatic subscription</a>.</p>
<h2 id="subscribe"><code>subscribe</code></h2>
<p>When called automatically (via <code>documentChanged</code> or <code>variablesChanged</code>) or explicitly, attemptes to subscribe. If a <code>observableSubscription</code> already exists, it will use that one, unless <a href="/api/core/interfaces/subscription/#shouldresubscribe"><code>shouldResubscribe</code></a> is set.</p>
<h2 id="cancel"><code>cancel</code></h2>
<p>When called, ends the subscription and unsets the <code>Observable</code>.</p>
<h2 id="onsubscriptiondata"><code>onSubscriptionData</code></h2>
<p>Unary function which takes an object containing <code>client</code> and <code>subscriptionData</code>. The <code>subscriptionData</code> contains <code>data</code>, <code>loading</code>, and <code>error</code> properties. It is called <strong>after</strong> the element instance&rsquo;s properties are set.</p>
<h2 id="onsubscriptioncomplete"><code>onSubscriptionComplete</code></h2>
<p>The <a href="/api/core/interfaces/subscription/#onsubscriptioncomplete"><code>onSubscriptionComplete</code></a> callback is a function of no parameters that is called when the subscription ends (e.g. via <code>cancel</code> or on disconnect).</p>
<p><code>onData</code> is called <em>after</em> the element instance&rsquo; properties are set.</p>
<h2 id="onerror"><code>onError</code></h2>
<p>The <a href="/api/core/interfaces/query/#onerror"><code>onError</code></a> callback is a unary function that takes an <code>Error</code> or <code>ApolloError</code>.</p>
<p><code>onError</code> is called <em>after</em> the element instance&rsquo; properties are set.</p>
<h2 id="disconnectedcallback"><code>disconnectedCallback</code></h2>
<p>Cancels the subscription.</p>
<h2 id="events">Events</h2>
<p>Listen for the <code>apollo-subscription-result</code> and <code>apollo-error</code> <a href="/api/core/interfaces/query/#events">events</a> to react to changes. They fire <em>before</em> the element instance&rsquo; properties are set.</p>
<h3 id="apollo-subscription-result"><code>apollo-subscription-result</code></h3>
<p>Detail is an object containing <code>client</code> and <code>subscriptionData</code>. The <code>subscriptionData</code> contains <code>data</code>, <code>loading</code>, and <code>error</code> properties. It is called <strong>after</strong> the element instance&rsquo;s properties are set.</p>
]]></content:encoded>
    </item><item>
      <title>From Apollo Client 2.0</title>
      <link>https://apolloelements.dev/guides/getting-started/migrating/apollo-client-2/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/guides/getting-started/migrating/apollo-client-2/</guid>
      <description>&lt;p&gt;Apollo Client 3 and Apollo Elements 3 both bring with them significant breaking changes. When upgrading your app to &lt;code&gt;@apollo-elements&lt;/code&gt; 3, follow these steps to ease the transition:&lt;/p&gt;
&lt;h3 id=&#34;replace-imports-with-apolloclientcore&#34;&gt;Replace imports with &lt;code&gt;@apollo/client/core&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;apollo-client&lt;/code&gt;, &lt;code&gt;apollo-cache-inmemory&lt;/code&gt;, &lt;code&gt;apollo-link-*&lt;/code&gt; and others are now supplied by &lt;code&gt;@apollo/client/core&lt;/code&gt;, so replace your import statements to match.
&lt;em&gt;NB:&lt;/em&gt; you should always import from &lt;code&gt;@apollo/client/core&lt;/code&gt;, not from &lt;code&gt;@apollo/client&lt;/code&gt;, as the latter includes dependencies on &lt;code&gt;react&lt;/code&gt; which you probably don&amp;rsquo;t need or want. A single import statement from &lt;code&gt;@apollo/client&lt;/code&gt; in your app can cause the TypeScript compiler to fail if &lt;code&gt;react&lt;/code&gt; is not installed as a dependency. To avoid this, always import from &lt;code&gt;@apollo/client/core&lt;/code&gt;.&lt;/p&gt;</description>
      
      <content:encoded><![CDATA[<p>Apollo Client 3 and Apollo Elements 3 both bring with them significant breaking changes. When upgrading your app to <code>@apollo-elements</code> 3, follow these steps to ease the transition:</p>
<h3 id="replace-imports-with-apolloclientcore">Replace imports with <code>@apollo/client/core</code></h3>
<p><code>apollo-client</code>, <code>apollo-cache-inmemory</code>, <code>apollo-link-*</code> and others are now supplied by <code>@apollo/client/core</code>, so replace your import statements to match.
<em>NB:</em> you should always import from <code>@apollo/client/core</code>, not from <code>@apollo/client</code>, as the latter includes dependencies on <code>react</code> which you probably don&rsquo;t need or want. A single import statement from <code>@apollo/client</code> in your app can cause the TypeScript compiler to fail if <code>react</code> is not installed as a dependency. To avoid this, always import from <code>@apollo/client/core</code>.</p>
<h3 id="remove-calls-to-writedata">Remove calls to <code>writeData</code></h3>
<p>If your app used <code>client.writeData</code> (e.g. to set default values when loading the cache), you must replace it with calls to either <code>writeQuery</code>, <code>writeFragment</code> or <code>cache.modify</code>. You can also set default values in <a href="#replace-resolvers-with-type-policies">field policies</a></p>
<h3 id="check-non-nullable-variables">Check Non-Nullable Variables</h3>
<p>Query and Subscription elements in <code>@apollo-elements</code> 2 tried to prevent operations with non-nullable variables from fetching if their required arguments were null or undefined. Version 3 removes that check by default, so as long as there&rsquo;s a client and a query, they subscribe immediately. To avoid errors, always make sure to set your variables before you query.</p>
<p>To keep components from fetching until they have their required variables, see <a href="/guides/cool-tricks/validating-variables/">Validating Variables</a>.</p>
<h3 id="replace-resolvers-with-type-policies">Replace Resolvers with Type Policies</h3>
<p>Apollo client 3 deprecates local resolvers in favour of type policies. Your resolvers will still work for now, but it&rsquo;s recommended to migrate them.</p>
<p>Say you had this query, and you wanted to define the client-side type policies for it.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-graphql" data-lang="graphql"><span class="line"><span class="cl"><span class="kd">query</span><span class="w"> </span><span class="nc">DetailsOpenQuery</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="py">eenieOpen</span><span class="w"> </span><span class="nd">@client</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="py">meenieOpen</span><span class="w"> </span><span class="nd">@client</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>In which case you might define the type policies like this:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ts" data-lang="ts"><span class="line"><span class="cl"><span class="kr">export</span> <span class="kr">const</span> <span class="nx">DetailsTypePolicies</span>: <span class="kt">TypePolicies</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">Query</span><span class="o">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nx">fields</span><span class="o">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nx">eenieOpen</span><span class="o">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nx">read</span><span class="p">(</span><span class="nx">prev</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="nx">prev</span><span class="p">;</span> <span class="p">},</span>
</span></span><span class="line"><span class="cl">        <span class="nx">merge</span><span class="p">(</span><span class="nx">_</span><span class="p">,</span> <span class="nx">next</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="nx">next</span><span class="p">;</span> <span class="p">},</span>
</span></span><span class="line"><span class="cl">      <span class="p">},</span>
</span></span><span class="line"><span class="cl">      <span class="nx">meenieOpen</span><span class="o">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nx">read</span><span class="p">(</span><span class="nx">prev</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="nx">prev</span><span class="p">;</span> <span class="p">},</span>
</span></span><span class="line"><span class="cl">        <span class="nx">merge</span><span class="p">(</span><span class="nx">_</span><span class="p">,</span> <span class="nx">next</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="nx">next</span><span class="p">;</span> <span class="p">},</span>
</span></span><span class="line"><span class="cl">      <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Use <code>TypePoliciesMixin</code> to declare a component&rsquo;s type policies by setting the <code>typePolicies</code> property on the component.</p>


<code-tabs collection="libraries" default-tab="lit"></code-tabs>



    
      

      
        <button class="tab-button"
                role="tab"
                data-tab="html"
                aria-selected="false">
          <span class="tab-icon">📦</span>
          <span class="tab-label">HTML</span>
        </button>
      
        <button class="tab-button"
                role="tab"
                data-tab="lit"
                aria-selected="false">
          <span class="tab-icon">📦</span>
          <span class="tab-label">Lit</span>
        </button>
      
        <button class="tab-button"
                role="tab"
                data-tab="fast"
                aria-selected="false">
          <span class="tab-icon">📦</span>
          <span class="tab-label">FAST</span>
        </button>
      
        <button class="tab-button"
                role="tab"
                data-tab="gluon"
                aria-selected="false">
          <span class="tab-icon">📦</span>
          <span class="tab-label">Gluon</span>
        </button>
      
        <button class="tab-button"
                role="tab"
                data-tab="haunted"
                aria-selected="false">
          <span class="tab-icon">📦</span>
          <span class="tab-label">Haunted</span>
        </button>
      
        <button class="tab-button"
                role="tab"
                data-tab="atomico"
                aria-selected="false">
          <span class="tab-icon">📦</span>
          <span class="tab-label">Atomico</span>
        </button>
      
        <button class="tab-button"
                role="tab"
                data-tab="hybrids"
                aria-selected="false">
          <span class="tab-icon">📦</span>
          <span class="tab-label">Hybrids</span>
        </button>
      
        <button class="tab-button"
                role="tab"
                data-tab="mixins"
                aria-selected="false">
          <span class="tab-icon">📦</span>
          <span class="tab-label">Vanilla</span>
        </button>
      
        <button class="tab-button"
                role="tab"
                data-tab="polymer"
                aria-selected="false">
          <span class="tab-icon">📦</span>
          <span class="tab-label">Polymer</span>
        </button>
      
    
  </div>

  
  <div class="tabs-content">
    
    
      <div class="tab-panel active"
           id="code-tabs-1781103291-default"
           role="tabpanel"
           data-tab="default"
           aria-labelledby="code-tabs-1781103291-default-tab">
        

  ```html tab html
  <p>HTML apps should set all their type policies on the <code>apollo-client</code> element</p>
  <apollo-client>...</apollo-client>
  <script>
    import('./typePolicies')
      .then(({ DetailsTypePolicies }) => {
        document
          .currentScript
          .getRootNode()
          .querySelector('apollo-client')
          .typePolicies = DetailsTypePolicies;
      });
  </script>
  ```
  ```

  ```ts tab mixins
  import { ApolloQueryMixin, TypePoliciesMixins } from '@apollo-elements/mixins';

  import { DetailsTypePolicies } from './typePolicies';

  const template = document.createElement('template');
  template.innerHTML = `
    <details id="eenie">
      <summary>Eenie</summary>
      I'm the first mouse
    </details>

    <details id="meenie">
      <summary>Meenie</summary>
      I'm the second mouse
    </details>
  `;

  class ToggleViews extends TypePoliciesMixin(ApolloQuery)<Data, Variables> {
    query = DetailsOpenQuery;

    typePolicies = DetailsTypePolicies;

    #data: Data = null;

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

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

    constructor() {
      super()
      this.attachShadow({ mode: 'open' });
      this.shadowRoot.append(template.content.cloneNode(true))
      for (const details of this.shadowRoot.querySelectorAll('details'))
        details.addEventListener('toggle', this.onToggle.bind(this));
      this.render();
    }

    render() {
      this.shadowRoot.getElementById('eenie').open =
        this.data?.eenieOpen ?? false;

      this.shadowRoot.getElementById('meenie').open =
        this.data?.meenieOpen ?? false;
    }

    onToggle(event) {
      this.client.cache.writeQuery({
        query: this.query,
        data: {
          ...this.data,
          [`${event.target.id}Open`]: event.target.open,
        }
      });
    }
  }

  customElements.define('toggle-views', ToggleViews);
  ```

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

  import { TypePoliciesMixins } from '@apollo-elements/mixins/type-policies-mixin';

  import { DetailsTypePolicies } from './typePolicies';

  @customElement('toggle-views')
  class ToggleViews extends TypePoliciesMixin(ApolloQuery)<Data, Variables> {
    query = DetailsOpenQuery;

    typePolicies = DetailsTypePolicies;

    render() {
      return html`
        <details id="eenie"
            ?open="${this.data?.eenieOpen ?? false}"
            @toggle="${this.onToggle}">
          <summary>Eenie</summary>
          I'm the first mouse
        </details>

        <details id="meenie"
            ?open="${this.data?.meenieOpen ?? false}"
            @toggle="${this.onToggle}">
          <summary>Meenie</summary>
          I'm the second mouse
        </details>
      `;
    }

    onToggle(event) {
      this.client.cache.writeQuery({
        query: this.query,
        data: {
          ...this.data,
          [`${event.target.id}Open`]: event.target.open,
        }
      });
    }
  }
  ```

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

  import { TypePoliciesMixins } from '@apollo-elements/mixins/type-policies-mixin';

  import { DetailsTypePolicies } from './typePolicies';

  const template: ViewTemplate = html`
    <details id="eenie"
        ?open="${x => x.data?.eenieOpen ?? false}"
        @toggle="${(x, { event }) => x.onToggle(event)}">
      <summary>Eenie</summary>
      I'm the first mouse
    </details>

    <details id="meenie"
        ?open="${x => x.data?.meenieOpen ?? false}"
        @toggle="${(x, { event }) => x.onToggle(event)}">
      <summary>Meenie</summary>
      I'm the second mouse
    </details>
  `;

  @customElement({ name: 'toggle-views', template })
  class ToggleViews extends TypePoliciesMixin(ApolloQuery)<Data, Variables> {
    query = DetailsOpenQuery;

    typePolicies = DetailsTypePolicies;

    onToggle(event) {
      this.client.cache.writeQuery({
        query: this.query,
        data: {
          ...this.data,
          [`${event.target.id}Open`]: event.target.open,
        }
      });
    }
  }
  ```

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

  import { DetailsTypePolicies } from './typePolicies';

  function ToggleViews() {
    const { client, data } = useQuery(DetailsOpenQuery)

    /**
     * There's no TypePoliciesMixin for haunted,
     * but you can use the `useEffect` hook to do the same
     */
    useEffect(({ host: { client } }) => {
      client.cache.policies.addTypePolicies(DetailsTypePolicies);
    }, [client]);

    function onToggle(event) {
      client.cache.writeQuery({
        query: DetailsOpenQuery,
        data: {
          ...data,
          [`${event.target.id}Open`]: event.target.open,
        }
      });
    }

    return html`
      <details id="eenie"
          ?open="${data.eenieOpen ?? false}"
          @toggle="${onToggle}">
        <summary>Eenie</summary>
        I'm the first mouse
      </details>

      <details id="meenie"
          ?open="${data.meenieOpen ?? false}"
          @toggle="${onToggle}">
        <summary>Meenie</summary>
        I'm the second mouse
      </details>
    `;
  }

  customElements.define('toggle-views', component(ToggleViews));
  ```

  ```ts tab hybrids
  import { query, define, property, html } from '@apollo-elements/hybrids';

  import { DetailsTypePolicies } from './typePolicies';

  function onToggle(host, event) {
    host.client.cache.writeQuery({
      query: host.query,
      data: {
        ...host.data,
        [`${event.target.id}Open`]: event.target.open,
      }
    });
  }

  const render = ({ data }) => html`
    <details id="eenie"
        open="${data.eenieOpen ?? false}"
        ontoggle="${onToggle}">
      <summary>Eenie</summary>
      I'm the first mouse
    </details>

    <details id="meenie"
        open="${data.meenieOpen ?? false}"
        ontoggle="${onToggle}">
      <summary>Meenie</summary>
      I'm the second mouse
    </details>
  `;

  /**
   * There's no TypePoliciesMixin for hybrids,
   * but you can use this one-line function to do the same
   */
  function connect(host) {
    host.client.cache.policies.addTypePolicies(host.typePolicies);
  }

  define('toggle-views', {
    render,
    query: query(DetailsOpenQuery),
    typePolicies: property(DetailsTypePolicies, connect),
  });
  ```


      </div>
    

    
    

    
      
        <div class="tab-panel"
             id="code-tabs-1781103291-html"
             role="tabpanel"
             data-tab="html"
             aria-labelledby="code-tabs-1781103291-html-tab">
          <div class="tab-placeholder">
            <p>Loading Html example...</p>
          </div>
        </div>
      
        <div class="tab-panel"
             id="code-tabs-1781103291-lit"
             role="tabpanel"
             data-tab="lit"
             aria-labelledby="code-tabs-1781103291-lit-tab">
          <div class="tab-placeholder">
            <p>Loading Lit example...</p>
          </div>
        </div>
      
        <div class="tab-panel"
             id="code-tabs-1781103291-fast"
             role="tabpanel"
             data-tab="fast"
             aria-labelledby="code-tabs-1781103291-fast-tab">
          <div class="tab-placeholder">
            <p>Loading Fast example...</p>
          </div>
        </div>
      
        <div class="tab-panel"
             id="code-tabs-1781103291-gluon"
             role="tabpanel"
             data-tab="gluon"
             aria-labelledby="code-tabs-1781103291-gluon-tab">
          <div class="tab-placeholder">
            <p>Loading Gluon example...</p>
          </div>
        </div>
      
        <div class="tab-panel"
             id="code-tabs-1781103291-haunted"
             role="tabpanel"
             data-tab="haunted"
             aria-labelledby="code-tabs-1781103291-haunted-tab">
          <div class="tab-placeholder">
            <p>Loading Haunted example...</p>
          </div>
        </div>
      
        <div class="tab-panel"
             id="code-tabs-1781103291-atomico"
             role="tabpanel"
             data-tab="atomico"
             aria-labelledby="code-tabs-1781103291-atomico-tab">
          <div class="tab-placeholder">
            <p>Loading Atomico example...</p>
          </div>
        </div>
      
        <div class="tab-panel"
             id="code-tabs-1781103291-hybrids"
             role="tabpanel"
             data-tab="hybrids"
             aria-labelledby="code-tabs-1781103291-hybrids-tab">
          <div class="tab-placeholder">
            <p>Loading Hybrids example...</p>
          </div>
        </div>
      
        <div class="tab-panel"
             id="code-tabs-1781103291-mixins"
             role="tabpanel"
             data-tab="mixins"
             aria-labelledby="code-tabs-1781103291-mixins-tab">
          <div class="tab-placeholder">
            <p>Loading Mixins example...</p>
          </div>
        </div>
      
        <div class="tab-panel"
             id="code-tabs-1781103291-polymer"
             role="tabpanel"
             data-tab="polymer"
             aria-labelledby="code-tabs-1781103291-polymer-tab">
          <div class="tab-placeholder">
            <p>Loading Polymer example...</p>
          </div>
        </div>
      
    
  </div>
</div>


<style>
  .code-tabs-container {
    display: block;
    margin: 1.5rem 0;
    border: 1px solid var(--color-border, #e1e5e9);
    border-radius: 8px;
    overflow: hidden;
    background: var(--color-surface, #ffffff);
  }

  .tabs-nav {
    display: flex;
    background: var(--color-surface-secondary, #f8f9fa);
    border-bottom: 1px solid var(--color-border, #e1e5e9);
    overflow-x: auto;
    scrollbar-width: none;
    -ms-overflow-style: none;
  }

  .tabs-nav::-webkit-scrollbar {
    display: none;
  }

  .tab-button {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.75rem 1rem;
    background: transparent;
    border: none;
    cursor: pointer;
    font-family: inherit;
    font-size: 0.875rem;
    font-weight: 500;
    color: var(--color-text-secondary, #6c757d);
    transition: all 0.2s ease;
    white-space: nowrap;
    border-bottom: 2px solid transparent;
    position: relative;
    &:hover {
      color: var(--color-primary, #a0f);
      background: rgba(160, 0, 255, 0.05);
    }
    &.active {
      color: var(--color-primary, #a0f);
      background: var(--color-surface, #ffffff);
      border-bottom-color: var(--color-primary, #a0f);
    }
  }

  .tab-icon {
    font-size: 1rem;
    flex-shrink: 0;
  }

  .tab-label {
    flex-shrink: 0;
  }

  .tabs-content {
    min-height: 300px;
  }

  .tab-panel {
    display: none;
    padding: 1.5rem;
    animation: fadeIn 0.3s ease-in-out;
  }

  .tab-panel.active {
    display: block;
  }

  .tab-placeholder {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 200px;
    color: var(--color-text-secondary, #6c757d);
    font-style: italic;
  }

   
  .tab-panel svg {
    width: 100px;
    height: 100px;
    margin: 0 auto 1rem;
    display: block;
    color: var(--color-primary, #a0f);
    opacity: 0.6;
  }

  .tab-panel p {
    text-align: center;
    color: var(--color-text-secondary, #6c757d);
    margin: 0;
  }

   
  @keyframes fadeIn {
    from { opacity: 0; transform: translateY(10px); }
    to { opacity: 1; transform: translateY(0); }
  }

   
  @media (prefers-color-scheme: dark) {
    .code-tabs-container {
      border-color: var(--color-border-dark, #404040);
      background: var(--color-surface-dark, #1a1a1a);
    }

    .tabs-nav {
      background: var(--color-surface-secondary-dark, #222222);
      border-bottom-color: var(--color-border-dark, #404040);
    }

    .tab-button.active {
      background: var(--color-surface-dark, #1a1a1a);
    }

    .tab-placeholder {
      color: var(--color-text-secondary-dark, #a1a1a1);
    }
  }

   
  @media (max-width: 768px) {
    .tab-button {
      padding: 0.5rem 0.75rem;
      font-size: 0.8rem;
    }

    .tab-icon {
      font-size: 0.9rem;
    }

    .tabs-content {
      min-height: 250px;
    }

    .tab-panel {
      padding: 1rem;
    }
  }
</style>


<script>
  document.addEventListener('DOMContentLoaded', () => {
    const container = document.getElementById('code-tabs-1781103291');
    if (!container) return;

    const tabButtons = container.querySelectorAll('.tab-button');
    const tabPanels = container.querySelectorAll('.tab-panel');

    
    function switchTab(targetTab) {
      
      tabButtons.forEach(button => {
        const isActive = button.getAttribute('data-tab') === targetTab;
        button.classList.toggle('active', isActive);
        button.setAttribute('aria-selected', isActive);
      });

      
      tabPanels.forEach(panel => {
        const isActive = panel.getAttribute('data-tab') === targetTab;
        panel.classList.toggle('active', isActive);
      });

      
      if (container.getAttribute('data-collection') === 'frameworks') {
        populateFrameworkContent(targetTab);
      }
    }

    
    tabButtons.forEach(button => {
      button.addEventListener('click', () => {
        const targetTab = button.getAttribute('data-tab');
        switchTab(targetTab);
      });
    });

    
    function populateFrameworkContent(framework) {
      const panel = container.querySelector(`[data-tab="${framework}"]`);
      if (!panel || panel.querySelector('.codesandbox-container')) return;

      const placeholder = panel.querySelector('.tab-placeholder');
      if (placeholder) {
        placeholder.innerHTML = `
          <div class="codesandbox-container">
            <div class="framework-demo">
              <div class="demo-header">
                <h4>${framework.charAt(0).toUpperCase() + framework.slice(1)} Demo</h4>
                <p>Apollo Elements integration with ${framework.charAt(0).toUpperCase() + framework.slice(1)}</p>
              </div>
              <div class="demo-content">
                <p>🚀 Interactive ${framework.charAt(0).toUpperCase() + framework.slice(1)} demo would load here</p>
                <button onclick="window.open('https://codesandbox.io/s/apollo-elements-in-${framework}', '_blank')"
                        class="demo-button">
                  Open in CodeSandbox
                </button>
              </div>
            </div>
          </div>
        `;
      }
    }

    
    
    switchTab('lit');
    

    
    setTimeout(() => {
      
      const slots = document.querySelectorAll('[slot]');
      slots.forEach(slot => {
        const slotName = slot.getAttribute('slot');
        const targetPanel = container.querySelector(`[data-tab="${slotName}"]`);
        if (targetPanel) {
          const placeholder = targetPanel.querySelector('.tab-placeholder');
          if (placeholder) {
            placeholder.parentNode.replaceChild(slot, placeholder);
          }
        }
      });
    }, 100);
  });
</script>

<style>
  code-tabs .highlight {
    width: 100%;
  }
  .framework-demo {
    text-align: center;
    padding: 2rem;
  }

  .demo-header h4 {
    margin: 0 0 0.5rem 0;
    color: var(--color-primary);
  }

  .demo-header p {
    margin: 0 0 1.5rem 0;
    color: var(--color-text-secondary);
    opacity: 0.8;
  }

  .demo-content {
    background: var(--color-surface-secondary);
    border-radius: 8px;
    padding: 1.5rem;
    border: 1px solid var(--color-border);
  }

  .demo-button {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.75rem 1.5rem;
    background: var(--color-primary);
    color: white;
    border: none;
    border-radius: 6px;
    font-weight: 500;
    cursor: pointer;
    transition: all 0.2s ease;
    text-decoration: none;
    margin-top: 1rem;
  }

  .demo-button:hover {
    background: var(--color-primary-hover);
    transform: translateY(-1px);
  }
</style>

]]></content:encoded>
    </item><item>
      <title>Mutation Factory</title>
      <link>https://apolloelements.dev/api/libraries/hybrids/mutation/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/api/libraries/hybrids/mutation/</guid>
      <description>&lt;!-- ----------------------------------------------------------------------------------------
     Welcome! This file includes automatically generated API documentation.
     To edit the docs that appear within, find the original source file under `packages/*`,
     corresponding to the package name and module in this YAML front-matter block.
     Thank you for your interest in Apollo Elements 😁
------------------------------------------------------------------------------------------ --&gt;
&lt;p&gt;Use the &lt;code&gt;mutation&lt;/code&gt; factory to add a GraphQL mutation to you hybrids element.&lt;/p&gt;
&lt;docs-playground id=&#34;mutation-factory&#34;&gt;
  &lt;template shadowrootmode=&#34;open&#34;&gt;
    &lt;style&gt;
      :host {
        display: block;
        box-sizing: border-box;
        position: relative;
        width: 100%;
        height: auto;
      }

      playground-ide {
        display: none;
        border: 0;
        overflow: hidden;

        --playground-code-font-family: monospace;
        --playground-code-font-size: 14px;
        --playground-border: none;
      }

      #snippet,
      playground-ide {
        width: 100%;
        height: 100%;
        border-radius: var(--playground-snippet-border-radius, 6px);
      }

      #snippet {
        display: block;
        box-sizing: border-box;
      }

      #snippet,
      button {
        border: 1px solid var(--playground-snippet-border-color, transparent);
        transition: border-color 0.2s ease-in-out;
        will-change: border-color;
      }

      :host([show]) playground-ide {
        display: flex;
        width: var(--playground-ide-width, 100%);
        height: var(--playground-ide-height, 600px);
      }

      button {
        background: var(--playground-snippet-button-background);
        border-end-end-radius: 6px;
        border-start-start-radius: 6px;
        color: inherit;
        cursor: pointer;
        display: block;
        font-size: 16px;
        outline: none;
        padding: 9px 16px;
        position: absolute;
        bottom: 0;
        right: -2px;
        transition:
          border-color 0.2s ease-in-out,
          background 0.1s ease,
          color 0.1s ease;
      }

      button:focus,
      button:hover {
        color: var(--playground-snippet-button-focus-color, var(--code-button-focus-color));
        background: var(--playground-snippet-button-focus-background, var(--code-button-focus-background));
        border-bottom-color: var(--playground-snippet-button-focus-background, var(--code-button-focus-background)) !important;
        border-right-color: var(--playground-snippet-button-focus-background, var(--code-button-focus-background)) !important;
      }

      :host([show]) #snippet,
      :host([show]) button {
        display: none;
      }

      :host(:not([show]):focus-within) #snippet,
      :host(:not([show]):hover) #snippet {
        border-color: var(--playground-snippet-focus-border-color, black);
      }

      :host(:not([show]):focus-within) button,
      :host(:not([show]):hover) button {
        border-top-color: var(--playground-snippet-focus-border-color, black);
        border-left-color: var(--playground-snippet-focus-border-color, black);
        border-bottom-color: var(--playground-snippet-outer-background-color, var(--page-background));
        border-right-color: var(--playground-snippet-outer-background-color, var(--page-background));
      }

      #snippet ::slotted(pre) {
        margin-bottom: 0 !important;
      }

      :host([loading]) #edit,
      #loading {
        display: none;
      }

      :host([loading]) #loading {
        display: inline-block;
      }
    &lt;/style&gt;

    &lt;div id=&#34;snippet&#34;&gt;&lt;slot&gt;&lt;/slot&gt;&lt;/div&gt;

    &lt;playground-ide part=&#34;playground-ide&#34; exportparts=&#34;lhs,rhs&#34;&gt;&lt;/playground-ide&gt;

    &lt;button part=&#34;button&#34;&gt;
      &lt;span id=&#34;edit&#34;&gt;▶️ Edit Live&lt;/span&gt;

      &lt;slot name=&#34;loader&#34;&gt;
        
        &lt;svg id=&#34;loading&#34; width=&#34;90&#34; height=&#34;20&#34; viewBox=&#34;0 0 120 30&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34; fill=&#34;var(--primary-text-color)&#34;&gt;
            &lt;circle cx=&#34;15&#34; cy=&#34;15&#34; r=&#34;15&#34;&gt;
                &lt;animate attributeName=&#34;r&#34; from=&#34;15&#34; to=&#34;15&#34;
                         begin=&#34;0s&#34; dur=&#34;0.8s&#34;
                         values=&#34;15;9;15&#34; calcMode=&#34;linear&#34;
                         repeatCount=&#34;indefinite&#34; /&gt;
                &lt;animate attributeName=&#34;fill-opacity&#34; from=&#34;1&#34; to=&#34;1&#34;
                         begin=&#34;0s&#34; dur=&#34;0.8s&#34;
                         values=&#34;1;.5;1&#34; calcMode=&#34;linear&#34;
                         repeatCount=&#34;indefinite&#34; /&gt;
            &lt;/circle&gt;
            &lt;circle cx=&#34;60&#34; cy=&#34;15&#34; r=&#34;9&#34; fill-opacity=&#34;0.3&#34;&gt;
                &lt;animate attributeName=&#34;r&#34; from=&#34;9&#34; to=&#34;9&#34;
                         begin=&#34;0s&#34; dur=&#34;0.8s&#34;
                         values=&#34;9;15;9&#34; calcMode=&#34;linear&#34;
                         repeatCount=&#34;indefinite&#34; /&gt;
                &lt;animate attributeName=&#34;fill-opacity&#34; from=&#34;0.5&#34; to=&#34;0.5&#34;
                         begin=&#34;0s&#34; dur=&#34;0.8s&#34;
                         values=&#34;.5;1;.5&#34; calcMode=&#34;linear&#34;
                         repeatCount=&#34;indefinite&#34; /&gt;
            &lt;/circle&gt;
            &lt;circle cx=&#34;105&#34; cy=&#34;15&#34; r=&#34;15&#34;&gt;
                &lt;animate attributeName=&#34;r&#34; from=&#34;15&#34; to=&#34;15&#34;
                         begin=&#34;0s&#34; dur=&#34;0.8s&#34;
                         values=&#34;15;9;15&#34; calcMode=&#34;linear&#34;
                         repeatCount=&#34;indefinite&#34; /&gt;
                &lt;animate attributeName=&#34;fill-opacity&#34; from=&#34;1&#34; to=&#34;1&#34;
                         begin=&#34;0s&#34; dur=&#34;0.8s&#34;
                         values=&#34;1;.5;1&#34; calcMode=&#34;linear&#34;
                         repeatCount=&#34;indefinite&#34; /&gt;
            &lt;/circle&gt;
        &lt;/svg&gt;
      &lt;/slot&gt;
    &lt;/button&gt;
  &lt;/template&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ts&#34; data-lang=&#34;ts&#34;&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;template data-playground-id=&#34;mutation-factory&#34;
            data-filename=&#34;add-user.ts&#34;&gt;&lt;/template&gt;

  &lt;template data-playground-id=&#34;mutation-factory&#34;
            data-filename=&#34;add-user.css&#34;&gt;&lt;/template&gt;


  &lt;template data-playground-id=&#34;mutation-factory&#34;
            data-filename=&#34;AddUser.mutation.graphql.ts&#34;&gt;import type { User } from &amp;#39;./client&amp;#39;;
  import type { TypedDocumentNode } from &amp;#39;@apollo/client/core&amp;#39;;
  import { gql } from &amp;#39;@apollo/client/core&amp;#39;;
  export const AddUserMutation: TypedDocumentNode&amp;lt;{ addUser: User }, { name: String }&amp;gt; =  gql`
    mutation AddUserMutation($name: String)  {
      addUser(name: $name) {
        id
        name
      }
    }
  `;&lt;/template&gt;


  &lt;template data-playground-id=&#34;mutation-factory&#34;
            data-filename=&#34;index.html&#34;&gt;&amp;lt;script type=&amp;#34;module&amp;#34; src=&amp;#34;client.js&amp;#34;&amp;gt;&amp;lt;/script&amp;gt;
  &amp;lt;script type=&amp;#34;module&amp;#34; src=&amp;#34;users-list.js&amp;#34;&amp;gt;&amp;lt;/script&amp;gt;
  &amp;lt;users-list&amp;gt;&amp;lt;/users-list&amp;gt;&lt;/template&gt;


  &lt;template data-playground-id=&#34;mutation-factory&#34;
            data-filename=&#34;client.ts&#34;&gt;import type { InMemoryCacheConfig, NormalizedCacheObject } from &amp;#39;@apollo/client/core&amp;#39;;
  
  import { SchemaLink } from &amp;#39;@apollo/client/link/schema&amp;#39;;
  import { makeExecutableSchema } from &amp;#39;@graphql-tools/schema&amp;#39;;
  import { addMocksToSchema } from &amp;#39;@graphql-tools/mock&amp;#39;;
  
  import { ApolloClient, InMemoryCache, HttpLink } from &amp;#39;@apollo/client/core&amp;#39;;
  
  export interface User {
    id: string;
    name: string;
    status?: &amp;#39;DELETED&amp;#39;;
  };
  
  const typeDefs = `
    type User {
      name: String
      id: ID
    }
  
    type Query {
      users: [User]
    }
  
    type Mutation {
      addUser(name: String): User
      removeUser(id: ID): User
    }
  `;
  
  const USERS = [
    { id: 1, name: &amp;#39;Neil&amp;#39; }
  ];
  
  const randomDelay = () =&amp;gt;  new Promise(r =&amp;gt; setTimeout(r, Math.random() * 500));
  
  export const client = new ApolloClient({
    cache: new InMemoryCache(),
    link: new SchemaLink({
      schema: makeExecutableSchema({
        typeDefs,
        resolvers: {
          Query: {
            users() {
              return USERS.filter(x =&amp;gt; x.status !== &amp;#39;DELETED&amp;#39;);
            }
          },
          Mutation: {
            async addUser(_, { name }) {
              const user = { name, id: Math.max(...USERS.map(x =&amp;gt; x.id)) &amp;#43; 1 };
              USERS.push(user);
              await randomDelay()
              return user;
            },
            async removeUser(_, { id }) {
              const user = USERS.find(x =&amp;gt; x.id == parseInt(id));
              user.status = &amp;#39;DELETED&amp;#39;;
              await randomDelay();
              return user;
            }
          }
        }
      }),
    }),
  });
  
  window.__APOLLO_CLIENT__ = client;&lt;/template&gt;

&lt;/docs-playground&gt;</description>
      
      <content:encoded><![CDATA[<!-- ----------------------------------------------------------------------------------------
     Welcome! This file includes automatically generated API documentation.
     To edit the docs that appear within, find the original source file under `packages/*`,
     corresponding to the package name and module in this YAML front-matter block.
     Thank you for your interest in Apollo Elements 😁
------------------------------------------------------------------------------------------ -->
<p>Use the <code>mutation</code> factory to add a GraphQL mutation to you hybrids element.</p>
<docs-playground id="mutation-factory">
  <template shadowrootmode="open">
    <style>
      :host {
        display: block;
        box-sizing: border-box;
        position: relative;
        width: 100%;
        height: auto;
      }

      playground-ide {
        display: none;
        border: 0;
        overflow: hidden;

        --playground-code-font-family: monospace;
        --playground-code-font-size: 14px;
        --playground-border: none;
      }

      #snippet,
      playground-ide {
        width: 100%;
        height: 100%;
        border-radius: var(--playground-snippet-border-radius, 6px);
      }

      #snippet {
        display: block;
        box-sizing: border-box;
      }

      #snippet,
      button {
        border: 1px solid var(--playground-snippet-border-color, transparent);
        transition: border-color 0.2s ease-in-out;
        will-change: border-color;
      }

      :host([show]) playground-ide {
        display: flex;
        width: var(--playground-ide-width, 100%);
        height: var(--playground-ide-height, 600px);
      }

      button {
        background: var(--playground-snippet-button-background);
        border-end-end-radius: 6px;
        border-start-start-radius: 6px;
        color: inherit;
        cursor: pointer;
        display: block;
        font-size: 16px;
        outline: none;
        padding: 9px 16px;
        position: absolute;
        bottom: 0;
        right: -2px;
        transition:
          border-color 0.2s ease-in-out,
          background 0.1s ease,
          color 0.1s ease;
      }

      button:focus,
      button:hover {
        color: var(--playground-snippet-button-focus-color, var(--code-button-focus-color));
        background: var(--playground-snippet-button-focus-background, var(--code-button-focus-background));
        border-bottom-color: var(--playground-snippet-button-focus-background, var(--code-button-focus-background)) !important;
        border-right-color: var(--playground-snippet-button-focus-background, var(--code-button-focus-background)) !important;
      }

      :host([show]) #snippet,
      :host([show]) button {
        display: none;
      }

      :host(:not([show]):focus-within) #snippet,
      :host(:not([show]):hover) #snippet {
        border-color: var(--playground-snippet-focus-border-color, black);
      }

      :host(:not([show]):focus-within) button,
      :host(:not([show]):hover) button {
        border-top-color: var(--playground-snippet-focus-border-color, black);
        border-left-color: var(--playground-snippet-focus-border-color, black);
        border-bottom-color: var(--playground-snippet-outer-background-color, var(--page-background));
        border-right-color: var(--playground-snippet-outer-background-color, var(--page-background));
      }

      #snippet ::slotted(pre) {
        margin-bottom: 0 !important;
      }

      :host([loading]) #edit,
      #loading {
        display: none;
      }

      :host([loading]) #loading {
        display: inline-block;
      }
    </style>

    <div id="snippet"><slot></slot></div>

    <playground-ide part="playground-ide" exportparts="lhs,rhs"></playground-ide>

    <button part="button">
      <span id="edit">▶️ Edit Live</span>

      <slot name="loader">
        
        <svg id="loading" width="90" height="20" viewBox="0 0 120 30" xmlns="http://www.w3.org/2000/svg" fill="var(--primary-text-color)">
            <circle cx="15" cy="15" r="15">
                <animate attributeName="r" from="15" to="15"
                         begin="0s" dur="0.8s"
                         values="15;9;15" calcMode="linear"
                         repeatCount="indefinite" />
                <animate attributeName="fill-opacity" from="1" to="1"
                         begin="0s" dur="0.8s"
                         values="1;.5;1" calcMode="linear"
                         repeatCount="indefinite" />
            </circle>
            <circle cx="60" cy="15" r="9" fill-opacity="0.3">
                <animate attributeName="r" from="9" to="9"
                         begin="0s" dur="0.8s"
                         values="9;15;9" calcMode="linear"
                         repeatCount="indefinite" />
                <animate attributeName="fill-opacity" from="0.5" to="0.5"
                         begin="0s" dur="0.8s"
                         values=".5;1;.5" calcMode="linear"
                         repeatCount="indefinite" />
            </circle>
            <circle cx="105" cy="15" r="15">
                <animate attributeName="r" from="15" to="15"
                         begin="0s" dur="0.8s"
                         values="15;9;15" calcMode="linear"
                         repeatCount="indefinite" />
                <animate attributeName="fill-opacity" from="1" to="1"
                         begin="0s" dur="0.8s"
                         values="1;.5;1" calcMode="linear"
                         repeatCount="indefinite" />
            </circle>
        </svg>
      </slot>
    </button>
  </template><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ts" data-lang="ts"></code></pre></div>
  <template data-playground-id="mutation-factory"
            data-filename="add-user.ts"></template>

  <template data-playground-id="mutation-factory"
            data-filename="add-user.css"></template>


  <template data-playground-id="mutation-factory"
            data-filename="AddUser.mutation.graphql.ts">import type { User } from &#39;./client&#39;;
  import type { TypedDocumentNode } from &#39;@apollo/client/core&#39;;
  import { gql } from &#39;@apollo/client/core&#39;;
  export const AddUserMutation: TypedDocumentNode&lt;{ addUser: User }, { name: String }&gt; =  gql`
    mutation AddUserMutation($name: String)  {
      addUser(name: $name) {
        id
        name
      }
    }
  `;</template>


  <template data-playground-id="mutation-factory"
            data-filename="index.html">&lt;script type=&#34;module&#34; src=&#34;client.js&#34;&gt;&lt;/script&gt;
  &lt;script type=&#34;module&#34; src=&#34;users-list.js&#34;&gt;&lt;/script&gt;
  &lt;users-list&gt;&lt;/users-list&gt;</template>


  <template data-playground-id="mutation-factory"
            data-filename="client.ts">import type { InMemoryCacheConfig, NormalizedCacheObject } from &#39;@apollo/client/core&#39;;
  
  import { SchemaLink } from &#39;@apollo/client/link/schema&#39;;
  import { makeExecutableSchema } from &#39;@graphql-tools/schema&#39;;
  import { addMocksToSchema } from &#39;@graphql-tools/mock&#39;;
  
  import { ApolloClient, InMemoryCache, HttpLink } from &#39;@apollo/client/core&#39;;
  
  export interface User {
    id: string;
    name: string;
    status?: &#39;DELETED&#39;;
  };
  
  const typeDefs = `
    type User {
      name: String
      id: ID
    }
  
    type Query {
      users: [User]
    }
  
    type Mutation {
      addUser(name: String): User
      removeUser(id: ID): User
    }
  `;
  
  const USERS = [
    { id: 1, name: &#39;Neil&#39; }
  ];
  
  const randomDelay = () =&gt;  new Promise(r =&gt; setTimeout(r, Math.random() * 500));
  
  export const client = new ApolloClient({
    cache: new InMemoryCache(),
    link: new SchemaLink({
      schema: makeExecutableSchema({
        typeDefs,
        resolvers: {
          Query: {
            users() {
              return USERS.filter(x =&gt; x.status !== &#39;DELETED&#39;);
            }
          },
          Mutation: {
            async addUser(_, { name }) {
              const user = { name, id: Math.max(...USERS.map(x =&gt; x.id)) &#43; 1 };
              USERS.push(user);
              await randomDelay()
              return user;
            },
            async removeUser(_, { id }) {
              const user = USERS.find(x =&gt; x.id == parseInt(id));
              user.status = &#39;DELETED&#39;;
              await randomDelay();
              return user;
            }
          }
        }
      }),
    }),
  });
  
  window.__APOLLO_CLIENT__ = client;</template>

</docs-playground>

]]></content:encoded>
    </item><item>
      <title>polymer-apollo-mutation</title>
      <link>https://apolloelements.dev/api/libraries/polymer/apollo-mutation/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/api/libraries/polymer/apollo-mutation/</guid>
      <description>&lt;!-- ----------------------------------------------------------------------------------------
     Welcome! This file includes automatically generated API documentation.
     To edit the docs that appear within, find the original source file under `packages/*`,
     corresponding to the package name and module in this YAML front-matter block.
     Thank you for your interest in Apollo Elements 😁
------------------------------------------------------------------------------------------ --&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;apollo-mutation&amp;gt;&lt;/code&gt; fires Polymer-style prop-changed events when its &lt;code&gt;called&lt;/code&gt;, &lt;code&gt;data&lt;/code&gt;, &lt;code&gt;error&lt;/code&gt;, or &lt;code&gt;loading&lt;/code&gt; properties change.&lt;/p&gt;
&lt;p&gt;See &lt;a href=&#34;https://apolloelements.dev/api/core/interfaces/mutation/&#34;&gt;ApolloMutationInterface&lt;/a&gt; for more information.&lt;/p&gt;
&lt;docs-playground id=&#34;polymer-apollo&#34;&gt;
  &lt;template shadowrootmode=&#34;open&#34;&gt;
    &lt;style&gt;
      :host {
        display: block;
        box-sizing: border-box;
        position: relative;
        width: 100%;
        height: auto;
      }

      playground-ide {
        display: none;
        border: 0;
        overflow: hidden;

        --playground-code-font-family: monospace;
        --playground-code-font-size: 14px;
        --playground-border: none;
      }

      #snippet,
      playground-ide {
        width: 100%;
        height: 100%;
        border-radius: var(--playground-snippet-border-radius, 6px);
      }

      #snippet {
        display: block;
        box-sizing: border-box;
      }

      #snippet,
      button {
        border: 1px solid var(--playground-snippet-border-color, transparent);
        transition: border-color 0.2s ease-in-out;
        will-change: border-color;
      }

      :host([show]) playground-ide {
        display: flex;
        width: var(--playground-ide-width, 100%);
        height: var(--playground-ide-height, 600px);
      }

      button {
        background: var(--playground-snippet-button-background);
        border-end-end-radius: 6px;
        border-start-start-radius: 6px;
        color: inherit;
        cursor: pointer;
        display: block;
        font-size: 16px;
        outline: none;
        padding: 9px 16px;
        position: absolute;
        bottom: 0;
        right: -2px;
        transition:
          border-color 0.2s ease-in-out,
          background 0.1s ease,
          color 0.1s ease;
      }

      button:focus,
      button:hover {
        color: var(--playground-snippet-button-focus-color, var(--code-button-focus-color));
        background: var(--playground-snippet-button-focus-background, var(--code-button-focus-background));
        border-bottom-color: var(--playground-snippet-button-focus-background, var(--code-button-focus-background)) !important;
        border-right-color: var(--playground-snippet-button-focus-background, var(--code-button-focus-background)) !important;
      }

      :host([show]) #snippet,
      :host([show]) button {
        display: none;
      }

      :host(:not([show]):focus-within) #snippet,
      :host(:not([show]):hover) #snippet {
        border-color: var(--playground-snippet-focus-border-color, black);
      }

      :host(:not([show]):focus-within) button,
      :host(:not([show]):hover) button {
        border-top-color: var(--playground-snippet-focus-border-color, black);
        border-left-color: var(--playground-snippet-focus-border-color, black);
        border-bottom-color: var(--playground-snippet-outer-background-color, var(--page-background));
        border-right-color: var(--playground-snippet-outer-background-color, var(--page-background));
      }

      #snippet ::slotted(pre) {
        margin-bottom: 0 !important;
      }

      :host([loading]) #edit,
      #loading {
        display: none;
      }

      :host([loading]) #loading {
        display: inline-block;
      }
    &lt;/style&gt;

    &lt;div id=&#34;snippet&#34;&gt;&lt;slot&gt;&lt;/slot&gt;&lt;/div&gt;

    &lt;playground-ide part=&#34;playground-ide&#34; exportparts=&#34;lhs,rhs&#34;&gt;&lt;/playground-ide&gt;

    &lt;button part=&#34;button&#34;&gt;
      &lt;span id=&#34;edit&#34;&gt;▶️ Edit Live&lt;/span&gt;

      &lt;slot name=&#34;loader&#34;&gt;
        
        &lt;svg id=&#34;loading&#34; width=&#34;90&#34; height=&#34;20&#34; viewBox=&#34;0 0 120 30&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34; fill=&#34;var(--primary-text-color)&#34;&gt;
            &lt;circle cx=&#34;15&#34; cy=&#34;15&#34; r=&#34;15&#34;&gt;
                &lt;animate attributeName=&#34;r&#34; from=&#34;15&#34; to=&#34;15&#34;
                         begin=&#34;0s&#34; dur=&#34;0.8s&#34;
                         values=&#34;15;9;15&#34; calcMode=&#34;linear&#34;
                         repeatCount=&#34;indefinite&#34; /&gt;
                &lt;animate attributeName=&#34;fill-opacity&#34; from=&#34;1&#34; to=&#34;1&#34;
                         begin=&#34;0s&#34; dur=&#34;0.8s&#34;
                         values=&#34;1;.5;1&#34; calcMode=&#34;linear&#34;
                         repeatCount=&#34;indefinite&#34; /&gt;
            &lt;/circle&gt;
            &lt;circle cx=&#34;60&#34; cy=&#34;15&#34; r=&#34;9&#34; fill-opacity=&#34;0.3&#34;&gt;
                &lt;animate attributeName=&#34;r&#34; from=&#34;9&#34; to=&#34;9&#34;
                         begin=&#34;0s&#34; dur=&#34;0.8s&#34;
                         values=&#34;9;15;9&#34; calcMode=&#34;linear&#34;
                         repeatCount=&#34;indefinite&#34; /&gt;
                &lt;animate attributeName=&#34;fill-opacity&#34; from=&#34;0.5&#34; to=&#34;0.5&#34;
                         begin=&#34;0s&#34; dur=&#34;0.8s&#34;
                         values=&#34;.5;1;.5&#34; calcMode=&#34;linear&#34;
                         repeatCount=&#34;indefinite&#34; /&gt;
            &lt;/circle&gt;
            &lt;circle cx=&#34;105&#34; cy=&#34;15&#34; r=&#34;15&#34;&gt;
                &lt;animate attributeName=&#34;r&#34; from=&#34;15&#34; to=&#34;15&#34;
                         begin=&#34;0s&#34; dur=&#34;0.8s&#34;
                         values=&#34;15;9;15&#34; calcMode=&#34;linear&#34;
                         repeatCount=&#34;indefinite&#34; /&gt;
                &lt;animate attributeName=&#34;fill-opacity&#34; from=&#34;1&#34; to=&#34;1&#34;
                         begin=&#34;0s&#34; dur=&#34;0.8s&#34;
                         values=&#34;1;.5;1&#34; calcMode=&#34;linear&#34;
                         repeatCount=&#34;indefinite&#34; /&gt;
            &lt;/circle&gt;
        &lt;/svg&gt;
      &lt;/slot&gt;
    &lt;/button&gt;
  &lt;/template&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;PolymerElement&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;html&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;@polymer/polymer&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;AddUserMutation&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;./Hello.query.graphql.js&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;./elements.js&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;AddUserMutationElement&lt;/span&gt; &lt;span class=&#34;kr&#34;&gt;extends&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;PolymerElement&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;kr&#34;&gt;static&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;get&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;template&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;html&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;`
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;      &amp;lt;polymer-apollo-mutation id=&amp;#34;userMutation&amp;#34; data=&amp;#34;{{data}}&amp;#34; mutation=&amp;#34;[[mutation]]&amp;#34;&amp;gt;&amp;lt;/polymer-apollo-mutation&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;      &amp;lt;p-card&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;        &amp;lt;h2 slot=&amp;#34;heading&amp;#34;&amp;gt;Add a User&amp;lt;/h2&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;        &amp;lt;paper-input hidden=&amp;#34;[[data]]&amp;#34; label=&amp;#34;Name&amp;#34; value=&amp;#34;{{name}}&amp;#34;&amp;gt;&amp;lt;/paper-input&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;        &amp;lt;paper-button slot=&amp;#34;actions&amp;#34; hidden=&amp;#34;[[data]]&amp;#34; on-click=&amp;#34;mutate&amp;#34;&amp;gt;Submit&amp;lt;/paper-button&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;        &amp;lt;p hidden=&amp;#34;[[!data]]&amp;#34;&amp;gt;[[data.insertUsers.returning.0.name]] added!&amp;lt;/p&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;      &amp;lt;/p-card&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;    `&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;kr&#34;&gt;static&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;get&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;properties&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nx&#34;&gt;mutation&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;Object&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;AddUserMutation&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;mutate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;name&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;this&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;this&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;userMutation&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;mutate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;({&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;variables&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;name&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;customElements&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;define&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;add-user&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;AddUserMutationElement&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;template data-playground-id=&#34;polymer-apollo&#34;
            data-filename=&#34;AddUser.js&#34;&gt;import { PolymerElement, html } from &amp;#39;@polymer/polymer&amp;#39;;
  import { AddUserMutation } from &amp;#39;./Hello.query.graphql.js&amp;#39;;
  import &amp;#39;./elements.js&amp;#39;;
  
  class AddUserMutationElement extends PolymerElement {
    static get template() {
      return html`
        &amp;lt;polymer-apollo-mutation id=&amp;#34;userMutation&amp;#34; data=&amp;#34;{{data}}&amp;#34; mutation=&amp;#34;[[mutation]]&amp;#34;&amp;gt;&amp;lt;/polymer-apollo-mutation&amp;gt;
  
        &amp;lt;p-card&amp;gt;
          &amp;lt;h2 slot=&amp;#34;heading&amp;#34;&amp;gt;Add a User&amp;lt;/h2&amp;gt;
          &amp;lt;paper-input hidden=&amp;#34;[[data]]&amp;#34; label=&amp;#34;Name&amp;#34; value=&amp;#34;{{name}}&amp;#34;&amp;gt;&amp;lt;/paper-input&amp;gt;
          &amp;lt;paper-button slot=&amp;#34;actions&amp;#34; hidden=&amp;#34;[[data]]&amp;#34; on-click=&amp;#34;mutate&amp;#34;&amp;gt;Submit&amp;lt;/paper-button&amp;gt;
          &amp;lt;p hidden=&amp;#34;[[!data]]&amp;#34;&amp;gt;[[data.insertUsers.returning.0.name]] added!&amp;lt;/p&amp;gt;
        &amp;lt;/p-card&amp;gt;
      `;
    }
  
    static get properties() {
      return {
        mutation: { type: Object, value: () =&amp;gt; AddUserMutation },
      };
    }
  
    mutate() {
      const { name } = this;
      return this.$.userMutation.mutate({ variables: { name } });
    }
  }
  
  customElements.define(&amp;#39;add-user&amp;#39;, AddUserMutationElement);&lt;/template&gt;

  &lt;template data-playground-id=&#34;polymer-apollo&#34;
            data-filename=&#34;Hello.query.graphql.js&#34;&gt;import { gql } from &amp;#39;@apollo/client/core&amp;#39;;
  export const HelloQuery = gql`
    query HelloQuery($name: String, $greeting: String) {
      hello(name: $name, greeting: $greeting) {
        name
        greeting
      }
    }
  `;&lt;/template&gt;


  &lt;template data-playground-id=&#34;polymer-apollo&#34;
            data-filename=&#34;index.html&#34;&gt;&amp;lt;script type=&amp;#34;module&amp;#34; src=&amp;#34;client.js&amp;#34;&amp;gt;&amp;lt;/script&amp;gt;
  &amp;lt;script type=&amp;#34;module&amp;#34; src=&amp;#34;Hello.js&amp;#34;&amp;gt;&amp;lt;/script&amp;gt;
  
  &amp;lt;apollo-client&amp;gt;
    &amp;lt;hello-query&amp;gt;&amp;lt;/hello-query&amp;gt;
  &amp;lt;/apollo-client&amp;gt;&lt;/template&gt;


  &lt;template data-playground-id=&#34;polymer-apollo&#34;
            data-filename=&#34;elements.js&#34;&gt;import &amp;#39;@apollo-elements/components/apollo-client&amp;#39;;
  import &amp;#39;@apollo-elements/polymer/polymer-apollo-mutation&amp;#39;;
  import &amp;#39;@polymer/paper-button/paper-button&amp;#39;
  import &amp;#39;@polymer/paper-input/paper-input&amp;#39;;
  import &amp;#39;@power-elements/card&amp;#39;;&lt;/template&gt;

&lt;/docs-playground&gt;</description>
      
      <content:encoded><![CDATA[<!-- ----------------------------------------------------------------------------------------
     Welcome! This file includes automatically generated API documentation.
     To edit the docs that appear within, find the original source file under `packages/*`,
     corresponding to the package name and module in this YAML front-matter block.
     Thank you for your interest in Apollo Elements 😁
------------------------------------------------------------------------------------------ -->
<p><code>&lt;apollo-mutation&gt;</code> fires Polymer-style prop-changed events when its <code>called</code>, <code>data</code>, <code>error</code>, or <code>loading</code> properties change.</p>
<p>See <a href="/api/core/interfaces/mutation/">ApolloMutationInterface</a> for more information.</p>
<docs-playground id="polymer-apollo">
  <template shadowrootmode="open">
    <style>
      :host {
        display: block;
        box-sizing: border-box;
        position: relative;
        width: 100%;
        height: auto;
      }

      playground-ide {
        display: none;
        border: 0;
        overflow: hidden;

        --playground-code-font-family: monospace;
        --playground-code-font-size: 14px;
        --playground-border: none;
      }

      #snippet,
      playground-ide {
        width: 100%;
        height: 100%;
        border-radius: var(--playground-snippet-border-radius, 6px);
      }

      #snippet {
        display: block;
        box-sizing: border-box;
      }

      #snippet,
      button {
        border: 1px solid var(--playground-snippet-border-color, transparent);
        transition: border-color 0.2s ease-in-out;
        will-change: border-color;
      }

      :host([show]) playground-ide {
        display: flex;
        width: var(--playground-ide-width, 100%);
        height: var(--playground-ide-height, 600px);
      }

      button {
        background: var(--playground-snippet-button-background);
        border-end-end-radius: 6px;
        border-start-start-radius: 6px;
        color: inherit;
        cursor: pointer;
        display: block;
        font-size: 16px;
        outline: none;
        padding: 9px 16px;
        position: absolute;
        bottom: 0;
        right: -2px;
        transition:
          border-color 0.2s ease-in-out,
          background 0.1s ease,
          color 0.1s ease;
      }

      button:focus,
      button:hover {
        color: var(--playground-snippet-button-focus-color, var(--code-button-focus-color));
        background: var(--playground-snippet-button-focus-background, var(--code-button-focus-background));
        border-bottom-color: var(--playground-snippet-button-focus-background, var(--code-button-focus-background)) !important;
        border-right-color: var(--playground-snippet-button-focus-background, var(--code-button-focus-background)) !important;
      }

      :host([show]) #snippet,
      :host([show]) button {
        display: none;
      }

      :host(:not([show]):focus-within) #snippet,
      :host(:not([show]):hover) #snippet {
        border-color: var(--playground-snippet-focus-border-color, black);
      }

      :host(:not([show]):focus-within) button,
      :host(:not([show]):hover) button {
        border-top-color: var(--playground-snippet-focus-border-color, black);
        border-left-color: var(--playground-snippet-focus-border-color, black);
        border-bottom-color: var(--playground-snippet-outer-background-color, var(--page-background));
        border-right-color: var(--playground-snippet-outer-background-color, var(--page-background));
      }

      #snippet ::slotted(pre) {
        margin-bottom: 0 !important;
      }

      :host([loading]) #edit,
      #loading {
        display: none;
      }

      :host([loading]) #loading {
        display: inline-block;
      }
    </style>

    <div id="snippet"><slot></slot></div>

    <playground-ide part="playground-ide" exportparts="lhs,rhs"></playground-ide>

    <button part="button">
      <span id="edit">▶️ Edit Live</span>

      <slot name="loader">
        
        <svg id="loading" width="90" height="20" viewBox="0 0 120 30" xmlns="http://www.w3.org/2000/svg" fill="var(--primary-text-color)">
            <circle cx="15" cy="15" r="15">
                <animate attributeName="r" from="15" to="15"
                         begin="0s" dur="0.8s"
                         values="15;9;15" calcMode="linear"
                         repeatCount="indefinite" />
                <animate attributeName="fill-opacity" from="1" to="1"
                         begin="0s" dur="0.8s"
                         values="1;.5;1" calcMode="linear"
                         repeatCount="indefinite" />
            </circle>
            <circle cx="60" cy="15" r="9" fill-opacity="0.3">
                <animate attributeName="r" from="9" to="9"
                         begin="0s" dur="0.8s"
                         values="9;15;9" calcMode="linear"
                         repeatCount="indefinite" />
                <animate attributeName="fill-opacity" from="0.5" to="0.5"
                         begin="0s" dur="0.8s"
                         values=".5;1;.5" calcMode="linear"
                         repeatCount="indefinite" />
            </circle>
            <circle cx="105" cy="15" r="15">
                <animate attributeName="r" from="15" to="15"
                         begin="0s" dur="0.8s"
                         values="15;9;15" calcMode="linear"
                         repeatCount="indefinite" />
                <animate attributeName="fill-opacity" from="1" to="1"
                         begin="0s" dur="0.8s"
                         values="1;.5;1" calcMode="linear"
                         repeatCount="indefinite" />
            </circle>
        </svg>
      </slot>
    </button>
  </template><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">PolymerElement</span><span class="p">,</span> <span class="nx">html</span> <span class="p">}</span> <span class="nx">from</span> <span class="s1">&#39;@polymer/polymer&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">AddUserMutation</span> <span class="p">}</span> <span class="nx">from</span> <span class="s1">&#39;./Hello.query.graphql.js&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="s1">&#39;./elements.js&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">class</span> <span class="nx">AddUserMutationElement</span> <span class="kr">extends</span> <span class="nx">PolymerElement</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="kr">static</span> <span class="nx">get</span> <span class="nx">template</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="nx">html</span><span class="sb">`
</span></span></span><span class="line"><span class="cl"><span class="sb">      &lt;polymer-apollo-mutation id=&#34;userMutation&#34; data=&#34;{{data}}&#34; mutation=&#34;[[mutation]]&#34;&gt;&lt;/polymer-apollo-mutation&gt;
</span></span></span><span class="line"><span class="cl"><span class="sb">
</span></span></span><span class="line"><span class="cl"><span class="sb">      &lt;p-card&gt;
</span></span></span><span class="line"><span class="cl"><span class="sb">        &lt;h2 slot=&#34;heading&#34;&gt;Add a User&lt;/h2&gt;
</span></span></span><span class="line"><span class="cl"><span class="sb">        &lt;paper-input hidden=&#34;[[data]]&#34; label=&#34;Name&#34; value=&#34;{{name}}&#34;&gt;&lt;/paper-input&gt;
</span></span></span><span class="line"><span class="cl"><span class="sb">        &lt;paper-button slot=&#34;actions&#34; hidden=&#34;[[data]]&#34; on-click=&#34;mutate&#34;&gt;Submit&lt;/paper-button&gt;
</span></span></span><span class="line"><span class="cl"><span class="sb">        &lt;p hidden=&#34;[[!data]]&#34;&gt;[[data.insertUsers.returning.0.name]] added!&lt;/p&gt;
</span></span></span><span class="line"><span class="cl"><span class="sb">      &lt;/p-card&gt;
</span></span></span><span class="line"><span class="cl"><span class="sb">    `</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="kr">static</span> <span class="nx">get</span> <span class="nx">properties</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nx">mutation</span><span class="o">:</span> <span class="p">{</span> <span class="nx">type</span><span class="o">:</span> <span class="nb">Object</span><span class="p">,</span> <span class="nx">value</span><span class="o">:</span> <span class="p">()</span> <span class="p">=&gt;</span> <span class="nx">AddUserMutation</span> <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="nx">mutate</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kr">const</span> <span class="p">{</span> <span class="nx">name</span> <span class="p">}</span> <span class="o">=</span> <span class="k">this</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">$</span><span class="p">.</span><span class="nx">userMutation</span><span class="p">.</span><span class="nx">mutate</span><span class="p">({</span> <span class="nx">variables</span><span class="o">:</span> <span class="p">{</span> <span class="nx">name</span> <span class="p">}</span> <span class="p">});</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nx">customElements</span><span class="p">.</span><span class="nx">define</span><span class="p">(</span><span class="s1">&#39;add-user&#39;</span><span class="p">,</span> <span class="nx">AddUserMutationElement</span><span class="p">);</span></span></span></code></pre></div>
  <template data-playground-id="polymer-apollo"
            data-filename="AddUser.js">import { PolymerElement, html } from &#39;@polymer/polymer&#39;;
  import { AddUserMutation } from &#39;./Hello.query.graphql.js&#39;;
  import &#39;./elements.js&#39;;
  
  class AddUserMutationElement extends PolymerElement {
    static get template() {
      return html`
        &lt;polymer-apollo-mutation id=&#34;userMutation&#34; data=&#34;{{data}}&#34; mutation=&#34;[[mutation]]&#34;&gt;&lt;/polymer-apollo-mutation&gt;
  
        &lt;p-card&gt;
          &lt;h2 slot=&#34;heading&#34;&gt;Add a User&lt;/h2&gt;
          &lt;paper-input hidden=&#34;[[data]]&#34; label=&#34;Name&#34; value=&#34;{{name}}&#34;&gt;&lt;/paper-input&gt;
          &lt;paper-button slot=&#34;actions&#34; hidden=&#34;[[data]]&#34; on-click=&#34;mutate&#34;&gt;Submit&lt;/paper-button&gt;
          &lt;p hidden=&#34;[[!data]]&#34;&gt;[[data.insertUsers.returning.0.name]] added!&lt;/p&gt;
        &lt;/p-card&gt;
      `;
    }
  
    static get properties() {
      return {
        mutation: { type: Object, value: () =&gt; AddUserMutation },
      };
    }
  
    mutate() {
      const { name } = this;
      return this.$.userMutation.mutate({ variables: { name } });
    }
  }
  
  customElements.define(&#39;add-user&#39;, AddUserMutationElement);</template>

  <template data-playground-id="polymer-apollo"
            data-filename="Hello.query.graphql.js">import { gql } from &#39;@apollo/client/core&#39;;
  export const HelloQuery = gql`
    query HelloQuery($name: String, $greeting: String) {
      hello(name: $name, greeting: $greeting) {
        name
        greeting
      }
    }
  `;</template>


  <template data-playground-id="polymer-apollo"
            data-filename="index.html">&lt;script type=&#34;module&#34; src=&#34;client.js&#34;&gt;&lt;/script&gt;
  &lt;script type=&#34;module&#34; src=&#34;Hello.js&#34;&gt;&lt;/script&gt;
  
  &lt;apollo-client&gt;
    &lt;hello-query&gt;&lt;/hello-query&gt;
  &lt;/apollo-client&gt;</template>


  <template data-playground-id="polymer-apollo"
            data-filename="elements.js">import &#39;@apollo-elements/components/apollo-client&#39;;
  import &#39;@apollo-elements/polymer/polymer-apollo-mutation&#39;;
  import &#39;@polymer/paper-button/paper-button&#39;
  import &#39;@polymer/paper-input/paper-input&#39;;
  import &#39;@power-elements/card&#39;;</template>

</docs-playground>

]]></content:encoded>
    </item><item>
      <title>ApolloMutation</title>
      <link>https://apolloelements.dev/api/libraries/gluon/apollo-mutation/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/api/libraries/gluon/apollo-mutation/</guid>
      <description>&lt;!-- ----------------------------------------------------------------------------------------
     Welcome! This file includes automatically generated API documentation.
     To edit the docs that appear within, find the original source file under `packages/*`,
     corresponding to the package name and module in this YAML front-matter block.
     Thank you for your interest in Apollo Elements 😁
------------------------------------------------------------------------------------------ --&gt;
&lt;p&gt;&lt;code&gt;ApolloMutation&lt;/code&gt; inherits from &lt;code&gt;ApolloElement&lt;/code&gt; and implements the &lt;a href=&#34;https://apolloelements.dev/api/core/interfaces/mutation/&#34;&gt;&lt;code&gt;ApolloMutationInterface&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Read the &lt;a href=&#34;../../../../guides/usage/mutations/&#34;&gt;mutation component guides&lt;/a&gt; for examples and tips.&lt;/p&gt;</description>
      
      <content:encoded><![CDATA[<!-- ----------------------------------------------------------------------------------------
     Welcome! This file includes automatically generated API documentation.
     To edit the docs that appear within, find the original source file under `packages/*`,
     corresponding to the package name and module in this YAML front-matter block.
     Thank you for your interest in Apollo Elements 😁
------------------------------------------------------------------------------------------ -->
<p><code>ApolloMutation</code> inherits from <code>ApolloElement</code> and implements the <a href="/api/core/interfaces/mutation/"><code>ApolloMutationInterface</code></a>.</p>
<p>Read the <a href="../../../../guides/usage/mutations/">mutation component guides</a> for examples and tips.</p>
]]></content:encoded>
    </item><item>
      <title>ApolloMutation</title>
      <link>https://apolloelements.dev/api/libraries/lit-apollo/apollo-mutation/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/api/libraries/lit-apollo/apollo-mutation/</guid>
      <description>&lt;!-- ----------------------------------------------------------------------------------------
     Welcome! This file includes automatically generated API documentation.
     To edit the docs that appear within, find the original source file under `packages/*`,
     corresponding to the package name and module in this YAML front-matter block.
     Thank you for your interest in Apollo Elements 😁
------------------------------------------------------------------------------------------ --&gt;
&lt;inline-notification type=&#34;tip&#34;&gt;
&lt;p&gt;Looking for reactive Apollo controllers? See &lt;a href=&#34;https://apolloelements.dev/api/core/&#34;&gt;&lt;code&gt;@apollo-elements/core&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/inline-notification&gt;
&lt;p&gt;&lt;code&gt;ApolloMutation&lt;/code&gt; inherits from &lt;code&gt;ApolloElement&lt;/code&gt; and implements the &lt;a href=&#34;https://apolloelements.dev/api/core/interfaces/mutation/&#34;&gt;&lt;code&gt;ApolloMutationInterface&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Read the &lt;a href=&#34;../../../../guides/usage/mutations/&#34;&gt;mutation component guides&lt;/a&gt; for examples and tips.&lt;/p&gt;</description>
      
      <content:encoded><![CDATA[<!-- ----------------------------------------------------------------------------------------
     Welcome! This file includes automatically generated API documentation.
     To edit the docs that appear within, find the original source file under `packages/*`,
     corresponding to the package name and module in this YAML front-matter block.
     Thank you for your interest in Apollo Elements 😁
------------------------------------------------------------------------------------------ -->
<inline-notification type="tip">
<p>Looking for reactive Apollo controllers? See <a href="/api/core/"><code>@apollo-elements/core</code></a></p>
</inline-notification>
<p><code>ApolloMutation</code> inherits from <code>ApolloElement</code> and implements the <a href="/api/core/interfaces/mutation/"><code>ApolloMutationInterface</code></a>.</p>
<p>Read the <a href="../../../../guides/usage/mutations/">mutation component guides</a> for examples and tips.</p>
]]></content:encoded>
    </item><item>
      <title>ApolloMutationMixin</title>
      <link>https://apolloelements.dev/api/libraries/mixins/apollo-mutation-mixin/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/api/libraries/mixins/apollo-mutation-mixin/</guid>
      <description>&lt;!-- ----------------------------------------------------------------------------------------
     Welcome! This file includes automatically generated API documentation.
     To edit the docs that appear within, find the original source file under `packages/*`,
     corresponding to the package name and module in this YAML front-matter block.
     Thank you for your interest in Apollo Elements 😁
------------------------------------------------------------------------------------------ --&gt;
&lt;p&gt;&lt;code&gt;ApolloMutationMixins&lt;/code&gt; applies &lt;code&gt;ApolloElementMixin&lt;/code&gt; and the &lt;a href=&#34;https://apolloelements.dev/api/core/interfaces/mutation/&#34;&gt;&lt;code&gt;ApolloMutationInterface&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Read the &lt;a href=&#34;https://apolloelements.dev/guides/usage/mutations/&#34;&gt;mutation component guides&lt;/a&gt; for examples and tips.&lt;/p&gt;</description>
      
      <content:encoded><![CDATA[<!-- ----------------------------------------------------------------------------------------
     Welcome! This file includes automatically generated API documentation.
     To edit the docs that appear within, find the original source file under `packages/*`,
     corresponding to the package name and module in this YAML front-matter block.
     Thank you for your interest in Apollo Elements 😁
------------------------------------------------------------------------------------------ -->
<p><code>ApolloMutationMixins</code> applies <code>ApolloElementMixin</code> and the <a href="/api/core/interfaces/mutation/"><code>ApolloMutationInterface</code></a>.</p>
<p>Read the <a href="/guides/usage/mutations/">mutation component guides</a> for examples and tips.</p>
]]></content:encoded>
    </item><item>
      <title>From Apollo Client 3.0</title>
      <link>https://apolloelements.dev/guides/getting-started/migrating/apollo-client-3/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/guides/getting-started/migrating/apollo-client-3/</guid>
      <description>&lt;p&gt;Apollo Elements 4 updates to Apollo Client 4 and includes one breaking change to subscriptions. This guide will help you migrate your app from Apollo Elements 3 to 4.&lt;/p&gt;
&lt;h2 id=&#34;apollo-elements-breaking-changes&#34;&gt;Apollo Elements Breaking Changes&lt;/h2&gt;
&lt;h3 id=&#34;subscription-error-handling&#34;&gt;Subscription Error Handling&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;This is the main breaking change in Apollo Elements 4.&lt;/strong&gt; Subscription controllers no longer maintain an &lt;code&gt;errors&lt;/code&gt; (plural) array. Subscriptions now only use the &lt;code&gt;error&lt;/code&gt; (singular) field, matching Apollo Client&amp;rsquo;s &lt;code&gt;useSubscription&lt;/code&gt; behavior.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Before (Apollo Elements 3):&lt;/strong&gt;&lt;/p&gt;</description>
      
      <content:encoded><![CDATA[<p>Apollo Elements 4 updates to Apollo Client 4 and includes one breaking change to subscriptions. This guide will help you migrate your app from Apollo Elements 3 to 4.</p>
<h2 id="apollo-elements-breaking-changes">Apollo Elements Breaking Changes</h2>
<h3 id="subscription-error-handling">Subscription Error Handling</h3>
<p><strong>This is the main breaking change in Apollo Elements 4.</strong> Subscription controllers no longer maintain an <code>errors</code> (plural) array. Subscriptions now only use the <code>error</code> (singular) field, matching Apollo Client&rsquo;s <code>useSubscription</code> behavior.</p>
<p><strong>Before (Apollo Elements 3):</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-typescript" data-lang="typescript"><span class="line"><span class="cl"><span class="kr">class</span> <span class="nx">MyElement</span> <span class="kr">extends</span> <span class="nx">LitElement</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">subscription</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">ApolloSubscriptionController</span><span class="p">(</span><span class="k">this</span><span class="p">,</span> <span class="nx">MessageSubscription</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="nx">render() {</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// ❌ No longer available
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="k">if</span> <span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">subscription</span><span class="p">.</span><span class="nx">errors</span><span class="o">?</span><span class="p">.</span><span class="nx">length</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="k">return</span> <span class="nx">html</span><span class="sb">`&lt;p&gt;Errors: </span><span class="si">${</span><span class="k">this</span><span class="p">.</span><span class="nx">subscription</span><span class="p">.</span><span class="nx">errors</span><span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="nx">e</span> <span class="o">=&gt;</span> <span class="nx">e</span><span class="p">.</span><span class="nx">message</span><span class="p">).</span><span class="nx">join</span><span class="p">(</span><span class="s1">&#39;, &#39;</span><span class="p">)</span><span class="si">}</span><span class="sb">&lt;/p&gt;`</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="nx">html</span><span class="sb">`&lt;p&gt;</span><span class="si">${</span><span class="k">this</span><span class="p">.</span><span class="nx">subscription</span><span class="p">.</span><span class="nx">data</span><span class="o">?</span><span class="p">.</span><span class="nx">message</span><span class="si">}</span><span class="sb">&lt;/p&gt;`</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p><strong>After (Apollo Elements 4):</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-typescript" data-lang="typescript"><span class="line"><span class="cl"><span class="kr">class</span> <span class="nx">MyElement</span> <span class="kr">extends</span> <span class="nx">LitElement</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">subscription</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">ApolloSubscriptionController</span><span class="p">(</span><span class="k">this</span><span class="p">,</span> <span class="nx">MessageSubscription</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="nx">render() {</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// ✅ Use singular error instead
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="k">if</span> <span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">subscription</span><span class="p">.</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="k">return</span> <span class="nx">html</span><span class="sb">`&lt;p&gt;Error: </span><span class="si">${</span><span class="k">this</span><span class="p">.</span><span class="nx">subscription</span><span class="p">.</span><span class="nx">error</span><span class="p">.</span><span class="nx">message</span><span class="si">}</span><span class="sb">&lt;/p&gt;`</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="nx">html</span><span class="sb">`&lt;p&gt;</span><span class="si">${</span><span class="k">this</span><span class="p">.</span><span class="nx">subscription</span><span class="p">.</span><span class="nx">data</span><span class="o">?</span><span class="p">.</span><span class="nx">message</span><span class="si">}</span><span class="sb">&lt;/p&gt;`</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p><strong>Migration:</strong> If you&rsquo;re reading <code>subscription.errors</code>, replace it with <code>subscription.error</code>.</p>
<h2 id="environment-requirements">Environment Requirements</h2>
<h3 id="nodejs-24">Node.js 24</h3>
<p>Apollo Elements 4 requires Node.js 24 or higher (previously 18.x):</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">node --version  <span class="c1"># Should be 24.x or higher</span>
</span></span></code></pre></div><h3 id="typescript-47">TypeScript 4.7</h3>
<p>If you use TypeScript, you&rsquo;ll need version 4.7 or higher:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">npm install --save-dev typescript@^4.7.0
</span></span></code></pre></div><h2 id="apollo-client-4-dependency">Apollo Client 4 Dependency</h2>
<p>Apollo Elements 4 depends on Apollo Client 4. Update your dependency:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">npm install @apollo/client@^4.0.6
</span></span></code></pre></div><p>Most Apollo Client 4 changes are internal and won&rsquo;t affect Apollo Elements users. However, if you use the cache API directly, note these changes:</p>
<h3 id="removed-inmemorycachewritedata">Removed <code>InMemoryCache.writeData</code></h3>
<p>The deprecated <code>writeData</code> method has been removed. Use <code>writeQuery</code>, <code>writeFragment</code>, or <code>cache.modify</code> instead:</p>
<p><strong>Before:</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-typescript" data-lang="typescript"><span class="line"><span class="cl"><span class="nx">cache</span><span class="p">.</span><span class="nx">writeData</span><span class="p">({</span>
</span></span><span class="line"><span class="cl">  <span class="nx">data</span><span class="o">:</span> <span class="p">{</span> <span class="nx">user</span><span class="o">:</span> <span class="p">{</span> <span class="nx">id</span><span class="o">:</span> <span class="s2">&#34;1&#34;</span><span class="p">,</span> <span class="nx">name</span><span class="o">:</span> <span class="s2">&#34;Alice&#34;</span> <span class="p">}</span> <span class="p">},</span>
</span></span><span class="line"><span class="cl"><span class="p">});</span>
</span></span></code></pre></div><p><strong>After:</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-typescript" data-lang="typescript"><span class="line"><span class="cl"><span class="nx">cache</span><span class="p">.</span><span class="nx">writeQuery</span><span class="p">({</span>
</span></span><span class="line"><span class="cl">  <span class="nx">query</span>: <span class="kt">gql</span><span class="sb">`
</span></span></span><span class="line"><span class="cl"><span class="sb">    query GetUser {
</span></span></span><span class="line"><span class="cl"><span class="sb">      user {
</span></span></span><span class="line"><span class="cl"><span class="sb">        id
</span></span></span><span class="line"><span class="cl"><span class="sb">        name
</span></span></span><span class="line"><span class="cl"><span class="sb">      }
</span></span></span><span class="line"><span class="cl"><span class="sb">    }
</span></span></span><span class="line"><span class="cl"><span class="sb">  `</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nx">data</span><span class="o">:</span> <span class="p">{</span> <span class="nx">user</span><span class="o">:</span> <span class="p">{</span> <span class="nx">id</span><span class="o">:</span> <span class="s2">&#34;1&#34;</span><span class="p">,</span> <span class="nx">name</span><span class="o">:</span> <span class="s2">&#34;Alice&#34;</span> <span class="p">}</span> <span class="p">},</span>
</span></span><span class="line"><span class="cl"><span class="p">});</span>
</span></span></code></pre></div><h2 id="migration-checklist">Migration Checklist</h2>
<ol>
<li>✅ <strong>Update Node.js</strong> to version 24.x or higher</li>
<li>✅ <strong>Update TypeScript</strong> (if used) to version 4.7 or higher</li>
<li>✅ <strong>Install Apollo Client 4</strong>: <code>npm install @apollo/client@^4.0.6</code></li>
<li>✅ <strong>Update Apollo Elements packages</strong> to version 4.x</li>
<li>✅ <strong>Search for <code>subscription.errors</code></strong> in your codebase and replace with <code>subscription.error</code></li>
<li>✅ <strong>If using <code>cache.writeData</code></strong>, replace with <code>writeQuery</code>, <code>writeFragment</code>, or <code>cache.modify</code></li>
<li>✅ <strong>Run your tests</strong> to verify everything works</li>
</ol>
<h2 id="need-help">Need Help?</h2>
<p>If you encounter issues migrating:</p>
<ul>
<li>Check the <a href="https://www.apollographql.com/docs/react/migration/3.x-to-4.x">Apollo Client 4 migration guide</a></li>
<li><a href="https://github.com/apollo-elements/apollo-elements/issues/new">Open an issue</a> on GitHub</li>
</ul>
]]></content:encoded>
    </item><item>
      <title>polymer-apollo-subscription</title>
      <link>https://apolloelements.dev/api/libraries/polymer/apollo-subscription/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/api/libraries/polymer/apollo-subscription/</guid>
      <description>&lt;!-- ----------------------------------------------------------------------------------------
     Welcome! This file includes automatically generated API documentation.
     To edit the docs that appear within, find the original source file under `packages/*`,
     corresponding to the package name and module in this YAML front-matter block.
     Thank you for your interest in Apollo Elements 😁
------------------------------------------------------------------------------------------ --&gt;</description>
      
      <content:encoded><![CDATA[<!-- ----------------------------------------------------------------------------------------
     Welcome! This file includes automatically generated API documentation.
     To edit the docs that appear within, find the original source file under `packages/*`,
     corresponding to the package name and module in this YAML front-matter block.
     Thank you for your interest in Apollo Elements 😁
------------------------------------------------------------------------------------------ -->
]]></content:encoded>
    </item><item>
      <title>ApolloSubscription</title>
      <link>https://apolloelements.dev/api/libraries/gluon/apollo-subscription/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/api/libraries/gluon/apollo-subscription/</guid>
      <description>&lt;!-- ----------------------------------------------------------------------------------------
     Welcome! This file includes automatically generated API documentation.
     To edit the docs that appear within, find the original source file under `packages/*`,
     corresponding to the package name and module in this YAML front-matter block.
     Thank you for your interest in Apollo Elements 😁
------------------------------------------------------------------------------------------ --&gt;
&lt;p&gt;&lt;code&gt;ApolloSubscription&lt;/code&gt; inherits from &lt;code&gt;ApolloElement&lt;/code&gt; and implements the &lt;a href=&#34;https://apolloelements.dev/api/core/interfaces/subscription/&#34;&gt;&lt;code&gt;ApolloSubscriptionInterface&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Read the &lt;a href=&#34;../../../../guides/usage/subscriptions/&#34;&gt;subscription component guides&lt;/a&gt; for examples and tips.&lt;/p&gt;</description>
      
      <content:encoded><![CDATA[<!-- ----------------------------------------------------------------------------------------
     Welcome! This file includes automatically generated API documentation.
     To edit the docs that appear within, find the original source file under `packages/*`,
     corresponding to the package name and module in this YAML front-matter block.
     Thank you for your interest in Apollo Elements 😁
------------------------------------------------------------------------------------------ -->
<p><code>ApolloSubscription</code> inherits from <code>ApolloElement</code> and implements the <a href="/api/core/interfaces/subscription/"><code>ApolloSubscriptionInterface</code></a>.</p>
<p>Read the <a href="../../../../guides/usage/subscriptions/">subscription component guides</a> for examples and tips.</p>
]]></content:encoded>
    </item><item>
      <title>ApolloSubscription</title>
      <link>https://apolloelements.dev/api/libraries/lit-apollo/apollo-subscription/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/api/libraries/lit-apollo/apollo-subscription/</guid>
      <description>&lt;!-- ----------------------------------------------------------------------------------------
     Welcome! This file includes automatically generated API documentation.
     To edit the docs that appear within, find the original source file under `packages/*`,
     corresponding to the package name and module in this YAML front-matter block.
     Thank you for your interest in Apollo Elements 😁
------------------------------------------------------------------------------------------ --&gt;
&lt;inline-notification type=&#34;tip&#34;&gt;
&lt;p&gt;Looking for reactive Apollo controllers? See &lt;a href=&#34;https://apolloelements.dev/api/core/&#34;&gt;&lt;code&gt;@apollo-elements/core&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/inline-notification&gt;
&lt;p&gt;&lt;code&gt;ApolloSubscription&lt;/code&gt; inherits from &lt;code&gt;ApolloElement&lt;/code&gt; and implements the &lt;a href=&#34;https://apolloelements.dev/api/core/interfaces/subscription/&#34;&gt;&lt;code&gt;ApolloSubscriptionInterface&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Read the &lt;a href=&#34;../../../../guides/usage/subscriptions/&#34;&gt;subscription component guides&lt;/a&gt; for examples and tips.&lt;/p&gt;</description>
      
      <content:encoded><![CDATA[<!-- ----------------------------------------------------------------------------------------
     Welcome! This file includes automatically generated API documentation.
     To edit the docs that appear within, find the original source file under `packages/*`,
     corresponding to the package name and module in this YAML front-matter block.
     Thank you for your interest in Apollo Elements 😁
------------------------------------------------------------------------------------------ -->
<inline-notification type="tip">
<p>Looking for reactive Apollo controllers? See <a href="/api/core/"><code>@apollo-elements/core</code></a></p>
</inline-notification>
<p><code>ApolloSubscription</code> inherits from <code>ApolloElement</code> and implements the <a href="/api/core/interfaces/subscription/"><code>ApolloSubscriptionInterface</code></a>.</p>
<p>Read the <a href="../../../../guides/usage/subscriptions/">subscription component guides</a> for examples and tips.</p>
]]></content:encoded>
    </item><item>
      <title>ApolloSubscriptionBehavior</title>
      <link>https://apolloelements.dev/api/libraries/fast/apollo-subscription/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/api/libraries/fast/apollo-subscription/</guid>
      <description>&lt;!-- ----------------------------------------------------------------------------------------
     Welcome! This file includes automatically generated API documentation.
     To edit the docs that appear within, find the original source file under `packages/*`,
     corresponding to the package name and module in this YAML front-matter block.
     Thank you for your interest in Apollo Elements 😁
------------------------------------------------------------------------------------------ --&gt;
&lt;p&gt;&lt;code&gt;ApolloSubscriptionBehavior&lt;/code&gt; extends &lt;a href=&#34;https://apolloelements.dev/api/core/controllers/query/&#34;&gt;&lt;code&gt;ApolloSubscriptionController&lt;/code&gt;&lt;/a&gt; and implements the &lt;a href=&#34;https://www.fast.design/docs/api/fast-element.behavior&#34;&gt;&lt;code&gt;Behavior&lt;/code&gt;&lt;/a&gt; interface.&lt;/p&gt;
&lt;p&gt;Read the &lt;a href=&#34;https://apolloelements.dev/guides/usage/subscriptions/&#34;&gt;subscription component guides&lt;/a&gt; for examples and tips.&lt;/p&gt;</description>
      
      <content:encoded><![CDATA[<!-- ----------------------------------------------------------------------------------------
     Welcome! This file includes automatically generated API documentation.
     To edit the docs that appear within, find the original source file under `packages/*`,
     corresponding to the package name and module in this YAML front-matter block.
     Thank you for your interest in Apollo Elements 😁
------------------------------------------------------------------------------------------ -->
<p><code>ApolloSubscriptionBehavior</code> extends <a href="/api/core/controllers/query/"><code>ApolloSubscriptionController</code></a> and implements the <a href="https://www.fast.design/docs/api/fast-element.behavior"><code>Behavior</code></a> interface.</p>
<p>Read the <a href="/guides/usage/subscriptions/">subscription component guides</a> for examples and tips.</p>
]]></content:encoded>
    </item><item>
      <title>ApolloSubscriptionController</title>
      <link>https://apolloelements.dev/api/core/controllers/subscription/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/api/core/controllers/subscription/</guid>
      <description>Subscription Controller for Apollo Elements</description>
      
      <content:encoded><![CDATA[<!-- ----------------------------------------------------------------------------------------
     Welcome! This file includes automatically generated API documentation.
     To edit the docs that appear within, find the original source file under `packages/*`,
     corresponding to the package name and module in this YAML front-matter block.
     Thank you for your interest in Apollo Elements 😁
------------------------------------------------------------------------------------------ -->
<p><code>ApolloSubscriptionController</code> lets you subscribe to real-time updated from your GraphQL server. Pass it a GraphQL subscription document, and any options you choose, and it will update its host when it&rsquo;s state (e.g. <code>data</code>, <code>error</code>, or <code>loading</code>) changes.</p>
<p>The (optional) third argument to the constructor is an <a href="#options"><code>ApolloSubscriptionControllerOptions</code></a> object.</p>
<inline-notification type="tip">
<p>Apollo Elements controllers are not limited to Lit. Use them with any object that <a href="https://lit.dev/docs/composition/controllers/">implements the <code>ReactiveControllerHost</code> interface</a>. See <a href="/api/libraries/mixins/controller-host-mixin/"><code>ControllerHostMixin</code></a> for an example.</p>
</inline-notification>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ts" data-lang="ts"><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">ApolloSubscriptionController</span> <span class="p">}</span> <span class="kr">from</span> <span class="s1">&#39;@apollo-elements/core&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">customElement</span><span class="p">,</span> <span class="nx">query</span> <span class="p">}</span> <span class="kr">from</span> <span class="s1">&#39;lit/decorators.js&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">html</span><span class="p">,</span> <span class="nx">LitElement</span> <span class="p">}</span> <span class="kr">from</span> <span class="s1">&#39;lit&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">UserJoinedSubscription</span> <span class="p">}</span> <span class="kr">from</span> <span class="s1">&#39;./UserJoined.subscription.graphql.js&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">Snackbar</span> <span class="p">}</span> <span class="kr">from</span> <span class="s1">&#39;@material/mwc-snackbar&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">@customElement</span><span class="p">(</span><span class="s1">&#39;user-joined&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="kr">class</span> <span class="nx">UserJoined</span> <span class="kr">extends</span> <span class="nx">LitElement</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">userJoined</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">ApolloSubscriptionController</span><span class="p">(</span><span class="k">this</span><span class="p">,</span> <span class="nx">UserJoinedSubscription</span><span class="p">,</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nx">onData</span><span class="o">:</span> <span class="p">({</span> <span class="nx">subscriptionData</span> <span class="p">})</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="k">this</span><span class="p">.</span><span class="nx">last</span> <span class="o">=</span> <span class="nx">subscriptionData</span><span class="p">.</span><span class="nx">userJoined</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="k">this</span><span class="p">.</span><span class="nx">snackbar</span><span class="p">.</span><span class="nx">show</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">  <span class="p">});</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="kd">@query</span><span class="p">(</span><span class="s1">&#39;mwc-snackbar&#39;</span><span class="p">)</span><span class="o">:</span> <span class="nx">Snackbar</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="nx">render() {</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="nx">html</span><span class="sb">`
</span></span></span><span class="line"><span class="cl"><span class="sb">      &lt;mwc-snackbar labeltext=&#34;</span><span class="si">${</span><span class="k">this</span><span class="p">.</span><span class="nx">userJoined</span><span class="o">?</span><span class="p">.</span><span class="nx">data</span><span class="o">?</span><span class="p">.</span><span class="nx">name</span><span class="si">}</span><span class="sb">&#34;&gt;&lt;/mwc-snackbar&gt;
</span></span></span><span class="line"><span class="cl"><span class="sb">    `</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div>]]></content:encoded>
    </item><item>
      <title>ApolloSubscriptionMixin</title>
      <link>https://apolloelements.dev/api/libraries/mixins/apollo-subscription-mixin/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/api/libraries/mixins/apollo-subscription-mixin/</guid>
      <description>&lt;!-- ----------------------------------------------------------------------------------------
     Welcome! This file includes automatically generated API documentation.
     To edit the docs that appear within, find the original source file under `packages/*`,
     corresponding to the package name and module in this YAML front-matter block.
     Thank you for your interest in Apollo Elements 😁
------------------------------------------------------------------------------------------ --&gt;
&lt;p&gt;&lt;code&gt;ApolloSubscriptionMixin&lt;/code&gt; applies &lt;code&gt;ApolloElementMixin&lt;/code&gt; and the &lt;a href=&#34;https://apolloelements.dev/api/core/interfaces/subscription/&#34;&gt;&lt;code&gt;ApolloSubscriptionInterface&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Read the &lt;a href=&#34;../../../../guides/usage/subscriptions/&#34;&gt;subscription component guides&lt;/a&gt; for examples and tips.&lt;/p&gt;</description>
      
      <content:encoded><![CDATA[<!-- ----------------------------------------------------------------------------------------
     Welcome! This file includes automatically generated API documentation.
     To edit the docs that appear within, find the original source file under `packages/*`,
     corresponding to the package name and module in this YAML front-matter block.
     Thank you for your interest in Apollo Elements 😁
------------------------------------------------------------------------------------------ -->
<p><code>ApolloSubscriptionMixin</code> applies <code>ApolloElementMixin</code> and the <a href="/api/core/interfaces/subscription/"><code>ApolloSubscriptionInterface</code></a>.</p>
<p>Read the <a href="../../../../guides/usage/subscriptions/">subscription component guides</a> for examples and tips.</p>
]]></content:encoded>
    </item><item>
      <title>Decorators</title>
      <link>https://apolloelements.dev/api/core/helpers/decorators/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/api/core/helpers/decorators/</guid>
      <description>Property Decorators for Apollo Elements</description>
      
      <content:encoded><![CDATA[<!-- ----------------------------------------------------------------------------------------
     Welcome! This file includes automatically generated API documentation.
     To edit the docs that appear within, find the original source file under `packages/*`,
     corresponding to the package name and module in this YAML front-matter block.
     Thank you for your interest in Apollo Elements 😁
------------------------------------------------------------------------------------------ -->
<p>Decorators for Apollo Elements. Used internally to reflect properties from controllers to their elements. Normally you shouldn&rsquo;t need to import these directly.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ts" data-lang="ts"><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">controlled</span> <span class="p">}</span> <span class="kr">from</span> <span class="s1">&#39;@apollo-elements/core/decorators&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">class</span> <span class="nx">ControlledData</span><span class="p">&lt;</span><span class="nt">D</span><span class="p">,</span> <span class="na">V </span><span class="o">=</span> <span class="na">VariablesOf</span><span class="p">&lt;</span><span class="nt">D</span><span class="p">&gt;&gt;</span> <span class="kr">extends</span> <span class="nx">LitElement</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">controller</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">ApolloQueryController</span><span class="p">&lt;</span><span class="nt">D</span><span class="p">,</span> <span class="na">V</span><span class="p">&gt;(</span><span class="k">this</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="kd">@controlled</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">  <span class="kd">@state</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">  <span class="nx">data</span>: <span class="kt">Data</span><span class="p">&lt;</span><span class="nt">D</span><span class="p">&gt;</span> <span class="o">|</span> <span class="kc">null</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div>]]></content:encoded>
    </item><item>
      <title>GraphQLScriptChildMixin</title>
      <link>https://apolloelements.dev/api/libraries/mixins/graphql-script-child-mixin/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/api/libraries/mixins/graphql-script-child-mixin/</guid>
      <description>&lt;!-- ----------------------------------------------------------------------------------------
     Welcome! This file includes automatically generated API documentation.
     To edit the docs that appear within, find the original source file under `packages/*`,
     corresponding to the package name and module in this YAML front-matter block.
     Thank you for your interest in Apollo Elements 😁
------------------------------------------------------------------------------------------ --&gt;
&lt;p&gt;&lt;code&gt;GraphQLScriptChildMixin&lt;/code&gt; allows Apollo elements to read their GraphQL document (i.e. query, mutation, or subscription) and variables from HTML &lt;code&gt;&amp;lt;script type=&amp;quot;application/graphql&amp;quot;&amp;gt;&lt;/code&gt; or &lt;code&gt;&amp;lt;script type=&amp;quot;application/json&amp;quot;&amp;gt;&lt;/code&gt; elements&lt;/p&gt;</description>
      
      <content:encoded><![CDATA[<!-- ----------------------------------------------------------------------------------------
     Welcome! This file includes automatically generated API documentation.
     To edit the docs that appear within, find the original source file under `packages/*`,
     corresponding to the package name and module in this YAML front-matter block.
     Thank you for your interest in Apollo Elements 😁
------------------------------------------------------------------------------------------ -->
<p><code>GraphQLScriptChildMixin</code> allows Apollo elements to read their GraphQL document (i.e. query, mutation, or subscription) and variables from HTML <code>&lt;script type=&quot;application/graphql&quot;&gt;</code> or <code>&lt;script type=&quot;application/json&quot;&gt;</code> elements</p>
]]></content:encoded>
    </item><item>
      <title>Library Functions</title>
      <link>https://apolloelements.dev/api/core/helpers/lib/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/api/core/helpers/lib/</guid>
      <description>Apollo Elements core library helpers</description>
      
      <content:encoded><![CDATA[<!-- ----------------------------------------------------------------------------------------
     Welcome! This file includes automatically generated API documentation.
     To edit the docs that appear within, find the original source file under `packages/*`,
     corresponding to the package name and module in this YAML front-matter block.
     Thank you for your interest in Apollo Elements 😁
------------------------------------------------------------------------------------------ -->
]]></content:encoded>
    </item><item>
      <title>The Next Evolution of GraphQL Front Ends</title>
      <link>https://apolloelements.dev/blog/the-next-evolution-of-graphql-front-ends/</link>
      <pubDate>Mon, 02 Aug 2021 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/blog/the-next-evolution-of-graphql-front-ends/</guid>
      <description>Introducing the next evolution in GraphQL web apps with Apollo Elements: Reactive Controllers and dynamic HTML queries bring you more power and more flexibility.</description>
      <enclosure url="/blog/next-evolution/social@2x.png" type="image/jpeg" />
      <content:encoded><![CDATA[<p>Apollo Elements has come a long way since its first release as <code>lit-apollo</code> in 2017. What started as a way to build GraphQL-querying LitElements has blossomed into a <a href="https://apolloelements.dev/api/libraries/">multi-library</a>, multi-paradigm project with <a href="https://apolloelements.dev/api/">extensive docs</a>.</p>
<p>Today we&rsquo;re releasing the next version of Apollo Elements&rsquo; packages, including a major change: introducing GraphQL Controllers, and GraphQL HTML Elements.</p>
<h2 id="reactive-graphql-controllers">Reactive GraphQL Controllers</h2>
<p>The latest version of <a href="https://lit.dev">Lit</a> introduced a concept called &ldquo;reactive controllers&rdquo;. They&rsquo;re a way to pack up reusable functionality in JavaScript classes that you can share between elements. If you&rsquo;ve use JavaScript class mixins before (<em>not</em> the same as React mixins), they you&rsquo;re familiar with sharing code between elements. Controllers go one-better by being sharable and composable without requiring you to apply a mixin to the host element, as long as it implements the <a href="https://lit.dev/docs/composition/controllers/#controller-host-api"><code>ReactiveControllerHost</code></a> interface.</p>
<p>You can even have multiple copies of the same controller active on a given host. In the words of the Lit team, controllers represent a &ldquo;has a _&rdquo; relationship to the host element, where mixins represent an &ldquo;is a _&rdquo; relationship.</p>
<p>For Apollo Elements, it means now you can add many GraphQL operations to one component, like multiple queries or a query and a mutation. Here&rsquo;s an interactive example of the latter:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ts" data-lang="ts"><span class="line"><span class="cl"><span class="kr">import</span> <span class="kr">type</span> <span class="p">{</span> <span class="nx">TextField</span> <span class="p">}</span> <span class="kr">from</span> <span class="s1">&#39;@material/mwc-textfield&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">ApolloQueryController</span><span class="p">,</span> <span class="nx">ApolloMutationController</span> <span class="p">}</span> <span class="kr">from</span> <span class="s1">&#39;@apollo-elements/core&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">LitElement</span><span class="p">,</span> <span class="nx">html</span> <span class="p">}</span> <span class="kr">from</span> <span class="s1">&#39;lit&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">customElement</span><span class="p">,</span> <span class="nx">query</span> <span class="p">}</span> <span class="kr">from</span> <span class="s1">&#39;lit/decorators.js&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">UsersQuery</span><span class="p">,</span> <span class="nx">AddUserMutation</span> <span class="p">}</span> <span class="kr">from</span> <span class="s1">&#39;./graphql.documents.js&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">style</span> <span class="p">}</span> <span class="kr">from</span> <span class="s1">&#39;./Users.css.js&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">@customElement</span><span class="p">(</span><span class="s1">&#39;users-view&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="kr">class</span> <span class="nx">UsersView</span> <span class="kr">extends</span> <span class="nx">LitElement</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="kr">static</span> <span class="nx">styles</span> <span class="o">=</span> <span class="nx">style</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="kd">@query</span><span class="p">(</span><span class="s1">&#39;mwc-textfield&#39;</span><span class="p">)</span> <span class="nx">nameField</span>: <span class="kt">TextField</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="nx">users</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">ApolloQueryController</span><span class="p">(</span><span class="k">this</span><span class="p">,</span> <span class="nx">UsersQuery</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="nx">addUser</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">ApolloMutationController</span><span class="p">(</span><span class="k">this</span><span class="p">,</span> <span class="nx">AddUserMutation</span><span class="p">,</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nx">awaitRefetchQueries</span>: <span class="kt">true</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nx">refetchQueries</span><span class="o">:</span> <span class="p">[{</span> <span class="nx">query</span>: <span class="kt">UsersQuery</span> <span class="p">}],</span>
</span></span><span class="line"><span class="cl">  <span class="p">});</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="nx">onSubmit() {</span> <span class="k">this</span><span class="p">.</span><span class="nx">addUser</span><span class="p">.</span><span class="nx">mutate</span><span class="p">({</span> <span class="nx">variables</span><span class="o">:</span> <span class="p">{</span> <span class="nx">name</span>: <span class="kt">this.nameField.value</span> <span class="p">}</span> <span class="p">});</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="nx">render() {</span>
</span></span><span class="line"><span class="cl">    <span class="kr">const</span> <span class="nx">users</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">users</span><span class="p">.</span><span class="nx">data</span><span class="o">?</span><span class="p">.</span><span class="nx">users</span> <span class="o">??</span> <span class="p">[];</span>
</span></span><span class="line"><span class="cl">    <span class="kr">const</span> <span class="nx">loading</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">users</span><span class="p">.</span><span class="nx">loading</span> <span class="o">||</span> <span class="k">this</span><span class="p">.</span><span class="nx">addUser</span><span class="p">.</span><span class="nx">loading</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="nx">html</span><span class="sb">`
</span></span></span><span class="line"><span class="cl"><span class="sb">      &lt;form&gt;
</span></span></span><span class="line"><span class="cl"><span class="sb">        &lt;h2&gt;Add a New User&lt;/h2&gt;
</span></span></span><span class="line"><span class="cl"><span class="sb">        &lt;mwc-textfield label=&#34;Name&#34; ?disabled=&#34;</span><span class="si">${</span><span class="nx">loading</span><span class="si">}</span><span class="sb">&#34;&gt;&lt;/mwc-textfield&gt;
</span></span></span><span class="line"><span class="cl"><span class="sb">        &lt;mwc-linear-progress indeterminate ?closed=&#34;</span><span class="si">${</span><span class="o">!</span><span class="nx">loading</span><span class="si">}</span><span class="sb">&#34;&gt;&lt;/mwc-linear-progress&gt;
</span></span></span><span class="line"><span class="cl"><span class="sb">        &lt;mwc-button label=&#34;Submit&#34; ?disabled=&#34;</span><span class="si">${</span><span class="nx">loading</span><span class="si">}</span><span class="sb">&#34; @click=&#34;</span><span class="si">${</span><span class="k">this</span><span class="p">.</span><span class="nx">onSubmit</span><span class="si">}</span><span class="sb">&#34;&gt;&lt;/mwc-button&gt;
</span></span></span><span class="line"><span class="cl"><span class="sb">      &lt;/form&gt;
</span></span></span><span class="line"><span class="cl"><span class="sb">      &lt;h2&gt;All Users&lt;/h2&gt;
</span></span></span><span class="line"><span class="cl"><span class="sb">      &lt;mwc-list&gt;</span><span class="si">${</span><span class="nx">users</span><span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="nx">x</span> <span class="o">=&gt;</span> <span class="nx">html</span><span class="sb">`
</span></span></span><span class="line"><span class="cl"><span class="sb">        &lt;mwc-list-item noninteractive graphic=&#34;avatar&#34;&gt;
</span></span></span><span class="line"><span class="cl"><span class="sb">          &lt;img slot=&#34;graphic&#34; ?hidden=&#34;</span><span class="si">${</span><span class="o">!</span><span class="nx">x</span><span class="p">.</span><span class="nx">picture</span><span class="si">}</span><span class="sb">&#34; .src=&#34;</span><span class="si">${</span><span class="nx">x</span><span class="p">.</span><span class="nx">picture</span><span class="si">}</span><span class="sb">&#34; role=&#34;presentation&#34;/&gt;
</span></span></span><span class="line"><span class="cl"><span class="sb">          </span><span class="si">${</span><span class="nx">x</span><span class="p">.</span><span class="nx">name</span><span class="si">}</span><span class="sb">
</span></span></span><span class="line"><span class="cl"><span class="sb">        &lt;/mwc-list-item&gt;`</span><span class="p">)</span><span class="si">}</span><span class="sb">
</span></span></span><span class="line"><span class="cl"><span class="sb">      &lt;/mwc-list&gt;
</span></span></span><span class="line"><span class="cl"><span class="sb">    `</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Controllers are great for lots of reasons. One reason we&rsquo;ve found while developing and testing Apollo Elements is that unlike the class-based API of e.g. <code>@apollo-elements/lit-apollo</code> or <code>@apollo-elements/mixins</code>, when using controllers there&rsquo;s no need to pass in type parameters to the host class. By passing a <a href="https://github.com/dotansimha/graphql-typed-document-node">TypedDocumentNode</a> object as the argument to the controller, you&rsquo;ll get that typechecking and autocomplete you know and love in your class template and methods, without awkward <code>&lt;DataType, VarsType&gt;</code> class generics.</p>
<p>If you&rsquo;re working on an existing app that uses Apollo Elements&rsquo; base classes, not to worry, you can still <code>import { ApolloQuery } from '@apollo-elements/lit-apollo'</code>, We worked hard to keep the breaking changes to a minimum. Those base classes now use the controllers at their heart, so go ahead: mix-and-match query components with controller-host components in your app, it won&rsquo;t bloat your bundles.</p>
<p>We hope you have as much fun using Apollo Elements controllers as we&rsquo;ve had writing them.</p>
<h2 id="dynamic-graphql-templates-in-html">Dynamic GraphQL Templates in HTML</h2>
<p>The previous major version of <code>@apollo-elements/components</code> included <code>&lt;apollo-client&gt;</code> and <code>&lt;apollo-mutation&gt;</code>. Those are still here and they&rsquo;re better than ever, but now they&rsquo;re part of a set with <code>&lt;apollo-query&gt;</code> and <code>&lt;apollo-subscription&gt;</code> as well.</p>
<p>With these new elements, and their older sibling <code>&lt;apollo-mutation&gt;</code>, you can write entire GraphQL apps in nothing but HTML. You read that right, declarative, data-driven GraphQL apps in HTML. You still have access to the Apollo Client API, so feel free to sprinkle in a little JS here and there for added spice.</p>
<p>This is all made possible by a pair of libraries from the Lit team&rsquo;s Justin Fagnani called <a href="https://github.com/justinfagnani/stampino/">Stampino</a> and <a href="https://github.com/justinfagnani/jexpr/">jexpr</a>. Together, they let you define dynamic parts in HTML <code>&lt;template&gt;</code> elements, filling them with JavaScript expressions based on your GraphQL data.</p>
<p>Here&rsquo;s the demo app from above, but written in HTML:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">apollo-client</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="p">&lt;</span><span class="nt">apollo-query</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;</span><span class="nt">script</span> <span class="na">type</span><span class="o">=</span><span class="s">&#34;application/graphql&#34;</span> <span class="na">src</span><span class="o">=</span><span class="s">&#34;Users.query.graphql&#34;</span><span class="p">&gt;&lt;/</span><span class="nt">script</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;</span><span class="nt">template</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="p">&lt;</span><span class="nt">h2</span><span class="p">&gt;</span>Add a New User<span class="p">&lt;/</span><span class="nt">h2</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="p">&lt;</span><span class="nt">apollo-mutation</span> <span class="na">refetch-queries</span><span class="o">=</span><span class="s">&#34;Users&#34;</span> <span class="na">await-refetch-queries</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="p">&lt;</span><span class="nt">script</span> <span class="na">type</span><span class="o">=</span><span class="s">&#34;application/graphql&#34;</span> <span class="na">src</span><span class="o">=</span><span class="s">&#34;AddUser.mutation.graphql&#34;</span><span class="p">&gt;&lt;/</span><span class="nt">script</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="p">&lt;</span><span class="nt">mwc-textfield</span> <span class="na">label</span><span class="o">=</span><span class="s">&#34;Name&#34;</span>
</span></span><span class="line"><span class="cl">                       <span class="na">slot</span><span class="o">=</span><span class="s">&#34;name&#34;</span>
</span></span><span class="line"><span class="cl">                       <span class="na">data-variable</span><span class="o">=</span><span class="s">&#34;name&#34;</span>
</span></span><span class="line"><span class="cl">                       <span class="err">.</span><span class="na">disabled</span><span class="o">=</span><span class="s">&#34;{%raw%}{{ loading }}{%endraw%}&#34;</span><span class="p">&gt;&lt;/</span><span class="nt">mwc-textfield</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="p">&lt;</span><span class="nt">mwc-button</span> <span class="na">label</span><span class="o">=</span><span class="s">&#34;Submit&#34;</span>
</span></span><span class="line"><span class="cl">                    <span class="na">trigger</span>
</span></span><span class="line"><span class="cl">                    <span class="na">slot</span><span class="o">=</span><span class="s">&#34;name&#34;</span>
</span></span><span class="line"><span class="cl">                    <span class="err">.</span><span class="na">disabled</span><span class="o">=</span><span class="s">&#34;{%raw%}{{ loading }}{%endraw%}&#34;</span><span class="p">&gt;&lt;/</span><span class="nt">mwc-button</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="p">&lt;</span><span class="nt">template</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">          <span class="p">&lt;</span><span class="nt">form</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">            <span class="p">&lt;</span><span class="nt">slot</span> <span class="na">name</span><span class="o">=</span><span class="s">&#34;name&#34;</span><span class="p">&gt;&lt;/</span><span class="nt">slot</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">            <span class="p">&lt;</span><span class="nt">mwc-linear-progress</span> <span class="na">indeterminate</span> <span class="err">.</span><span class="na">closed</span><span class="o">=</span><span class="s">&#34;{%raw%}{{ !loading }}{%endraw%}&#34;</span><span class="p">&gt;&lt;/</span><span class="nt">mwc-linear-progress</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">            <span class="p">&lt;</span><span class="nt">slot</span> <span class="na">name</span><span class="o">=</span><span class="s">&#34;submit&#34;</span><span class="p">&gt;&lt;/</span><span class="nt">slot</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">          <span class="p">&lt;/</span><span class="nt">form</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="p">&lt;/</span><span class="nt">template</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="p">&lt;/</span><span class="nt">apollo-mutation</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="p">&lt;</span><span class="nt">h2</span><span class="p">&gt;</span>All Users<span class="p">&lt;/</span><span class="nt">h2</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="p">&lt;</span><span class="nt">mwc-list</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="p">&lt;</span><span class="nt">template</span> <span class="na">type</span><span class="o">=</span><span class="s">&#34;repeat&#34;</span> <span class="na">repeat</span><span class="o">=</span><span class="s">&#34;{%raw%}{{ data.users ?? [] }}{%endraw%}&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">          <span class="p">&lt;</span><span class="nt">mwc-list-item</span> <span class="na">noninteractive</span> <span class="na">graphic</span><span class="o">=</span><span class="s">&#34;avatar&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">            <span class="p">&lt;</span><span class="nt">img</span> <span class="err">.</span><span class="na">src</span><span class="o">=</span><span class="s">&#34;{%raw%}{{ item.picture }}{%endraw%}&#34;</span> <span class="na">slot</span><span class="o">=</span><span class="s">&#34;graphic&#34;</span> <span class="na">alt</span><span class="o">=</span><span class="s">&#34;&#34;</span><span class="p">/&gt;</span>
</span></span><span class="line"><span class="cl">            {%raw%}{{ item.name }}{%endraw%}
</span></span><span class="line"><span class="cl">          <span class="p">&lt;/</span><span class="nt">mwc-list-item</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="p">&lt;/</span><span class="nt">template</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="p">&lt;/</span><span class="nt">mwc-list</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;/</span><span class="nt">template</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="p">&lt;/</span><span class="nt">apollo-query</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="p">&lt;/</span><span class="nt">apollo-client</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">script</span> <span class="na">type</span><span class="o">=</span><span class="s">&#34;module&#34;</span> <span class="na">src</span><span class="o">=</span><span class="s">&#34;components.js&#34;</span><span class="p">&gt;&lt;/</span><span class="nt">script</span><span class="p">&gt;</span>
</span></span></code></pre></div><p>There&rsquo;s a tonne of potential here and we&rsquo;re very keen to see what you come up with using these new components. Bear in mind that the stampino API isn&rsquo;t stable yet: there may be changes coming down the pipe in the future, but we&rsquo;ll do our best to keep those changes private.</p>
<h2 id="more-flexible-html-mutations">More Flexible HTML Mutations</h2>
<p>The <code>&lt;apollo-mutation&gt;</code> component lets you declare GraphQL mutations in HTML. Now, the latest version gives you more options to layout your pages. Add a stampino template to render the mutation result into the light or shadow DOM. Use the <code>variable-for=&quot;&lt;id&gt;&quot;</code> and <code>trigger-for=&quot;&lt;id&gt;&quot;</code> attributes on sibling elements to better integrate with 3rd-party components, and specify the event which triggers the mutation by specifying a value to the <code>trigger</code> attribute.</p>
<figure>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">link</span> <span class="na">rel</span><span class="o">=</span><span class="s">&#34;stylesheet&#34;</span> <span class="na">href</span><span class="o">=</span><span class="s">&#34;https://unpkg.com/@shoelace-style/shoelace@2.0.0-beta.47/dist/themes/base.css&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">script</span> <span class="na">src</span><span class="o">=</span><span class="s">&#34;https://unpkg.com/@shoelace-style/shoelace@2.0.0-beta.47/dist/shoelace.js?module&#34;</span> <span class="na">type</span><span class="o">=</span><span class="s">&#34;module&#34;</span><span class="p">&gt;&lt;/</span><span class="nt">script</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">sl-button</span> <span class="na">id</span><span class="o">=</span><span class="s">&#34;toggle&#34;</span><span class="p">&gt;</span>Add a User<span class="p">&lt;/</span><span class="nt">sl-button</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">sl-dialog</span> <span class="na">label</span><span class="o">=</span><span class="s">&#34;Add User&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="p">&lt;</span><span class="nt">sl-input</span> <span class="na">label</span><span class="o">=</span><span class="s">&#34;What is your name?&#34;</span>
</span></span><span class="line"><span class="cl">            <span class="na">variable-for</span><span class="o">=</span><span class="s">&#34;add-user-mutation&#34;</span>
</span></span><span class="line"><span class="cl">            <span class="na">data-variable</span><span class="o">=</span><span class="s">&#34;name&#34;</span><span class="p">&gt;&lt;/</span><span class="nt">sl-input</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="p">&lt;</span><span class="nt">sl-button</span> <span class="na">slot</span><span class="o">=</span><span class="s">&#34;footer&#34;</span>
</span></span><span class="line"><span class="cl">             <span class="na">type</span><span class="o">=</span><span class="s">&#34;primary&#34;</span>
</span></span><span class="line"><span class="cl">             <span class="na">trigger-for</span><span class="o">=</span><span class="s">&#34;add-user-mutation&#34;</span><span class="p">&gt;</span>Add<span class="p">&lt;/</span><span class="nt">sl-button</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="p">&lt;/</span><span class="nt">sl-dialog</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">apollo-mutation</span> <span class="na">id</span><span class="o">=</span><span class="s">&#34;add-user-mutation&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="p">&lt;</span><span class="nt">script</span> <span class="na">type</span><span class="o">=</span><span class="s">&#34;application/graphql&#34;</span> <span class="na">src</span><span class="o">=</span><span class="s">&#34;AddUser.mutation.graphql&#34;</span><span class="p">&gt;&lt;/</span><span class="nt">script</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="p">&lt;</span><span class="nt">template</span><span class="p">&gt;</span>{%raw%}
</span></span><span class="line"><span class="cl">    <span class="p">&lt;</span><span class="nt">sl-alert</span> <span class="na">type</span><span class="o">=</span><span class="s">&#34;primary&#34;</span> <span class="na">duration</span><span class="o">=</span><span class="s">&#34;3000&#34;</span> <span class="na">closable</span> <span class="err">?</span><span class="na">open</span><span class="o">=</span><span class="s">&#34;{{ data }}&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="p">&lt;</span><span class="nt">sl-icon</span> <span class="na">slot</span><span class="o">=</span><span class="s">&#34;icon&#34;</span> <span class="na">name</span><span class="o">=</span><span class="s">&#34;info-circle&#34;</span><span class="p">&gt;&lt;/</span><span class="nt">sl-icon</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="p">&lt;</span><span class="nt">p</span><span class="p">&gt;</span>Added {{ data.addUser.name }}<span class="p">&lt;/</span><span class="nt">p</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;/</span><span class="nt">sl-alert</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  {%endraw%}<span class="p">&lt;/</span><span class="nt">template</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="p">&lt;/</span><span class="nt">apollo-mutation</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">script</span> <span class="na">type</span><span class="o">=</span><span class="s">&#34;module&#34;</span> <span class="na">src</span><span class="o">=</span><span class="s">&#34;imports.js&#34;</span><span class="p">&gt;&lt;/</span><span class="nt">script</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">script</span> <span class="na">type</span><span class="o">=</span><span class="s">&#34;module&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="kr">const</span> <span class="nx">toggle</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">&#39;toggle&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">  <span class="kr">const</span> <span class="nx">dialog</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">querySelector</span><span class="p">(</span><span class="s1">&#39;sl-dialog&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">  <span class="kr">const</span> <span class="nx">mutation</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">&#39;add-user-mutation&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">  <span class="nx">toggle</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="s1">&#39;click&#39;</span><span class="p">,</span> <span class="p">()</span> <span class="p">=&gt;</span> <span class="nx">dialog</span><span class="p">.</span><span class="nx">show</span><span class="p">());</span>
</span></span><span class="line"><span class="cl">  <span class="nx">mutation</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="s1">&#39;mutation-completed&#39;</span><span class="p">,</span> <span class="p">()</span> <span class="p">=&gt;</span> <span class="nx">dialog</span><span class="p">.</span><span class="nx">hide</span><span class="p">());</span>
</span></span><span class="line"><span class="cl"><span class="p">&lt;/</span><span class="nt">script</span><span class="p">&gt;</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl"><span class="kr">import</span> <span class="s1">&#39;@apollo-elements/components&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">{</span><span class="o">%</span> <span class="nx">include</span> <span class="p">.</span><span class="o">/</span><span class="nx">_assets</span><span class="o">/</span><span class="nx">html</span><span class="o">-</span><span class="nx">components</span><span class="o">/</span><span class="nx">client</span><span class="p">.</span><span class="nx">js</span> <span class="o">|</span> <span class="nx">safe</span> <span class="o">%</span><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">&#39;add-user-mutation&#39;</span><span class="p">).</span><span class="nx">client</span> <span class="o">=</span> <span class="nx">client</span><span class="p">;</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-graphql" data-lang="graphql"><span class="line"><span class="cl"><span class="p">{</span><span class="err">%</span><span class="w"> </span><span class="py">include</span><span class="w"> </span><span class="err">./</span><span class="py">_assets</span><span class="err">/</span><span class="py">html</span><span class="err">-</span><span class="py">components</span><span class="err">/</span><span class="py">AddUser</span><span class="err">.</span><span class="kd">mutation</span><span class="err">.</span><span class="nc">graphql</span><span class="w"> </span><span class="p">|</span><span class="w"> </span><span class="py">safe</span><span class="w"> </span><span class="err">%</span><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><figcaption>
<p>Demonstrating how to use <code>&lt;apollo-mutation&gt;</code> with <a href="https://shoelace.style">Shoelace</a> web components.</p>
</figcaption>
</figure>
<h2 id="atomico-support">Atomico support</h2>
<p>On the heels of the controllers release, we&rsquo;re happy to add a new package to the roster. Apollo Elements now has first-class support for <a href="https://atomico.gitbook.io">Atomico</a>, a new hooks-based web components library with JSX or template-string templating.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-jsx" data-lang="jsx"><span class="line"><span class="cl"><span class="p">{</span><span class="o">%</span> <span class="nx">include</span> <span class="p">.</span><span class="o">/</span><span class="nx">atomico</span><span class="p">.</span><span class="nx">jsx</span> <span class="o">%</span><span class="p">}</span>
</span></span></code></pre></div><h2 id="fast-behaviors">FAST Behaviors</h2>
<p><a href="https://fast.design">FAST</a> is an innovative web component library and design system from Microsoft. Apollo Elements added support for FAST in 2020, in the form of <code>Apollo*</code> base classes. The latest release transitions to FAST <a href="https://www.fast.design/docs/api/fast-element.controller.addbehaviors">Behaviors</a>, which are analogous to Lit <code>ReactiveControllers</code>.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ts" data-lang="ts"><span class="line"><span class="cl"><span class="kd">@customElement</span><span class="p">({</span> <span class="nx">name</span><span class="p">,</span> <span class="nx">styles</span><span class="p">,</span> <span class="nx">template</span> <span class="p">})</span>
</span></span><span class="line"><span class="cl"><span class="kr">class</span> <span class="nx">UserProfile</span> <span class="kr">extends</span> <span class="nx">FASTElement</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">profile</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">ApolloQueryBehavior</span><span class="p">(</span><span class="k">this</span><span class="p">,</span> <span class="nx">MyProfileQuery</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">  <span class="nx">updateProfile</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">ApolloMutationBehavior</span><span class="p">(</span><span class="k">this</span><span class="p">,</span> <span class="nx">UpdateProfileMutation</span><span class="p">,</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nx">update</span><span class="p">(</span><span class="nx">cache</span><span class="p">,</span> <span class="nx">result</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nx">cache</span><span class="p">.</span><span class="nx">writeQuery</span><span class="p">({</span>
</span></span><span class="line"><span class="cl">        <span class="nx">query</span>: <span class="kt">MyProfileQuery</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nx">data</span><span class="o">:</span> <span class="p">{</span> <span class="nx">profile</span>: <span class="kt">result.data.updateProfile</span> <span class="p">},</span>
</span></span><span class="line"><span class="cl">      <span class="p">});</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="p">});</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>The FAST team were instrumental in getting this feature over the line, so many thanks to them.</p>
<p>If you&rsquo;re already using <code>@apollo-elements/fast</code>, we recommend migrating your code to behaviors as soon as you&rsquo;re able, but you can continue to use the element base classes, just change your import paths to <code>/bases</code>. These may be removed in the <em>next</em> major release, though.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ts" data-lang="ts"><span class="line"><span class="cl"><span class="c1">// import { ApolloQuery } from &#39;@apollo-elements/fast/apollo-query&#39;;
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>   <span class="kr">import</span> <span class="p">{</span> <span class="nx">ApolloQuery</span> <span class="p">}</span> <span class="kr">from</span> <span class="s1">&#39;@apollo-elements/fast/bases/apollo-query&#39;</span><span class="p">;</span>
</span></span></code></pre></div><h2 id="new-and-improved-docs">New and Improved Docs</h2>
<p>It wouldn&rsquo;t be an Apollo Elements release without some docs goodies. This time, in addition to new and updated docs and guides for components and controllers, we&rsquo;ve replaced our webcomponents.dev iframes with <code>&lt;playground-ide&gt;</code> elements. All the &ldquo;Edit Live&rdquo; demos on this site, including the ones in this blog post, are running locally in your browser via a service worker. Talk about serverless, <em>amirite</em>?</p>
<p>The docs also got a major upgrade care of Pascal Schilp&rsquo;s untiring work in the <a href="https://www.w3.org/community/webcomponents/">Webcomponents Community Group</a> to get the custom elements manifest v1 published. This latest iteration of the API docs generates package manifests directly from source code, and converts them to API docs via <a href="https://rocket.modern-web.dev">Rocket</a>.</p>
<h2 id="ssr">SSR</h2>
<p>As part of the release, we updated our demo apps <a href="https://leeway.apolloelements.dev">leeway</a> and <a href="https://launchctl.apolloelements.dev">LaunchCTL</a>. In the case of leeway, we took the opportunity to implement extensive SSR with the help of a new browser standard called <a href="https://web.dev/declarative-shadow-dom/">Declarative Shadow DOM</a>. It&rsquo;s early days for this technique but it&rsquo;s already looking very promising. You can try it out in any chromium browser (Chrome, Brave, Edge, Opera) by disabling JavaScript and visiting <a href="https://leeway.apolloelements.dev">https://leeway.apolloelements.dev</a>.</p>
<h2 id="behind-the-scenes">Behind the Scenes</h2>
<p>Bringing this release into the light involved more than just refactoring and updating the <code>apollo-elements/apollo-elements</code> repo. It represents work across many projects, including PRs to</p>
<ul>
<li><a href="https://github.com/justinfagnani/stampino/pulls?q=is%3Apr+is%3Aclosed+merged%3A%3C2021-06-01+merged%3A%3E2021-01+">Stampino</a> and <a href="https://github.com/justinfagnani/jexpr/pulls?q=is%3Apr+is%3Aclosed+merged%3A%3E2021-01">jexpr</a>, to iron out bugs, decrease bundle size, and add features</li>
<li><a href="https://github.com/hybridsjs/hybrids/pull/167">Hybrids</a>, to add support for reactive controllers</li>
<li><a href="https://github.com/atomicojs/hooks/pull/7">Atomico</a> and <a href="https://github.com/matthewp/haunted/pull/239">Haunted</a>, to add the <code>useController</code> hook which underlies <code>useQuery</code> and co.</li>
</ul>
<p>Additionally, here in apollo-elements, we added the <a href="/api/libraries/mixins/controller-host-mixin/"><code>ControllerHostMixin</code></a> as a way to maintain the previous element-per-graphql-document API without breaking backwards (too much). You can use this generic mixin to add controller support to any web component.</p>
<h2 id="fixes-and-enhancements">Fixes and Enhancements</h2>
<p>The last release included support for the web components hooks library <a href="https://github.com/matthewp/haunted">haunted</a>, but that support hid a dirty little secret within. Any time you called a hook inside a Haunted function component, apollo elements would sneakily mix the GraphQL interface onto the custom element&rsquo;s prototype. It was a good hack as long as you only call one hook per component, but would break down as soon as you compose multiple operations.</p>
<p>With controllers at the core, and the <a href="https://github.com/matthewp/haunted#usecontroller"><code>useController</code></a> hook, you can use as many Apollo hooks as you want in your elements without clobbering each other or polluting the element interface.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl"><span class="p">{</span><span class="o">%</span> <span class="nx">include</span> <span class="p">.</span><span class="o">/</span><span class="nx">haunted</span><span class="o">-</span><span class="nx">healthy</span><span class="o">-</span><span class="nx">snack</span><span class="p">.</span><span class="nx">js</span> <span class="o">%</span><span class="p">}</span>
</span></span></code></pre></div><p>The same is true of the <a href="https://hybrids.js.org">hybrids</a> support, it now uses the controllers underneath the hood, letting you mix multiple operations in a single hybrid.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl"><span class="p">{</span><span class="o">%</span> <span class="nx">include</span> <span class="p">.</span><span class="o">/</span><span class="nx">hybrids</span><span class="o">-</span><span class="nx">healthy</span><span class="o">-</span><span class="nx">snack</span><span class="p">.</span><span class="nx">js</span> <span class="o">%</span><span class="p">}</span>
</span></span></code></pre></div><h2 id="try-it-out">Try it Out</h2>
<p>Apollo Elements next is available in prerelease on <a href="https://npm.im/@apollo-elements/core">npm</a>. We hope you enjoy using it and look forward to seeing what you come up with.</p>
<blockquote>
<p>Are you using Apollo Elements at work? Consider <a href="https://opencollective.com/apollo-elements">sponsoring the project via Open Collective</a> to receive perks like priority support.</p></blockquote>
<style data-helmet>
.markdown-body svg:first-of-type {
  fill: var(--markdown-syntax-color);
}
</style>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">css</span> <span class="p">}</span> <span class="nx">from</span> <span class="s1">&#39;lit&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kr">export</span> <span class="kr">const</span> <span class="nx">style</span> <span class="o">=</span> <span class="nx">css</span><span class="sb">`{% include ./_assets/multiple-controllers/Users.css | safe %}`</span><span class="p">;</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">script</span> <span class="na">type</span><span class="o">=</span><span class="s">&#34;module&#34;</span> <span class="na">src</span><span class="o">=</span><span class="s">&#34;Users.js&#34;</span><span class="p">&gt;&lt;/</span><span class="nt">script</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">users-view</span><span class="p">&gt;&lt;/</span><span class="nt">users-view</span><span class="p">&gt;</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="cl"><span class="nt">html</span><span class="o">,</span> <span class="nt">body</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="k">font-family</span><span class="p">:</span> <span class="s1">&#39;Open Sans&#39;</span><span class="p">,</span> <span class="kc">sans-serif</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ts" data-lang="ts"><span class="line"><span class="cl"><span class="p">{</span><span class="o">%</span> <span class="nx">include</span> <span class="p">.</span><span class="o">/</span><span class="nx">_assets</span><span class="o">/</span><span class="nx">multiple</span><span class="o">-</span><span class="nx">controllers</span><span class="o">/</span><span class="nx">graphql</span><span class="p">.</span><span class="nx">documents</span><span class="p">.</span><span class="nx">ts</span> <span class="o">|</span> <span class="nx">safe</span> <span class="o">%</span><span class="p">}</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-graphql" data-lang="graphql"><span class="line"><span class="cl"><span class="p">{</span><span class="err">%</span><span class="w"> </span><span class="py">include</span><span class="w"> </span><span class="err">./</span><span class="py">_assets</span><span class="err">/</span><span class="py">html</span><span class="err">-</span><span class="py">components</span><span class="err">/</span><span class="py">Users</span><span class="err">.</span><span class="kd">query</span><span class="err">.</span><span class="nc">graphql</span><span class="w"> </span><span class="p">|</span><span class="w"> </span><span class="py">safe</span><span class="w"> </span><span class="err">%</span><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-graphql" data-lang="graphql"><span class="line"><span class="cl"><span class="p">{</span><span class="err">%</span><span class="w"> </span><span class="py">include</span><span class="w"> </span><span class="err">./</span><span class="py">_assets</span><span class="err">/</span><span class="py">html</span><span class="err">-</span><span class="py">components</span><span class="err">/</span><span class="py">AddUser</span><span class="err">.</span><span class="kd">mutation</span><span class="err">.</span><span class="nc">graphql</span><span class="w"> </span><span class="p">|</span><span class="w"> </span><span class="py">safe</span><span class="w"> </span><span class="err">%</span><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl"><span class="p">{</span><span class="o">%</span> <span class="nx">include</span> <span class="p">.</span><span class="o">/</span><span class="nx">_assets</span><span class="o">/</span><span class="nx">html</span><span class="o">-</span><span class="nx">components</span><span class="o">/</span><span class="nx">components</span><span class="p">.</span><span class="nx">js</span> <span class="o">|</span> <span class="nx">safe</span> <span class="o">%</span><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">{</span><span class="o">%</span> <span class="nx">include</span> <span class="p">.</span><span class="o">/</span><span class="nx">_assets</span><span class="o">/</span><span class="nx">html</span><span class="o">-</span><span class="nx">components</span><span class="o">/</span><span class="nx">client</span><span class="p">.</span><span class="nx">js</span> <span class="o">|</span> <span class="nx">safe</span> <span class="o">%</span><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">document</span><span class="p">.</span><span class="nx">querySelector</span><span class="p">(</span><span class="s1">&#39;apollo-client&#39;</span><span class="p">).</span><span class="nx">client</span> <span class="o">=</span> <span class="nx">client</span><span class="p">;</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl">{% include ./_assets/healthy-snack/index.html | safe %}
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl">{% include ./_assets/healthy-snack/index.html | safe %}
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="cl"><span class="p">{</span><span class="err">%</span> <span class="err">include</span> <span class="err">./_assets/healthy-snack/healthy-snack.css</span> <span class="err">|</span> <span class="err">safe</span> <span class="err">%</span><span class="p">}</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="cl"><span class="p">{</span><span class="err">%</span> <span class="err">include</span> <span class="err">./_assets/healthy-snack/healthy-snack.css</span> <span class="err">|</span> <span class="err">safe</span> <span class="err">%</span><span class="p">}</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">gql</span> <span class="p">}</span> <span class="nx">from</span> <span class="s1">&#39;@apollo/client/core&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kr">export</span> <span class="kr">const</span> <span class="nx">FruitsQuery</span> <span class="o">=</span> <span class="nx">gql</span><span class="sb">`{% include ./_assets/healthy-snack/Fruits.query.graphql | safe %}`</span><span class="p">;</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">gql</span> <span class="p">}</span> <span class="nx">from</span> <span class="s1">&#39;@apollo/client/core&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kr">export</span> <span class="kr">const</span> <span class="nx">VeggiesQuery</span> <span class="o">=</span> <span class="nx">gql</span><span class="sb">`{% include ./_assets/healthy-snack/Veggies.query.graphql %}`</span><span class="p">;</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">gql</span> <span class="p">}</span> <span class="nx">from</span> <span class="s1">&#39;@apollo/client/core&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kr">export</span> <span class="kr">const</span> <span class="nx">FruitsQuery</span> <span class="o">=</span> <span class="nx">gql</span><span class="sb">`{% include ./_assets/healthy-snack/Fruits.query.graphql | safe %}`</span><span class="p">;</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">gql</span> <span class="p">}</span> <span class="nx">from</span> <span class="s1">&#39;@apollo/client/core&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kr">export</span> <span class="kr">const</span> <span class="nx">VeggiesQuery</span> <span class="o">=</span> <span class="nx">gql</span><span class="sb">`{% include ./_assets/healthy-snack/Veggies.query.graphql %}`</span><span class="p">;</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl"><span class="p">{</span><span class="o">%</span> <span class="nx">include</span> <span class="p">.</span><span class="o">/</span><span class="nx">_assets</span><span class="o">/</span><span class="nx">healthy</span><span class="o">-</span><span class="nx">snack</span><span class="o">/</span><span class="nx">client</span><span class="p">.</span><span class="nx">js</span> <span class="o">|</span> <span class="nx">safe</span> <span class="o">%</span><span class="p">}</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl"><span class="p">{</span><span class="o">%</span> <span class="nx">include</span> <span class="p">.</span><span class="o">/</span><span class="nx">_assets</span><span class="o">/</span><span class="nx">healthy</span><span class="o">-</span><span class="nx">snack</span><span class="o">/</span><span class="nx">client</span><span class="p">.</span><span class="nx">js</span> <span class="o">|</span> <span class="nx">safe</span> <span class="o">%</span><span class="p">}</span>
</span></span></code></pre></div><style data-helmet>
figure {
  margin-inline: 0;
}
#hybrids-multiple-factories,
#haunted-multiple-hooks {
  --playground-ide-height: 320px;
}
</style>
]]></content:encoded>
      <category>graphql</category>
      <category>webcomponents</category>
      <category>html</category>
    </item><item>
      <title>Writing a To-Do App with GraphQL and Web Components</title>
      <link>https://apolloelements.dev/blog/writing-a-to-do-app-with-graphql-and-web-components/</link>
      <pubDate>Fri, 15 Jan 2021 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/blog/writing-a-to-do-app-with-graphql-and-web-components/</guid>
      <description>Learn how to write a To-Do list app with Apollo Elements and GraphQL. Use declarative, standards-based components to write maintainable, future-proof code.</description>
      
      <content:encoded><![CDATA[<p>To-Do apps are <em>de rigueur</em> when it comes to demonstrating web app tech stacks. Writing one lets you see how the stack handles <abbr title="create, read, update, delete">CRUD</abbr> operations, giving you a feel for how it would handle larger, more complex apps. In this post, we&rsquo;ll learn how to write a to-do app using <a href="https://apolloelements.dev">Apollo Elements</a>, the GraphQL web component library.</p>
<inline-notification title="Take Me to the Code">
<p>View the completed project <a href="https://github.com/apollo-elements/todo-app">on GitHub</a></p>
</inline-notification>
<h2 id="the-plan">The Plan</h2>
<p>The typical to-do app has a backend which contains the authoritative database of to-dos, and a frontend which displays the list and exposes UI for operations like adding, editing, or deleting to-dos. We&rsquo;ll build our frontend out of a single GraphQL query and some GraphQL mutations, and our backend using Apollo server and Koa, with an in-memory &ldquo;database&rdquo; consisting of a javascript object.</p>
<p>We&rsquo;ll use <a href="https://shoelace.style">Shoelace</a> for our UI components, and <a href="https://lit.dev">Lit</a> as our web component base, so if you want to catch up or take a refresher, check out my <a href="https://dev.to/bennypowers/lets-build-web-components-part-5-litelement-906">blog post</a>.</p>
<h3 id="non-goals">Non-Goals</h3>
<p>For the purposes of this blog post, we&rsquo;re focusing solely on the frontend side, so a proper backend server and database is out of scope. Instead, we&rsquo;ll implement a backend server that plugs in to <a href="https://modern-web.dev/guides/dev-server/getting-started/">web dev server</a>. We&rsquo;re still going to write GraphQL resolver functions though, so we could copy parts of our mock backend into a NodeJS server and with some small modifications it would still work.</p>
<p>We also won&rsquo;t be doing any fancy footwork like pagination or advanced cache management. We&rsquo;re assuming a short todo list that fits on one screen.</p>
<h2 id="app-boilerplate">App Boilerplate</h2>
<p>Let&rsquo;s use the <a href="/api/create/app/">Apollo Elements generator</a> to scaffold an app template:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">mkdir todo-apollo
</span></span><span class="line"><span class="cl"><span class="nb">cd</span> todo-apollo
</span></span><span class="line"><span class="cl">npm init @apollo-elements -- <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>    app <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>  --uri /graphql <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>  --install <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>  --overwrite <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>  --package-defaults
</span></span></code></pre></div><p>Once that&rsquo;s done, let&rsquo;s install our dependencies.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">npm i -S apollo-server-koa urlpattern-polyfill
</span></span></code></pre></div><p>And let&rsquo;s add shoelace UI&rsquo;s styles and scripts to <code>/index.html</code>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">link</span> <span class="na">rel</span><span class="o">=</span><span class="s">&#34;stylesheet&#34;</span> <span class="na">href</span><span class="o">=</span><span class="s">&#34;https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.0.0-beta.48/dist/themes/base.css&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">script</span> <span class="na">type</span><span class="o">=</span><span class="s">&#34;module&#34;</span> <span class="na">src</span><span class="o">=</span><span class="s">&#34;https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.0.0-beta.48/dist/shoelace.js&#34;</span><span class="p">&gt;&lt;/</span><span class="nt">script</span><span class="p">&gt;</span>
</span></span></code></pre></div><p>And some initial styles in <code>/style.css</code>:</p>
<details open><summary><code>/style.css</code></summary>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="cl"><span class="nt">html</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="k">font-family</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">sl</span><span class="o">-</span><span class="n">font</span><span class="o">-</span><span class="n">sans</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nt">main</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="k">display</span><span class="p">:</span> <span class="kc">flex</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="n">place-content</span><span class="p">:</span> <span class="kc">start</span> <span class="kc">center</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nt">apollo-app</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="k">width</span><span class="p">:</span> <span class="nf">clamp</span><span class="p">(</span><span class="mi">400</span><span class="kt">px</span><span class="p">,</span> <span class="mi">90</span><span class="kt">vw</span><span class="p">,</span> <span class="mi">90</span><span class="kt">vw</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div></details>
<p>With our boilerplate ready, we&rsquo;re ready to start on our mock backend.</p>
<h2 id="the-backend">The Backend</h2>
<p>Let&rsquo;s define our backend first, starting with the GraphQL schema.</p>
<h3 id="the-schema">The Schema</h3>
<p>GraphQL apps resolve around their <a href="https://graphql.org/learn/schema/"><em>schema</em></a>, so let&rsquo;s define that now. We&rsquo;ll need a type to represent each to-do, and a corresponding input type for mutations. We&rsquo;ll also define our operations, or all the actions our app&rsquo;s users can perform. Those actions are:</p>
<ol>
<li>Reading the list of to-dos</li>
<li>Creating a new to-do</li>
<li>Editing an existing to-do</li>
<li>Deleting an existing to-do</li>
</ol>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-graphql" data-lang="graphql"><span class="line"><span class="cl"><span class="kd">type</span><span class="w"> </span><span class="nc">Todo</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="py">id</span><span class="p">:</span><span class="w"> </span><span class="nc">ID</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="py">name</span><span class="p">:</span><span class="w"> </span><span class="nc">String</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="py">complete</span><span class="p">:</span><span class="w"> </span><span class="nc">Boolean</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="kd">input</span><span class="w"> </span><span class="nc">TodoInput</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="py">todoId</span><span class="p">:</span><span class="w"> </span><span class="nc">ID</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="py">name</span><span class="p">:</span><span class="w"> </span><span class="nc">String</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="py">complete</span><span class="p">:</span><span class="w"> </span><span class="nc">Boolean</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="kd">type</span><span class="w"> </span><span class="nc">Query</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="py">todos</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="nc">Todo</span><span class="p">]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="py">todo</span><span class="p">(</span><span class="py">todoId</span><span class="p">:</span><span class="w"> </span><span class="nc">ID</span><span class="p">):</span><span class="w"> </span><span class="nc">Todo</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="kd">type</span><span class="w"> </span><span class="nc">Mutation</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="py">createTodo</span><span class="p">(</span><span class="kd">input</span><span class="p">:</span><span class="w"> </span><span class="nc">TodoInput</span><span class="p">!):</span><span class="w"> </span><span class="nc">Todo</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nc">updateTodo</span><span class="p">(</span><span class="kd">input</span><span class="p">:</span><span class="w"> </span><span class="nc">TodoInput</span><span class="p">!):</span><span class="w"> </span><span class="nc">Todo</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nc">toggleTodo</span><span class="p">(</span><span class="py">todoId</span><span class="p">:</span><span class="w"> </span><span class="nc">ID</span><span class="p">!):</span><span class="w"> </span><span class="nc">Todo</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="py">deleteTodo</span><span class="p">(</span><span class="kd">input</span><span class="p">:</span><span class="w"> </span><span class="nc">TodoInput</span><span class="p">!):</span><span class="w"> </span><span class="p">[</span><span class="nc">Todo</span><span class="p">]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>In a larger app we might have defined different input types to get stronger input validation for each operation. For the sake of this demo though, a single input with no required fields does the trick.</p>
<p>Copy the above snippets in to <code>/schema.graphql</code>.</p>
<h3 id="the-database">The Database</h3>
<p>Next, we need a database to store our todos and some initial content. For demo purposes, we&rsquo;ll store the todo list in-memory. We&rsquo;re going to cut a few corners for the sake of brevity, so don&rsquo;t take this as an example of inspired database design.</p>
<p>We do try to hide our shame somewhat though by keeping our four <abbr>CRUD</abbr> operations in the server&rsquo;s context. We&rsquo;ll call those functions to perform our DB operations in our GraphQL resolvers. We also will simulate network lag, delaying reponses some random number of milliseconds.</p>
<inline-notification type="warning">
<p>Our purpose here isn&rsquo;t to write the most efficient backend code, so don&rsquo;t take lessons from these mocks.</p>
</inline-notification>
<p>Create a file <code>/server.js</code> and copy the following snippet in.</p>
<details>
  <summary><code>/server.js</code></summary>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ts" data-lang="ts"><span class="line"><span class="cl"><span class="cm">/* eslint-env node */</span>
</span></span><span class="line"><span class="cl"><span class="cm">/* eslint-disable no-console */</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">ApolloServer</span> <span class="p">}</span> <span class="kr">from</span> <span class="s1">&#39;apollo-server-koa&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">readFileSync</span> <span class="p">}</span> <span class="kr">from</span> <span class="s1">&#39;fs&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">let</span> <span class="nx">TODOS</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">INITIAL_TODOS</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">  <span class="p">{</span> <span class="nx">id</span><span class="o">:</span> <span class="s1">&#39;0&#39;</span><span class="p">,</span> <span class="nx">name</span><span class="o">:</span> <span class="s1">&#39;Get Milk&#39;</span><span class="p">,</span> <span class="nx">complete</span>: <span class="kt">false</span> <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="p">{</span> <span class="nx">id</span><span class="o">:</span> <span class="s1">&#39;1&#39;</span><span class="p">,</span> <span class="nx">name</span><span class="o">:</span> <span class="s1">&#39;Get Bread&#39;</span><span class="p">,</span> <span class="nx">complete</span>: <span class="kt">false</span> <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="p">{</span> <span class="nx">id</span><span class="o">:</span> <span class="s1">&#39;2&#39;</span><span class="p">,</span> <span class="nx">name</span><span class="o">:</span> <span class="s1">&#39;Try to Take Over the World&#39;</span><span class="p">,</span> <span class="nx">complete</span>: <span class="kt">false</span> <span class="p">},</span>
</span></span><span class="line"><span class="cl"><span class="p">];</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">initTodos() {</span>
</span></span><span class="line"><span class="cl">  <span class="nx">TODOS</span> <span class="o">=</span> <span class="p">[...</span><span class="nx">INITIAL_TODOS</span><span class="p">];</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">byId</span><span class="p">(</span><span class="nx">id</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="k">return</span> <span class="nx">x</span> <span class="o">=&gt;</span> <span class="nx">x</span><span class="p">.</span><span class="nx">id</span> <span class="o">===</span> <span class="nx">id</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">getNextId() {</span>
</span></span><span class="line"><span class="cl">  <span class="kr">const</span> <span class="nx">last</span> <span class="o">=</span> <span class="nx">TODOS</span><span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="nx">x</span> <span class="o">=&gt;</span> <span class="nx">x</span><span class="p">.</span><span class="nx">id</span><span class="p">).</span><span class="nx">sort</span><span class="p">().</span><span class="nx">pop</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">  <span class="k">return</span> <span class="p">(</span><span class="nb">parseInt</span><span class="p">(</span><span class="nx">last</span> <span class="o">??</span> <span class="s1">&#39;-1&#39;</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span><span class="p">).</span><span class="nx">toString</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">async</span> <span class="kd">function</span> <span class="nx">randomSleep</span><span class="p">(</span><span class="nx">max</span> <span class="o">=</span> <span class="mi">800</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="k">await</span> <span class="k">new</span> <span class="nx">Promise</span><span class="p">(</span><span class="nx">r</span> <span class="o">=&gt;</span> <span class="nx">setTimeout</span><span class="p">(</span><span class="nx">r</span><span class="p">,</span> <span class="nb">Math</span><span class="p">.</span><span class="nx">random</span><span class="p">()</span> <span class="o">*</span> <span class="nx">max</span><span class="p">));</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nx">initTodos</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">server</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">ApolloServer</span><span class="p">({</span>
</span></span><span class="line"><span class="cl">  <span class="nx">typeDefs</span>: <span class="kt">readFileSync</span><span class="p">(</span><span class="k">new</span> <span class="nx">URL</span><span class="p">(</span><span class="s1">&#39;schema.graphql&#39;</span><span class="p">,</span> <span class="kr">import</span><span class="p">.</span><span class="nx">meta</span><span class="p">.</span><span class="nx">url</span><span class="p">),</span> <span class="s1">&#39;utf-8&#39;</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">  <span class="nx">context</span><span class="o">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nx">getTodo</span><span class="p">(</span><span class="nx">id</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="kr">const</span> <span class="nx">todo</span> <span class="o">=</span> <span class="nx">TODOS</span><span class="p">.</span><span class="nx">find</span><span class="p">(</span><span class="nx">byId</span><span class="p">(</span><span class="nx">id</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">      <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">todo</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span><span class="p">(</span><span class="sb">`TODO </span><span class="si">${</span><span class="nx">id</span><span class="si">}</span><span class="sb"> not found`</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">      <span class="k">return</span> <span class="nx">todo</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="kr">async</span> <span class="nx">getTodos() {</span>
</span></span><span class="line"><span class="cl">      <span class="k">await</span> <span class="nx">randomSleep</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">      <span class="k">return</span> <span class="nx">TODOS</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="kr">async</span> <span class="nx">addTodo</span><span class="p">({</span> <span class="nx">name</span><span class="p">,</span> <span class="nx">complete</span> <span class="p">})</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="k">await</span> <span class="nx">randomSleep</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">      <span class="kr">const</span> <span class="nx">todo</span> <span class="o">=</span> <span class="p">{</span> <span class="nx">id</span>: <span class="kt">getNextId</span><span class="p">(),</span> <span class="nx">name</span><span class="p">,</span> <span class="nx">complete</span> <span class="p">};</span>
</span></span><span class="line"><span class="cl">      <span class="nx">TODOS</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">todo</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">      <span class="k">return</span> <span class="nx">todo</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="kr">async</span> <span class="nx">updateTodo</span><span class="p">({</span> <span class="nx">id</span><span class="p">,</span> <span class="nx">name</span><span class="p">,</span> <span class="nx">complete</span> <span class="p">})</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="k">await</span> <span class="nx">randomSleep</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">      <span class="kr">const</span> <span class="nx">todo</span> <span class="o">=</span> <span class="nx">server</span><span class="p">.</span><span class="nx">context</span><span class="p">.</span><span class="nx">getTodo</span><span class="p">(</span><span class="nx">id</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">      <span class="nx">todo</span><span class="p">.</span><span class="nx">name</span> <span class="o">=</span> <span class="nx">name</span> <span class="o">??</span> <span class="nx">todo</span><span class="p">.</span><span class="nx">name</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="nx">todo</span><span class="p">.</span><span class="nx">complete</span> <span class="o">=</span> <span class="nx">complete</span> <span class="o">??</span> <span class="nx">todo</span><span class="p">.</span><span class="nx">complete</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="k">return</span> <span class="nx">todo</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="kr">async</span> <span class="nx">deleteTodo</span><span class="p">(</span><span class="nx">id</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="k">await</span> <span class="nx">randomSleep</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">      <span class="nx">server</span><span class="p">.</span><span class="nx">context</span><span class="p">.</span><span class="nx">getTodo</span><span class="p">(</span><span class="nx">id</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">      <span class="nx">TODOS</span> <span class="o">=</span> <span class="nx">TODOS</span><span class="p">.</span><span class="nx">filter</span><span class="p">(</span><span class="nx">x</span> <span class="o">=&gt;</span> <span class="nx">x</span><span class="p">.</span><span class="nx">id</span> <span class="o">!==</span> <span class="nx">id</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">      <span class="k">return</span> <span class="nx">TODOS</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="nx">resolvers</span><span class="o">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="p">},</span>
</span></span><span class="line"><span class="cl"><span class="p">});</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="cm">/** Attaches the Apollo server to web dev server */</span>
</span></span><span class="line"><span class="cl"><span class="kr">export</span> <span class="kd">function</span> <span class="nx">graphqlTodoPlugin() {</span>
</span></span><span class="line"><span class="cl">  <span class="k">return</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nx">name</span><span class="o">:</span> <span class="s1">&#39;graphql-todo-plugin&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="kr">async</span> <span class="nx">serverStart</span><span class="p">({</span> <span class="nx">app</span><span class="p">,</span> <span class="nx">config</span> <span class="p">})</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="k">await</span> <span class="nx">server</span><span class="p">.</span><span class="nx">start</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">      <span class="nx">server</span><span class="p">.</span><span class="nx">applyMiddleware</span><span class="p">({</span> <span class="nx">app</span> <span class="p">});</span>
</span></span><span class="line"><span class="cl">      <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="sb">`🚀 GraphQL Dev Server ready at http://localhost:</span><span class="si">${</span><span class="nx">config</span><span class="p">.</span><span class="nx">port</span><span class="si">}${</span><span class="nx">server</span><span class="p">.</span><span class="nx">graphqlPath</span><span class="si">}</span><span class="sb">`</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div></details>
<h3 id="the-resolvers">The Resolvers</h3>
<p>With that accomplished, our next task is to define resolvers for each of the operations in our schema: <code>todos</code>, <code>createTodo</code>, <code>updateTodo</code>, and <code>deleteTodo</code>.</p>
<p>Ccopy the following snippet into the <code>resolvers</code> block of <code>server.js</code>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ts" data-lang="ts"><span class="line"><span class="cl"><span class="nx">Query</span><span class="o">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="kr">async</span> <span class="nx">todo</span><span class="p">(</span><span class="nx">_</span><span class="p">,</span> <span class="p">{</span> <span class="nx">todoId</span> <span class="p">},</span> <span class="nx">context</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">await</span> <span class="nx">randomSleep</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="nx">todoId</span> <span class="o">?</span> <span class="nx">context</span><span class="p">.</span><span class="nx">getTodo</span><span class="p">(</span><span class="nx">todoId</span><span class="p">)</span> <span class="o">:</span> <span class="kc">null</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="kr">async</span> <span class="nx">todos</span><span class="p">(</span><span class="nx">_</span><span class="p">,</span> <span class="nx">__</span><span class="p">,</span> <span class="nx">context</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="nx">context</span><span class="p">.</span><span class="nx">getTodos</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">  <span class="p">},</span>
</span></span><span class="line"><span class="cl"><span class="p">},</span>
</span></span><span class="line"><span class="cl"><span class="nx">Mutation</span><span class="o">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="kr">async</span> <span class="nx">createTodo</span><span class="p">(</span><span class="nx">_</span><span class="p">,</span> <span class="p">{</span> <span class="nx">input</span><span class="o">:</span> <span class="p">{</span> <span class="nx">name</span><span class="p">,</span> <span class="nx">complete</span> <span class="o">=</span> <span class="kc">false</span> <span class="p">}</span> <span class="p">},</span> <span class="nx">context</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="nx">context</span><span class="p">.</span><span class="nx">addTodo</span><span class="p">({</span> <span class="nx">name</span><span class="p">,</span> <span class="nx">complete</span> <span class="p">});</span>
</span></span><span class="line"><span class="cl">  <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="kr">async</span> <span class="nx">updateTodo</span><span class="p">(</span><span class="nx">_</span><span class="p">,</span> <span class="p">{</span> <span class="nx">input</span><span class="o">:</span> <span class="p">{</span> <span class="nx">todoId</span><span class="p">,</span> <span class="nx">name</span><span class="p">,</span> <span class="nx">complete</span> <span class="p">}</span> <span class="p">},</span> <span class="nx">context</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="nx">context</span><span class="p">.</span><span class="nx">updateTodo</span><span class="p">({</span> <span class="nx">id</span>: <span class="kt">todoId</span><span class="p">,</span> <span class="nx">name</span><span class="p">,</span> <span class="nx">complete</span> <span class="p">});</span>
</span></span><span class="line"><span class="cl">  <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="kr">async</span> <span class="nx">toggleTodo</span><span class="p">(</span><span class="nx">_</span><span class="p">,</span> <span class="p">{</span> <span class="nx">todoId</span> <span class="p">},</span> <span class="nx">context</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kr">const</span> <span class="nx">todo</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">context</span><span class="p">.</span><span class="nx">getTodo</span><span class="p">(</span><span class="nx">todoId</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="nx">context</span><span class="p">.</span><span class="nx">updateTodo</span><span class="p">({</span> <span class="p">...</span><span class="nx">todo</span><span class="p">,</span> <span class="nx">complete</span><span class="o">:</span> <span class="o">!</span><span class="nx">todo</span><span class="p">.</span><span class="nx">complete</span> <span class="p">});</span>
</span></span><span class="line"><span class="cl">  <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="kr">async</span> <span class="nx">deleteTodo</span><span class="p">(</span><span class="nx">_</span><span class="p">,</span> <span class="p">{</span> <span class="nx">input</span><span class="o">:</span> <span class="p">{</span> <span class="nx">todoId</span> <span class="p">}</span> <span class="p">},</span> <span class="nx">context</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">await</span> <span class="nx">context</span><span class="p">.</span><span class="nx">deleteTodo</span><span class="p">(</span><span class="nx">todoId</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="nx">context</span><span class="p">.</span><span class="nx">getTodos</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">  <span class="p">},</span>
</span></span><span class="line"><span class="cl"><span class="p">},</span>
</span></span></code></pre></div><p>Since we&rsquo;re relying on the <code>context</code> functions we defined earlier, our resolvers can stay simple.</p>
<h3 id="the-server">The Server</h3>
<p>Our backend code is almost ready to go, all we have to do is hook it up to our frontend via the dev server. We need to add two custom dev server plugins:</p>
<ol>
<li><code>graphqlTodoPlugin</code>, which loads our graphql server code on the <code>/graphql</code> route, and</li>
<li><code>resolveCodegenPlugin</code> to make sure the dev server loads graphql operations from the code-generated typescript files instead of their graphql sources. <code>@apollo-elements/create/helpers.js</code> exports this one for your convenience.</li>
</ol>
<p>Replace the contents of <code>web-dev-server.config.js</code> with the following snippet:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">esbuildPlugin</span> <span class="p">}</span> <span class="nx">from</span> <span class="s1">&#39;@web/dev-server-esbuild&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">fromRollup</span> <span class="p">}</span> <span class="nx">from</span> <span class="s1">&#39;@web/dev-server-rollup&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">graphqlTodoPlugin</span> <span class="p">}</span> <span class="nx">from</span> <span class="s1">&#39;./server.js&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">resolveCodegenPlugin</span> <span class="p">}</span> <span class="nx">from</span> <span class="s1">&#39;@apollo-elements/create/helpers.js&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="nx">_litcss</span> <span class="nx">from</span> <span class="s1">&#39;rollup-plugin-lit-css&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">litcss</span> <span class="o">=</span> <span class="nx">fromRollup</span><span class="p">(</span><span class="nx">_litcss</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">export</span> <span class="k">default</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">nodeResolve</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nx">port</span><span class="o">:</span> <span class="mi">8004</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nx">appIndex</span><span class="o">:</span> <span class="s1">&#39;index.html&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nx">rootDir</span><span class="o">:</span> <span class="s1">&#39;.&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nx">mimeTypes</span><span class="o">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;src/components/**/*.css&#39;</span><span class="o">:</span> <span class="s1">&#39;js&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="nx">plugins</span><span class="o">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">    <span class="nx">esbuildPlugin</span><span class="p">({</span> <span class="nx">ts</span><span class="o">:</span> <span class="kc">true</span> <span class="p">}),</span>
</span></span><span class="line"><span class="cl">    <span class="nx">resolveCodegenPlugin</span><span class="p">({</span> <span class="nx">ts</span><span class="o">:</span> <span class="kc">true</span> <span class="p">}),</span>
</span></span><span class="line"><span class="cl">    <span class="nx">graphqlTodoPlugin</span><span class="p">(),</span>
</span></span><span class="line"><span class="cl">    <span class="nx">litcss</span><span class="p">({</span>
</span></span><span class="line"><span class="cl">      <span class="nx">include</span><span class="o">:</span> <span class="s1">&#39;src/components/**/*.css&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nx">exclude</span><span class="o">:</span> <span class="s1">&#39;src/style.css&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="p">}),</span>
</span></span><span class="line"><span class="cl">  <span class="p">],</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span></code></pre></div><h2 id="the-apollo-client">The Apollo Client</h2>
<p>Our Apollo Client uses <a href="https://www.apollographql.com/docs/react/networking/advanced-http-networking/#the-httplink-object"><code>HttpLink</code></a> to connect to the backend server.</p>
<p>To make sure the todo-list renders the latest data, define a <a href="https://www.apollographql.com/docs/react/caching/cache-configuration/#typepolicy-fields">type policy</a> which replaces the entire cached todo list every time the <code>todos</code> query updates. Replace the <code>typePolicies</code> config object with:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ts" data-lang="ts"><span class="line"><span class="cl"><span class="nx">typePolicies</span><span class="o">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">Query</span><span class="o">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nx">fields</span><span class="o">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nx">location</span><span class="p">()</span><span class="o">:</span> <span class="nx">Location</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="nx">locationVar</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">      <span class="p">},</span>
</span></span><span class="line"><span class="cl">      <span class="nx">todos</span><span class="o">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="cm">/** overwrite previous array when updating todos. */</span>
</span></span><span class="line"><span class="cl">        <span class="nx">merge</span><span class="p">(</span><span class="nx">_</span><span class="p">,</span> <span class="nx">next</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">          <span class="k">return</span> <span class="nx">next</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="p">},</span>
</span></span><span class="line"><span class="cl">      <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="p">},</span>
</span></span><span class="line"><span class="cl"><span class="p">},</span>
</span></span></code></pre></div><h2 id="the-app-shell">The App Shell</h2>
<p>Next we&rsquo;ll use the <a href="https://github.com/WICG/urlpattern/blob/main/explainer.md#urlpattern"><code>URLPattern</code> proposal</a> polyfill to set up some client-side routing. Open up <code>src/router.ts</code> and paste in the following.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ts" data-lang="ts"><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">makeVar</span> <span class="p">}</span> <span class="kr">from</span> <span class="s1">&#39;@apollo/client/core&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">installRouter</span> <span class="p">}</span> <span class="kr">from</span> <span class="s1">&#39;pwa-helpers/router&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">URLPattern</span> <span class="p">}</span> <span class="kr">from</span> <span class="s1">&#39;urlpattern-polyfill&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">pattern</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">URLPattern</span><span class="p">({</span>
</span></span><span class="line"><span class="cl">  <span class="nx">pathname</span><span class="o">:</span> <span class="s1">&#39;/todos/:todoId&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"><span class="p">});</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">makeLocation</span><span class="p">(</span><span class="nx">location</span> <span class="o">=</span> <span class="nb">window</span><span class="p">.</span><span class="nx">location</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="kr">const</span> <span class="p">{</span> <span class="nx">assign</span><span class="p">,</span> <span class="nx">reload</span><span class="p">,</span> <span class="nx">replace</span><span class="p">,</span> <span class="nx">toString</span><span class="p">,</span> <span class="nx">valueOf</span><span class="p">,</span> <span class="p">...</span><span class="nx">rest</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">location</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="k">return</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nx">__typename</span><span class="o">:</span> <span class="s1">&#39;Location&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="p">...</span><span class="nx">rest</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nx">todoId</span>: <span class="kt">pattern.exec</span><span class="p">(</span><span class="k">new</span> <span class="nx">URL</span><span class="p">(</span><span class="nx">rest</span><span class="p">.</span><span class="nx">href</span><span class="p">))</span><span class="o">?</span><span class="p">.</span><span class="nx">pathname</span><span class="o">?</span><span class="p">.</span><span class="nx">groups</span><span class="o">?</span><span class="p">.</span><span class="nx">todoId</span> <span class="o">??</span> <span class="kc">null</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">update</span><span class="p">(</span><span class="nx">location</span> <span class="o">=</span> <span class="nb">window</span><span class="p">.</span><span class="nx">location</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">locationVar</span><span class="p">(</span><span class="nx">makeLocation</span><span class="p">(</span><span class="nx">location</span><span class="p">));</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">export</span> <span class="kr">const</span> <span class="nx">locationVar</span> <span class="o">=</span> <span class="nx">makeVar</span><span class="p">(</span><span class="nx">makeLocation</span><span class="p">());</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">export</span> <span class="kr">async</span> <span class="kd">function</span> <span class="nx">go</span><span class="p">(</span><span class="nx">path</span>: <span class="kt">string</span><span class="p">)</span><span class="o">:</span> <span class="nx">Promise</span><span class="p">&lt;</span><span class="nt">void</span><span class="p">&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">history</span><span class="p">.</span><span class="nx">pushState</span><span class="p">(</span><span class="kc">null</span><span class="p">,</span> <span class="s1">&#39;next&#39;</span><span class="p">,</span> <span class="k">new</span> <span class="nx">URL</span><span class="p">(</span><span class="nx">path</span><span class="p">,</span> <span class="nx">location</span><span class="p">.</span><span class="nx">origin</span><span class="p">).</span><span class="nx">toString</span><span class="p">());</span>
</span></span><span class="line"><span class="cl">  <span class="k">await</span> <span class="k">new</span> <span class="nx">Promise</span><span class="p">(</span><span class="nx">r</span> <span class="o">=&gt;</span> <span class="nx">requestAnimationFrame</span><span class="p">(</span><span class="nx">r</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">  <span class="nx">update</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nx">installRouter</span><span class="p">(</span><span class="nx">update</span><span class="p">);</span>
</span></span></code></pre></div><p>Now we&rsquo;re ready to start writing our UI components.</p>
<h2 id="reading-todos">Reading Todos</h2>
<p>Let&rsquo;s define a <a href="/guides/usage/queries/">query</a> to display our list. Edit <code>/src/components/app/App.query.graphql</code> so that our app shell gets the list of todos:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-graphql" data-lang="graphql"><span class="line"><span class="cl"><span class="kd">query</span><span class="w"> </span><span class="nc">AppQuery</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="py">location</span><span class="w"> </span><span class="nd">@client</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="py">pathname</span><span class="w"> </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="py">todos</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="py">id</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="py">name</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="py">complete</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>Our next step is to add the query operation to our app shell component and render it&rsquo;s data.
Next let&rsquo;s define the component&rsquo;s template in <code>src/components/list/list.ts</code>,</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ts" data-lang="ts"><span class="line"><span class="cl"><span class="nx">render</span><span class="p">()</span><span class="o">:</span> <span class="nx">TemplateResult</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="kr">const</span> <span class="nx">todos</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">query</span><span class="p">.</span><span class="nx">data</span><span class="o">?</span><span class="p">.</span><span class="nx">todos</span> <span class="o">??</span> <span class="p">[];</span>
</span></span><span class="line"><span class="cl">  <span class="k">return</span> <span class="nx">html</span><span class="sb">`
</span></span></span><span class="line"><span class="cl"><span class="sb">  &lt;sl-card&gt;
</span></span></span><span class="line"><span class="cl"><span class="sb">    &lt;h2 slot=&#34;header&#34;&gt;To-Do List&lt;/h2&gt;
</span></span></span><span class="line"><span class="cl"><span class="sb">    &lt;ol&gt;</span><span class="si">${</span><span class="nx">todos</span><span class="p">.</span><span class="nx">map</span><span class="p">(({</span> <span class="nx">name</span><span class="p">,</span> <span class="nx">id</span><span class="p">,</span> <span class="nx">complete</span> <span class="si">}</span><span class="sb">) =&gt; html`</span>
</span></span><span class="line"><span class="cl">      <span class="p">&lt;</span><span class="nt">li</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="p">&lt;</span><span class="nt">sl</span><span class="err">-</span><span class="na">icon</span> <span class="na">name</span><span class="o">=</span><span class="s">&#34;${complete ? &#39;check-square&#39; : &#39;square&#39;}&#34;</span><span class="p">&gt;</span><span class="o">&lt;</span><span class="err">/sl-icon&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="p">&lt;</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">&#34;/todos/${id}&#34;</span><span class="p">&gt;</span><span class="nx">$</span><span class="p">{</span><span class="nx">name</span><span class="p">}&lt;/</span><span class="nt">a</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="p">&lt;/</span><span class="nt">li</span><span class="p">&gt;</span><span class="sb">`)}
</span></span></span><span class="line"><span class="cl"><span class="sb">    &lt;/ol&gt;
</span></span></span><span class="line"><span class="cl"><span class="sb">  &lt;/sl-card&gt;
</span></span></span><span class="line"><span class="cl"><span class="sb">  `</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>add some styles in <code>src/components/app/app.css</code>,</p>
<details><summary<code>src/components/app/app.css</code></summary>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="cl"><span class="p">:</span><span class="nd">host</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="k">display</span><span class="p">:</span> <span class="k">grid</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="k">grid-template-columns</span><span class="p">:</span> <span class="nf">repeat</span><span class="p">(</span><span class="kc">auto</span><span class="o">-</span><span class="n">fit</span><span class="p">,</span> <span class="nf">minmax</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="kc">auto</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">  <span class="k">gap</span><span class="p">:</span> <span class="mi">12</span><span class="kt">px</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nt">ol</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="k">width</span><span class="p">:</span> <span class="mi">100</span><span class="kt">%</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="k">list-style-type</span><span class="p">:</span> <span class="kc">none</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="k">padding</span><span class="p">:</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nt">li</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="k">display</span><span class="p">:</span> <span class="kc">flex</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="k">align-items</span><span class="p">:</span> <span class="kc">center</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="k">gap</span><span class="p">:</span> <span class="mi">4</span><span class="kt">px</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nt">sl-card</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="k">width</span><span class="p">:</span> <span class="mi">100</span><span class="kt">%</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nt">sl-card</span><span class="o">,</span> <span class="nt">sl-card</span><span class="p">::</span><span class="nd">part</span><span class="o">(</span><span class="nt">base</span><span class="o">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="k">height</span><span class="p">:</span> <span class="mi">100</span><span class="kt">%</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nt">sl-card</span><span class="p">::</span><span class="nd">part</span><span class="o">(</span><span class="nt">header</span><span class="o">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="k">display</span><span class="p">:</span> <span class="kc">flex</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="k">justify-content</span><span class="p">:</span> <span class="kc">space-between</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="k">align-items</span><span class="p">:</span> <span class="kc">center</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div></details>
<p>And don&rsquo;t forget to load the module in <code>src/main.ts</code>.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ts" data-lang="ts"><span class="line"><span class="cl"><span class="kr">import</span> <span class="s1">&#39;./components/list&#39;</span><span class="p">;</span>
</span></span></code></pre></div><p>We&rsquo;ve fulfilled the first of our requirements: we can read the list of todos!</p>
<ol>
<li><input checked="" disabled="" type="checkbox"> Display todo-list</li>
<li><input disabled="" type="checkbox"> Add new todos</li>
<li><input disabled="" type="checkbox"> Edit todos</li>
<li><input disabled="" type="checkbox"> Delete todos</li>
</ol>
<p>Now we&rsquo;ll move on to the next step by adding a mutation operation to our component.</p>
<h2 id="adding-todos">Adding Todos</h2>
<p>Let&rsquo;s define our operation in <code>src/components/app/CreateTodo.mutation.graphql</code>. The <code>createTodo</code> operation takes a <code>TodoInput</code> object and returns a <code>Todo</code>.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-graphql" data-lang="graphql"><span class="line"><span class="cl"><span class="kd">mutation</span><span class="w"> </span><span class="nc">CreateTodo</span><span class="p">(</span><span class="nv">$input</span><span class="p">:</span><span class="w"> </span><span class="nc">TodoInput</span><span class="p">!)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="py">createTodo</span><span class="p">(</span><span class="kd">input</span><span class="p">:</span><span class="w"> </span><span class="nv">$input</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nc">id</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nc">name</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="py">complete</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>Add that mutation to our component by importing and instantiating an <code>ApolloMutationController</code> with an <code>update</code> function that appends the new todo to the cached list. For the UI, let&rsquo;s add an icon-button to the header of our main card, and have it toggle a dialog with a form for the new item.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ts" data-lang="ts"><span class="line"><span class="cl"><span class="kd">@query</span><span class="p">(</span><span class="s1">&#39;sl-input&#39;</span><span class="p">)</span> <span class="nx">input</span>: <span class="kt">HTMLInputElement</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kd">@query</span><span class="p">(</span><span class="s1">&#39;#new-dialog&#39;</span><span class="p">)</span> <span class="nx">newDialog</span>: <span class="kt">SLDialog</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nx">query</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">ApolloQueryController</span><span class="p">(</span><span class="k">this</span><span class="p">,</span> <span class="nx">AppQuery</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nx">mutation</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">ApolloMutationController</span><span class="p">(</span><span class="k">this</span><span class="p">,</span> <span class="nx">CreateTodo</span><span class="p">,</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">update</span><span class="o">:</span> <span class="p">(</span><span class="nx">cache</span><span class="p">,</span> <span class="nx">result</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kr">const</span> <span class="nx">cached</span> <span class="o">=</span> <span class="nx">cache</span><span class="p">.</span><span class="nx">readQuery</span><span class="p">({</span> <span class="nx">query</span>: <span class="kt">AppQuery</span><span class="p">,</span> <span class="nx">returnPartialData</span>: <span class="kt">true</span> <span class="p">});</span>
</span></span><span class="line"><span class="cl">    <span class="nx">cache</span><span class="p">.</span><span class="nx">writeQuery</span><span class="p">({</span>
</span></span><span class="line"><span class="cl">      <span class="nx">query</span>: <span class="kt">AppQuery</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nx">data</span><span class="o">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="p">...</span><span class="nx">cached</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nx">todos</span><span class="o">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">          <span class="p">...</span><span class="nx">cached</span><span class="p">.</span><span class="nx">todos</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nx">result</span><span class="p">.</span><span class="nx">data</span><span class="p">.</span><span class="nx">createTodo</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="p">],</span>
</span></span><span class="line"><span class="cl">      <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="p">});</span>
</span></span><span class="line"><span class="cl">  <span class="p">},</span>
</span></span><span class="line"><span class="cl"><span class="p">});</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nx">render</span><span class="p">()</span><span class="o">:</span> <span class="nx">TemplateResult</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="kr">const</span> <span class="nx">todos</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">query</span><span class="p">.</span><span class="nx">data</span><span class="o">?</span><span class="p">.</span><span class="nx">todos</span> <span class="o">??</span> <span class="p">[];</span>
</span></span><span class="line"><span class="cl">  <span class="k">return</span> <span class="nx">html</span><span class="sb">`
</span></span></span><span class="line"><span class="cl"><span class="sb">  &lt;sl-card&gt;
</span></span></span><span class="line"><span class="cl"><span class="sb">    &lt;h2 slot=&#34;header&#34;&gt;To-Do List&lt;/h2&gt;
</span></span></span><span class="line"><span class="cl"><span class="sb">    &lt;sl-tooltip slot=&#34;header&#34; content=&#34;Add Todo&#34;&gt;
</span></span></span><span class="line"><span class="cl"><span class="sb">      &lt;sl-icon-button name=&#34;plus-circle&#34;
</span></span></span><span class="line"><span class="cl"><span class="sb">                      label=&#34;Add Todo&#34;
</span></span></span><span class="line"><span class="cl"><span class="sb">                      @click=&#34;</span><span class="si">${</span><span class="p">()</span> <span class="o">=&gt;</span> <span class="k">this</span><span class="p">.</span><span class="nx">newDialog</span><span class="p">.</span><span class="nx">show</span><span class="p">()</span><span class="si">}</span><span class="sb">&#34;&gt;&lt;/sl-icon-button&gt;
</span></span></span><span class="line"><span class="cl"><span class="sb">    &lt;/sl-tooltip&gt;
</span></span></span><span class="line"><span class="cl"><span class="sb">    &lt;ol&gt;</span><span class="si">${</span><span class="nx">todos</span><span class="p">.</span><span class="nx">map</span><span class="p">(({</span> <span class="nx">name</span><span class="p">,</span> <span class="nx">id</span><span class="p">,</span> <span class="nx">complete</span> <span class="si">}</span><span class="sb">) =&gt; html`</span>
</span></span><span class="line"><span class="cl">      <span class="p">&lt;</span><span class="nt">li</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="p">&lt;</span><span class="nt">sl</span><span class="err">-</span><span class="na">icon</span> <span class="na">name</span><span class="o">=</span><span class="s">&#34;${complete ? &#39;check-square&#39; : &#39;square&#39;}&#34;</span><span class="p">&gt;</span><span class="o">&lt;</span><span class="err">/sl-icon&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="p">&lt;</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">&#34;/todos/${id}&#34;</span><span class="p">&gt;</span><span class="nx">$</span><span class="p">{</span><span class="nx">name</span><span class="p">}&lt;/</span><span class="nt">a</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="p">&lt;/</span><span class="nt">li</span><span class="p">&gt;</span><span class="sb">`)}
</span></span></span><span class="line"><span class="cl"><span class="sb">    &lt;/ol&gt;
</span></span></span><span class="line"><span class="cl"><span class="sb">  &lt;/sl-card&gt;
</span></span></span><span class="line"><span class="cl"><span class="sb">
</span></span></span><span class="line"><span class="cl"><span class="sb">  &lt;sl-dialog id=&#34;new-dialog&#34; label=&#34;New To-Do Item&#34;&gt;
</span></span></span><span class="line"><span class="cl"><span class="sb">    &lt;sl-input ?disabled=&#34;</span><span class="si">${</span><span class="k">this</span><span class="p">.</span><span class="nx">mutation</span><span class="p">.</span><span class="nx">loading</span><span class="si">}</span><span class="sb">&#34;&gt;&lt;/sl-input&gt;
</span></span></span><span class="line"><span class="cl"><span class="sb">    &lt;sl-button slot=&#34;footer&#34; @click=&#34;</span><span class="si">${</span><span class="k">this</span><span class="p">.</span><span class="nx">addTodo</span><span class="si">}</span><span class="sb">&#34;&gt;Add Todo&lt;/sl-button&gt;
</span></span></span><span class="line"><span class="cl"><span class="sb">  &lt;/sl-dialog&gt;
</span></span></span><span class="line"><span class="cl"><span class="sb">  `</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">private</span> <span class="kr">async</span> <span class="nx">addTodo() {</span>
</span></span><span class="line"><span class="cl">  <span class="k">try</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">await</span> <span class="k">this</span><span class="p">.</span><span class="nx">mutation</span><span class="p">.</span><span class="nx">mutate</span><span class="p">({</span>
</span></span><span class="line"><span class="cl">      <span class="nx">variables</span><span class="o">:</span> <span class="p">{</span> <span class="nx">input</span><span class="o">:</span> <span class="p">{</span> <span class="nx">name</span>: <span class="kt">this.input.value</span> <span class="p">}</span> <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="p">});</span>
</span></span><span class="line"><span class="cl">    <span class="k">this</span><span class="p">.</span><span class="nx">input</span><span class="p">.</span><span class="nx">value</span> <span class="o">=</span> <span class="s1">&#39;&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">this</span><span class="p">.</span><span class="nx">input</span><span class="p">.</span><span class="nx">blur</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">    <span class="k">this</span><span class="p">.</span><span class="nx">newDialog</span><span class="p">.</span><span class="nx">hide</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="nx">e</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Nice! Two requirements down, two to go:</p>
<ol>
<li><input checked="" disabled="" type="checkbox"> Display todo-list</li>
<li><input checked="" disabled="" type="checkbox"> Add new todos</li>
<li><input disabled="" type="checkbox"> Edit todos</li>
<li><input disabled="" type="checkbox"> Delete todos</li>
</ol>
<h2 id="toggling-todos">Toggling Todos</h2>
<p>Our todo-list will have two different ways to update a todo, toggling it&rsquo;s <code>complete</code> status, and editing it&rsquo;s content. For the toggle operation, let&rsquo;s create and import <code>ToggleTodo.mutation.graphql</code>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-graphql" data-lang="graphql"><span class="line"><span class="cl"><span class="kd">mutation</span><span class="w"> </span><span class="nc">ToggleTodo</span><span class="p">(</span><span class="nv">$todoId</span><span class="p">:</span><span class="w"> </span><span class="nc">ID</span><span class="p">!)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="py">toggleTodo</span><span class="p">(</span><span class="py">todoId</span><span class="p">:</span><span class="w"> </span><span class="nv">$todoId</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nc">id</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="py">name</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="py">complete</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>And for the UI, let&rsquo;s import <code>@apollo-elements/components/apollo-mutation</code> for a quick one-off. This component will sit in place of the complete icon in our app&rsquo;s template. We&rsquo;ll add a <code>data-todo-id</code> attribute on <code>&lt;apollo-mutation&gt;</code> to define a single <code>todoId</code> variable for the element, and we&rsquo;ll set <code>refetch-queries</code> and <code>await-refetch-queries</code> attributes to tell Apollo client to update the list of Todos after mutating, and to keep <code>loading</code> true until that request resolves. We could do without those, but this way the user gets a nicer experience. <code>refetch-queries</code> is a declarative alternative to a mutation update function. See the finished code for an example using <code>updater</code>.
The <code>trigger</code> attribute on the slotted button tells <code>&lt;apollo-mutation&gt;</code> to execute when the user clicks, the element will also manage the <code>disabled</code> state of the button for you. Check out the <a href="https://apolloelements.dev/api/components/apollo-mutation/"><code>&lt;apollo-mutation&gt;</code> docs</a> for more info.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">li</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="p">&lt;</span><span class="nt">apollo-mutation</span> <span class="na">data-todo-id</span><span class="o">=</span><span class="s">&#34;${id}&#34;</span>
</span></span><span class="line"><span class="cl">                  <span class="err">.</span><span class="na">mutation</span><span class="o">=</span><span class="s">&#34;${ToggleTodo}&#34;</span>
</span></span><span class="line"><span class="cl">                  <span class="err">.</span><span class="na">optimisticResponse</span><span class="o">=</span><span class="s">{{</span> <span class="na">toggleTodo:</span> <span class="err">{</span> <span class="na">__typename:</span> <span class="err">&#39;</span><span class="na">Todo</span><span class="err">&#39;,</span> <span class="na">complete:</span> <span class="err">!</span><span class="na">complete</span><span class="err">,</span> <span class="na">id</span><span class="err">,</span> <span class="na">name</span> <span class="err">}</span> <span class="err">}}</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;</span><span class="nt">sl-icon-button</span> <span class="na">trigger</span> <span class="na">name</span><span class="o">=</span><span class="s">&#34;${complete ? &#39;check-square&#39; : &#39;square&#39;}&#34;</span><span class="p">&gt;&lt;/</span><span class="nt">sl-icon-button</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="p">&lt;/</span><span class="nt">apollo-mutation</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="p">&lt;</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">&#34;/todos/${id}&#34;</span><span class="p">&gt;</span>${name}<span class="p">&lt;/</span><span class="nt">a</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="p">&lt;/</span><span class="nt">li</span><span class="p">&gt;</span>
</span></span></code></pre></div><h2 id="editing-todos">Editing Todos</h2>
<p>So far we&rsquo;ve been adding on to the app shell component for each new feature. At this point our <code>app.ts</code> file is over 100 lines long. Not terrible, but starting to approach the area we&rsquo;d want to break it up. For our editing feature, let&rsquo;s define a new <code>&lt;todo-edit&gt;</code> element with its own mutation operation. We&rsquo;ll fire up the good old generator to scaffold the files:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">npm init @apollo-elements -- <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>    component <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>  --name todo-edit <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>  --type mutation <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>  --operation-name UpdateTodo
</span></span><span class="line"><span class="cl">  --subdir <span class="s1">&#39;&#39;</span> <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>  --overwrite <span class="se">\
</span></span></span></code></pre></div><p>At the editor prompt, paste in the following:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-graphql" data-lang="graphql"><span class="line"><span class="cl"><span class="kd">mutation</span><span class="w"> </span><span class="nc">UpdateTodo</span><span class="p">(</span><span class="nv">$input</span><span class="p">:</span><span class="w"> </span><span class="nc">TodoInput</span><span class="p">!)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="py">updateTodo</span><span class="p">(</span><span class="kd">input</span><span class="p">:</span><span class="w"> </span><span class="nv">$input</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nc">id</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nc">name</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="py">complete</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>Just like before, we&rsquo;ll define the template and styles. The component features an input field for the text of the todo with a checkbox to indicate the todo&rsquo;s status. Hitting the enter key on or blurring the input, or toggling the checkbox initiates the mutation.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ts" data-lang="ts"><span class="line"><span class="cl"><span class="kd">@property</span><span class="p">({</span> <span class="nx">attribute</span><span class="o">:</span> <span class="s1">&#39;data-id&#39;</span> <span class="p">})</span> <span class="nx">todoId?</span>: <span class="kt">string</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kd">@property</span><span class="p">({</span> <span class="nx">attribute</span><span class="o">:</span> <span class="s1">&#39;data-name&#39;</span> <span class="p">})</span> <span class="nx">todoName?</span>: <span class="kt">string</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kd">@property</span><span class="p">({</span> <span class="nx">attribute</span><span class="o">:</span> <span class="s1">&#39;data-complete&#39;</span><span class="p">,</span> <span class="kr">type</span><span class="o">:</span> <span class="nb">Boolean</span> <span class="p">})</span> <span class="nx">complete?</span>: <span class="kt">boolean</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">@query</span><span class="p">(</span><span class="s1">&#39;sl-input&#39;</span><span class="p">)</span> <span class="nx">input</span>: <span class="kt">HTMLInputElement</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kd">@query</span><span class="p">(</span><span class="s1">&#39;sl-checkbox&#39;</span><span class="p">)</span> <span class="nx">checkbox</span>: <span class="kt">HTMLInputElement</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nx">render</span><span class="p">()</span><span class="o">:</span> <span class="nx">TemplateResult</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="k">return</span> <span class="nx">html</span><span class="sb">`
</span></span></span><span class="line"><span class="cl"><span class="sb">    &lt;sl-input label=&#34;To-Do Item&#34;
</span></span></span><span class="line"><span class="cl"><span class="sb">              value=&#34;</span><span class="si">${</span><span class="k">this</span><span class="p">.</span><span class="nx">todoName</span><span class="si">}</span><span class="sb">&#34;
</span></span></span><span class="line"><span class="cl"><span class="sb">              @keyup=&#34;</span><span class="si">${</span><span class="nx">event</span> <span class="o">=&gt;</span> <span class="nx">event</span><span class="p">.</span><span class="nx">key</span> <span class="o">===</span> <span class="s1">&#39;Enter&#39;</span> <span class="o">&amp;&amp;</span> <span class="k">this</span><span class="p">.</span><span class="nx">mutate</span><span class="p">()</span><span class="si">}</span><span class="sb">&#34;
</span></span></span><span class="line"><span class="cl"><span class="sb">              ?disabled=&#34;</span><span class="si">${</span><span class="k">this</span><span class="p">.</span><span class="nx">mutation</span><span class="p">.</span><span class="nx">loading</span><span class="si">}</span><span class="sb">&#34;&gt;&lt;/sl-input&gt;
</span></span></span><span class="line"><span class="cl"><span class="sb">    &lt;sl-checkbox ?checked=&#34;</span><span class="si">${</span><span class="k">this</span><span class="p">.</span><span class="nx">complete</span><span class="si">}</span><span class="sb">&#34;
</span></span></span><span class="line"><span class="cl"><span class="sb">                 ?disabled=&#34;</span><span class="si">${</span><span class="k">this</span><span class="p">.</span><span class="nx">mutation</span><span class="p">.</span><span class="nx">loading</span><span class="si">}</span><span class="sb">&#34;
</span></span></span><span class="line"><span class="cl"><span class="sb">                 @click=&#34;</span><span class="si">${</span><span class="k">this</span><span class="p">.</span><span class="nx">mutate</span><span class="si">}</span><span class="sb">&#34;&gt;Complete&lt;/sl-checkbox&gt;
</span></span></span><span class="line"><span class="cl"><span class="sb">  `</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nx">mutate</span><span class="p">()</span><span class="o">:</span> <span class="k">void</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="k">this</span><span class="p">.</span><span class="nx">mutation</span><span class="p">.</span><span class="nx">mutate</span><span class="p">({</span>
</span></span><span class="line"><span class="cl">    <span class="nx">variables</span><span class="o">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nx">input</span><span class="o">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nx">todoId</span>: <span class="kt">this.todoId</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nx">name</span>: <span class="kt">this.input.value</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nx">complete</span>: <span class="kt">this.checkbox.checked</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="p">});</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="cl"><span class="p">:</span><span class="nd">host</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="k">display</span><span class="p">:</span> <span class="k">grid</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="k">gap</span><span class="p">:</span> <span class="mi">12</span><span class="kt">px</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>We opted to pass our todo item&rsquo;s properties as attributes into the component in this case, but note that we could have just as well passed the todo object as a DOM property in the app shell&rsquo;s template. Both approaches have their pros and cons.</p>
<p>Let&rsquo;s take a moment to write an update function for our mutation, like the one we wrote for <code>ToggleTodo</code>. In this case, if we wrote our updater function with <code>readQuery</code> and <code>writeQuery</code>, we&rsquo;d have to manage the entire <code>todos</code> array ourselves, which would be error-prone and poorly performing. let&rsquo;s use <code>writeFragment</code> instead. Create a new file at <code>src/components/edit/todo.fragment.graphql</code> and give it the following content:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-graphql" data-lang="graphql"><span class="line"><span class="cl"><span class="kd">fragment</span><span class="w"> </span><span class="nc">todo</span><span class="w"> </span><span class="kd">on</span><span class="w"> </span><span class="py">Todo</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="py">id</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="py">name</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="py">complete</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p><a href="https://graphql.org/learn/queries/#fragments">GraphQL fragments</a> are pretty much just what they sound like, bits of a larger document. The <code>on</code> clause of the document declaration tells GraphQL which type this fragment belongs to. If we wanted, we could use fancy footwork like importing that <code>todo</code> fragment into our other operation files, but that&rsquo;s beyond the scope of this tutorial.</p>
<p>Import the fragment into <code>edit.ts</code> and add this <code>update</code> function to the mutation controller.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ts" data-lang="ts"><span class="line"><span class="cl"><span class="nx">mutation</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">ApolloMutationController</span><span class="p">(</span><span class="k">this</span><span class="p">,</span> <span class="nx">UpdateTodo</span><span class="p">,</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">update</span><span class="o">:</span> <span class="p">(</span><span class="nx">cache</span><span class="p">,</span> <span class="nx">result</span><span class="p">)</span> <span class="o">=&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nx">cache</span><span class="p">.</span><span class="nx">writeFragment</span><span class="p">({</span>
</span></span><span class="line"><span class="cl">      <span class="nx">fragment</span>: <span class="kt">todoFragmentDoc</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nx">id</span>: <span class="kt">cache.identify</span><span class="p">({</span> <span class="nx">__typename</span><span class="o">:</span> <span class="s1">&#39;Todo&#39;</span><span class="p">,</span> <span class="nx">id</span>: <span class="kt">this.todoId</span> <span class="p">}),</span>
</span></span><span class="line"><span class="cl">      <span class="nx">data</span>: <span class="kt">result.data.updateTodo</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="p">}),</span>
</span></span><span class="line"><span class="cl"><span class="p">});</span>
</span></span></code></pre></div><inline-notification type="tip" title="this reference">
<p>Be sure to define the <code>update</code> option as an arrow function, so that the <code>this</code> binding refers to the element, not the options object.</p>
</inline-notification>
<p>Ok, we&rsquo;ve defined our component but we can&rsquo;t <em>use</em> it yet. To view the edit component, we&rsquo;ll put our client-side router to work in the app shell. Open up <code>src/components/app/app.ts</code> then add an <code>onData</code> callback to the query controller that sets a <code>view</code> property and lazy-loads the edit component.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ts" data-lang="ts"><span class="line"><span class="cl"><span class="kd">@state</span><span class="p">()</span> <span class="nx">view</span> <span class="o">=</span> <span class="s1">&#39;&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nx">query</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">ApolloQueryController</span><span class="p">(</span><span class="k">this</span><span class="p">,</span> <span class="nx">AppQuery</span><span class="p">,</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">onData</span>: <span class="kt">data</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">this</span><span class="p">.</span><span class="nx">view</span> <span class="o">=</span> <span class="nx">data</span><span class="o">?</span><span class="p">.</span><span class="nx">location</span><span class="o">?</span><span class="p">.</span><span class="nx">todoId</span> <span class="o">?</span> <span class="s1">&#39;edit&#39;</span> <span class="o">:</span> <span class="s1">&#39;list&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">view</span> <span class="o">===</span> <span class="s1">&#39;edit&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">      <span class="kr">import</span><span class="p">(</span><span class="s1">&#39;../edit&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">  <span class="p">},</span>
</span></span><span class="line"><span class="cl"><span class="p">});</span>
</span></span></code></pre></div><p><code>onData</code> gets called whenever the data changes, with the new data as it&rsquo;s argument. Like above, make sure to use an arrow function so we can access the app shell&rsquo;s state on <code>this</code>.</p>
<p>We&rsquo;ll also add a second <code>&lt;sl-card&gt;</code> to display the editor, as a sibling to the first card.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">sl-card</span> <span class="err">?</span><span class="na">hidden</span><span class="o">=</span><span class="s">&#34;${this.view !== &#39;edit&#39;}&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="p">&lt;</span><span class="nt">h2</span> <span class="na">slot</span><span class="o">=</span><span class="s">&#34;header&#34;</span><span class="p">&gt;</span>Edit Todo<span class="p">&lt;/</span><span class="nt">h2</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="p">&lt;</span><span class="nt">sl-icon-button</span> <span class="na">slot</span><span class="o">=</span><span class="s">&#34;header&#34;</span> <span class="na">name</span><span class="o">=</span><span class="s">&#34;x&#34;</span> <span class="na">label</span><span class="o">=</span><span class="s">&#34;Close&#34;</span> <span class="na">href</span><span class="o">=</span><span class="s">&#34;/&#34;</span><span class="p">&gt;&lt;/</span><span class="nt">sl-icon-button</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="p">&lt;</span><span class="nt">todo-edit</span> <span class="na">data-id</span><span class="o">=</span><span class="s">&#34;${this.query.data?.todo?.id}&#34;</span>
</span></span><span class="line"><span class="cl">             <span class="na">data-name</span><span class="o">=</span><span class="s">&#34;${this.query.data?.todo?.name}&#34;</span>
</span></span><span class="line"><span class="cl">             <span class="err">?</span><span class="na">data-complete</span><span class="o">=</span><span class="s">&#34;${this.query.data?.todo?.complete}&#34;</span>
</span></span><span class="line"><span class="cl">             <span class="err">?</span><span class="na">hidden</span><span class="o">=</span><span class="s">&#34;${this.view !== &#39;edit&#39;}&#34;</span><span class="p">&gt;&lt;/</span><span class="nt">todo-edit</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="p">&lt;/</span><span class="nt">sl-card</span><span class="p">&gt;</span>
</span></span></code></pre></div><p>The way our client-side routing works is simple but effective. Whenever the route changes, we lazy-load the desired view component, and we hide the edit card in our template unless the route matches.</p>
<p>By this point, you should be able to add an edit todos, which brings us 3/4 of the way there.</p>
<ol>
<li><input checked="" disabled="" type="checkbox"> Display todo-list</li>
<li><input checked="" disabled="" type="checkbox"> Add new todos</li>
<li><input checked="" disabled="" type="checkbox"> Edit todos</li>
<li><input disabled="" type="checkbox"> Delete todos</li>
</ol>
<h2 id="deleting-todos">Deleting Todos</h2>
<p>For our last component let&rsquo;s change things up a little bit. Rather than adding a controller or an <code>&lt;apollo-mutation&gt;</code> element, we&rsquo;ll call the Apollo client&rsquo;s <code>mutate</code> method directly.</p>
<p>First, create <code>src/components/edit/DeleteTodo.mutation.graphql</code> with the following contents, and be sure to import it into <code>edit.ts</code>.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-graphql" data-lang="graphql"><span class="line"><span class="cl"><span class="kd">mutation</span><span class="w"> </span><span class="nc">DeleteTodo</span><span class="p">(</span><span class="nv">$input</span><span class="p">:</span><span class="w"> </span><span class="nc">TodoInput</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="py">deleteTodo</span><span class="p">(</span><span class="kd">input</span><span class="p">:</span><span class="w"> </span><span class="nv">$input</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nc">id</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nc">name</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="py">complete</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>Add the following to the <code>&lt;todo-edit&gt;</code> template:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">sl-button</span> <span class="na">type</span><span class="o">=</span><span class="s">&#34;danger&#34;</span> <span class="err">@</span><span class="na">click</span><span class="o">=</span><span class="s">&#34;${this.deleteTodo}&#34;</span><span class="p">&gt;</span>Delete Todo<span class="p">&lt;/</span><span class="nt">sl-button</span><span class="p">&gt;</span>
</span></span></code></pre></div><p>When the user clicks the &ldquo;Delete Todo&rdquo; button, four things need to happen in sequence:</p>
<ol>
<li>Update the <code>loading</code> state of the form. We can accomplish this either by calling <code>requestUpdate</code> imperatively or by defining a state property on the element and having the template check if that <em>or</em> the mutation controller&rsquo;s loading property is set.</li>
<li>Borrow a reference to the Apollo client from the existing mutation controller and call <code>mutate()</code> it, passing the <code>DeleteTodo</code> document and variables.</li>
<li>Update the cache to remove the deleted todo and update the list of todos.</li>
<li>Navigate back to the todo list, which causes the &ldquo;Edit Todo&rdquo; card to hide.</li>
</ol>
<p>Let&rsquo;s do all four of those in the <code>deleteTodo</code> method, importing the <code>go</code> helper from <code>router.ts</code>.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ts" data-lang="ts"><span class="line"><span class="cl"><span class="kr">private</span> <span class="kr">async</span> <span class="nx">deleteTodo</span><span class="p">()</span><span class="o">:</span> <span class="nx">Promise</span><span class="p">&lt;</span><span class="nt">void</span><span class="p">&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="kr">const</span> <span class="p">{</span> <span class="nx">todoId</span> <span class="p">}</span> <span class="o">=</span> <span class="k">this</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="c1">// 1: set loading state
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="k">this</span><span class="p">.</span><span class="nx">loading</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="k">try</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// 2: call the mutation imperatively
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="k">await</span> <span class="k">this</span><span class="p">.</span><span class="nx">mutation</span><span class="p">.</span><span class="nx">client</span><span class="p">.</span><span class="nx">mutate</span><span class="p">({</span>
</span></span><span class="line"><span class="cl">      <span class="nx">mutation</span>: <span class="kt">DeleteTodo</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nx">variables</span><span class="o">:</span> <span class="p">{</span> <span class="nx">input</span><span class="o">:</span> <span class="p">{</span> <span class="nx">todoId</span> <span class="p">}</span> <span class="p">},</span>
</span></span><span class="line"><span class="cl">      <span class="cm">/**
</span></span></span><span class="line"><span class="cl"><span class="cm">       * 3: The mutation returns the updated list of todos.
</span></span></span><span class="line"><span class="cl"><span class="cm">       * Overwriting the todos array causes the cache GC
</span></span></span><span class="line"><span class="cl"><span class="cm">       * To remove the missing entry.
</span></span></span><span class="line"><span class="cl"><span class="cm">       */</span>
</span></span><span class="line"><span class="cl">      <span class="nx">update</span><span class="p">(</span><span class="nx">cache</span><span class="p">,</span> <span class="nx">result</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="kr">const</span> <span class="nx">query</span> <span class="o">=</span> <span class="nx">AppQuery</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="kr">const</span> <span class="nx">variables</span> <span class="o">=</span> <span class="p">{</span> <span class="nx">todoId</span> <span class="p">};</span>
</span></span><span class="line"><span class="cl">        <span class="nx">cache</span><span class="p">.</span><span class="nx">writeQuery</span><span class="p">({</span>
</span></span><span class="line"><span class="cl">          <span class="nx">query</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nx">variables</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nx">data</span><span class="o">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="p">...</span><span class="nx">cache</span><span class="p">.</span><span class="nx">readQuery</span><span class="p">({</span> <span class="nx">query</span><span class="p">,</span> <span class="nx">variables</span> <span class="p">}),</span>
</span></span><span class="line"><span class="cl">            <span class="nx">todos</span>: <span class="kt">result.data.deleteTodo</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="p">},</span>
</span></span><span class="line"><span class="cl">        <span class="p">});</span>
</span></span><span class="line"><span class="cl">      <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="p">});</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// 4: navigate back to the list
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="k">await</span> <span class="nx">go</span><span class="p">(</span><span class="s1">&#39;/&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span> <span class="k">finally</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// clean up loading state.
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="k">this</span><span class="p">.</span><span class="nx">loading</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><ol>
<li><input checked="" disabled="" type="checkbox"> Display todo-list</li>
<li><input checked="" disabled="" type="checkbox"> Add new todos</li>
<li><input checked="" disabled="" type="checkbox"> Edit todos</li>
<li><input checked="" disabled="" type="checkbox"> Delete todos</li>
</ol>
<blockquote>
<p>git commit &amp;&amp; git push</p></blockquote>
<h2 id="the-end-result">The End Result</h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">body</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="p">&lt;</span><span class="nt">main</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="p">&lt;</span><span class="nt">apollo-client</span> <span class="na">id</span><span class="o">=</span><span class="s">&#34;client&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="p">&lt;</span><span class="nt">p-card</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="p">&lt;</span><span class="nt">h2</span> <span class="na">slot</span><span class="o">=</span><span class="s">&#34;heading&#34;</span><span class="p">&gt;</span>To-Do List<span class="p">&lt;/</span><span class="nt">h2</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="p">&lt;</span><span class="nt">todo-todos</span><span class="p">&gt;&lt;/</span><span class="nt">todo-todos</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="p">&lt;</span><span class="nt">todo-add</span> <span class="na">id</span><span class="o">=</span><span class="s">&#34;add&#34;</span> <span class="na">refetch-queries</span><span class="o">=</span><span class="s">&#34;Todos&#34;</span><span class="p">&gt;&lt;/</span><span class="nt">todo-add</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="p">&lt;</span><span class="nt">mwc-button</span> <span class="na">id</span><span class="o">=</span><span class="s">&#34;submit&#34;</span> <span class="na">slot</span><span class="o">=</span><span class="s">&#34;actions&#34;</span><span class="p">&gt;</span>Add Todo<span class="p">&lt;/</span><span class="nt">mwc-button</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">      <span class="p">&lt;/</span><span class="nt">p-card</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;/</span><span class="nt">apollo-client</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="p">&lt;/</span><span class="nt">main</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="p">&lt;/</span><span class="nt">body</span><span class="p">&gt;</span>
</span></span></code></pre></div><p>The final product gives us:</p>
<ul>
<li><em>Create</em>, <em>Update</em>, and <em>Delete</em> operations via GraphQL mutations</li>
<li><em>Read</em> operation via GraphQL query</li>
<li>Declarative, maintainable code</li>
</ul>
<p>Code reviewers (or future us) or will be able to get an at-a-glance perspective on what our code does by reading our GraphQL operation documents. Since we used web components for the UI, we&rsquo;ll be able to incrementally update or swap out our front-end framework with ease (or get rid of it altogether in favour of imperative vanilla JS).</p>
<p>Along the way we learned how to:</p>
<ul>
<li>Generate components with <code>npm init @apollo-elements</code></li>
<li>Render a query using the element&rsquo;s <code>data</code> property</li>
<li>Fire a mutation to change the data in our graph</li>
<li>Compose mutation components with queries three ways
<ol>
<li>By adding an <code>ApolloMutationController</code> to the host element</li>
<li>By using the <code>&lt;apollo-mutation&gt;</code> component.</li>
<li>By imperatively calling <code>client.mutate()</code></li>
</ol>
</li>
<li>Update the client side state following a mutation two ways:
<ol>
<li>with <code>refetchQueries</code></li>
<li>with <code>updater</code></li>
</ol>
</li>
</ul>
<p>I hope you enjoyed reading and look forward to chatting with you about GraphQL and Web Components on our discord, telegram, or slack channels.</p>
]]></content:encoded>
      <category>graphql</category>
      <category>webcomponents</category>
      <category>todo</category>
      <category>mutations</category>
      <category>custom elements</category>
    </item><item>
      <title>GraphQL Components that Work in Every Framework</title>
      <link>https://apolloelements.dev/blog/graphql-components-that-work-in-every-framework/</link>
      <pubDate>Fri, 01 Jan 2021 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/blog/graphql-components-that-work-in-every-framework/</guid>
      <description>Apollo Elements lets you write reusable and interoperable GraphQL components once, then use them in any frontend framework or none. Share your work across teams or publish your company&#39;s web components for others to use.</description>
      
      <content:encoded><![CDATA[<p>You know how it goes. You hear about the hot new framework everyone&rsquo;s posting about. Sooner or later the shine fades on your lame old app&rsquo;s front-end stack. You start dreaming about the next project, how you&rsquo;ll do things differently. Or maybe you commit to The Big Rewrite™️, but it doesn&rsquo;t go as planned. Despairing, despondent, dejected, you wonder if there&rsquo;s any way to get off this churning treadmill.</p>
<p>Friend, let me tell you - there&rsquo;s a solution looking your right in the face. In fact that solution comes built in to the browser you&rsquo;re reading this post with. You can escape the hype cycle for good with web components.</p>
<h2 id="framework-interoperability">Framework Interoperability</h2>
<p>One of the main advantages to web components is that they are just HTML DOM objects. That means they interface with each other and the rest of the app primarily via standards like HTML attributes, DOM properties, and Events. So imagine you had a <code>&lt;spicy-input&gt;</code> element that fires a <code>spicy-change</code> event every time the user types a word that&rsquo;s for grown-ups only. If, down the line, you refactor <code>&lt;spicy-input&gt;</code> by writing it with a different custom-element base class (e.g. swapping <code>LitElement</code> for <code>FASTElement</code>) as long as the external API (attributes, properties, named slots, css custom properties or shadow parts, and events) stays the same, you don&rsquo;t have to change any other files.</p>
<p><small>If reading this gave you a sudden urge to implement that <code>&lt;spicy-input&gt;</code> element, then you&rsquo;re the hero we&rsquo;re waiting for, so get on it.</small></p>
<blockquote>
<p>With web components, the library or framework you build them with is an implementation detail, and you can swap them out piecemeal without changing the rest of your app.</p></blockquote>
<p>This also means that you can use web components inside your old-school framework, or with other web-component libraries.</p>
<code-tabs collection="frameworks" default-tab="preact">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">spicy-input</span> <span class="err">(</span><span class="na">spicy-change</span><span class="err">)=&#34;</span><span class="na">onSpicyChange</span><span class="err">($</span><span class="na">event</span><span class="err">)&#34;</span> <span class="err">[</span><span class="na">value</span><span class="err">]=&#34;</span><span class="na">spicyValue</span><span class="err">&#34;</span><span class="p">&gt;&lt;/</span><span class="nt">spicy-input</span><span class="p">&gt;</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-jsx" data-lang="jsx"><span class="line"><span class="cl"><span class="k">return</span> <span class="p">&lt;</span><span class="nt">spicy</span><span class="err">-</span><span class="na">input</span> <span class="na">onspicy</span><span class="err">-</span><span class="na">change</span><span class="o">=</span><span class="p">{</span><span class="nx">onSpicyChange</span><span class="p">}</span> <span class="na">value</span><span class="o">=</span><span class="p">{</span><span class="nx">spicyValue</span><span class="p">}&gt;</span><span class="o">&lt;</span><span class="err">/spicy-input&gt;;</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-jsx" data-lang="jsx"><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">spicyInputRef</span> <span class="o">=</span> <span class="nx">createRef</span><span class="p">(</span><span class="kc">null</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">onSpicyChange</span> <span class="o">=</span> <span class="nx">e</span> <span class="p">=&gt;</span> <span class="nx">setSpicyValue</span><span class="p">(</span><span class="nx">e</span><span class="p">.</span><span class="nx">target</span><span class="p">.</span><span class="nx">value</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="p">[</span><span class="nx">spicyValue</span><span class="p">,</span> <span class="nx">setSpicyValue</span><span class="p">]</span> <span class="o">=</span> <span class="nx">useState</span><span class="p">(</span><span class="s1">&#39;&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="nx">useEffect</span><span class="p">(()</span> <span class="p">=&gt;</span> <span class="nx">spicyInputRef</span><span class="p">.</span><span class="nx">current</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="s1">&#39;spicy-change&#39;</span><span class="p">,</span> <span class="nx">onSpicyChange</span><span class="p">));</span>
</span></span><span class="line"><span class="cl"><span class="nx">useEffect</span><span class="p">(()</span> <span class="p">=&gt;</span> <span class="p">(</span><span class="nx">spicyInputRef</span><span class="p">.</span><span class="nx">current</span><span class="p">.</span><span class="nx">value</span> <span class="o">=</span> <span class="nx">spicyValue</span><span class="p">),</span> <span class="p">[</span><span class="nx">spicyValue</span><span class="p">]);</span>
</span></span><span class="line"><span class="cl"><span class="k">return</span> <span class="p">&lt;</span><span class="nt">spicy</span><span class="err">-</span><span class="na">input</span> <span class="na">ref</span><span class="o">=</span><span class="p">{</span><span class="nx">spicyInputRef</span><span class="p">}&gt;</span><span class="o">&lt;</span><span class="err">/spicy-input&gt;</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">spicy-input</span> <span class="na">on:spicy-change</span><span class="o">=</span><span class="s">{onSpicyChange}</span> <span class="na">value</span><span class="o">=</span><span class="s">{spicyValue}</span><span class="p">&gt;&lt;/</span><span class="nt">spicy-input</span><span class="p">&gt;</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">spicy-input</span> <span class="err">@</span><span class="na">spicy-change</span><span class="o">=</span><span class="s">&#34;onSpicyChange&#34;</span> <span class="na">:value</span><span class="o">=</span><span class="s">&#34;spicyValue&#34;</span><span class="p">&gt;&lt;/</span><span class="nt">spicy-input</span><span class="p">&gt;</span>
</span></span></code></pre></div></code-tabs>
<p>{% assign react_footnote = &ldquo;Why all the extra code for React? As of this writing, <a href="https://custom-elements-everywhere.com/#react">React has the poorest HTML and DOM support of any framework</a>. Hopefully this will change soon. In the meantime there are a few <a href="https://www.npmjs.com/package/reactify-wc">wrapper</a> libraries that make it easier to use web components in React by handling all this boilerplate for you.&rdquo; | markdown | replace: &ldquo;<p>&rdquo; , &quot;&quot; | replace: &ldquo;</p>&rdquo; , &quot;&quot; %}</p>
<blockquote>
<p>TL;DR: web components work in {% footnoteref &ldquo;react&rdquo; react_footnote %}all frameworks{% endfootnoteref %}, or none, since they&rsquo;re just HTML and the DOM.</p></blockquote>
<h2 id="graphql-meets-web-components">GraphQL Meets Web Components</h2>
<p>So interop takes the pressure off &ldquo;The Big Rewrite™️&rdquo; and helps us share our work across teams and apps, but web components have another super power which helps us get the job done: <em>encapsulation</em>.</p>
<p>A well-written web component keeps its insides in and its outsides out. By that, I mean that the internal implementation of the component is kept hidden while the external APIs remain stable and accessible.</p>
<p>In the world of GraphQL, that can mean associating a query with a component so that it&rsquo;s data and it&rsquo;s DOM structure are tightly linked. Apollo Elements lets us define query components that render their data to their private shadow DOM.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ts" data-lang="ts"><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">useQuery</span><span class="p">,</span> <span class="nx">html</span><span class="p">,</span> <span class="nx">component</span> <span class="p">}</span> <span class="kr">from</span> <span class="s1">&#39;@apollo-elements/haunted&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">gql</span><span class="p">,</span> <span class="nx">TypedDocumentNode</span> <span class="p">}</span> <span class="kr">from</span> <span class="s1">&#39;@apollo/client/core&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">PostsQuery</span> <span class="p">}</span> <span class="kr">from</span> <span class="s1">&#39;./Posts.query.graphql&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">Posts</span><span class="p">({</span> <span class="nx">limit</span><span class="p">,</span> <span class="nx">sort</span> <span class="p">})</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="kr">const</span> <span class="p">{</span> <span class="nx">data</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">useQuery</span><span class="p">(</span><span class="nx">PostsQuery</span><span class="p">,</span> <span class="p">{</span> <span class="nx">variables</span><span class="o">:</span> <span class="p">{</span> <span class="nx">limit</span><span class="p">,</span> <span class="nx">sort</span> <span class="p">}</span> <span class="p">});</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="kr">const</span> <span class="nx">posts</span> <span class="o">=</span> <span class="nx">data</span><span class="o">?</span><span class="p">.</span><span class="nx">posts</span> <span class="o">??</span> <span class="p">[];</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="kd">function</span> <span class="nx">onLike() {</span>
</span></span><span class="line"><span class="cl">    <span class="kr">const</span> <span class="p">{</span> <span class="nx">id</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">event</span><span class="p">.</span><span class="nx">target</span><span class="p">.</span><span class="nx">closest</span><span class="p">(</span><span class="s1">&#39;li&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">this</span><span class="p">.</span><span class="nx">dispatchEvent</span><span class="p">(</span><span class="k">new</span> <span class="nx">CustomEvent</span><span class="p">(</span><span class="s1">&#39;like-post&#39;</span><span class="p">,</span> <span class="p">{</span> <span class="nx">detail</span><span class="o">:</span> <span class="p">{</span> <span class="nx">id</span> <span class="p">}</span> <span class="p">}));</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="k">return</span> <span class="nx">html</span><span class="sb">`
</span></span></span><span class="line"><span class="cl"><span class="sb">    &lt;h2&gt;Posts&lt;/h2&gt;
</span></span></span><span class="line"><span class="cl"><span class="sb">    &lt;ol&gt;
</span></span></span><span class="line"><span class="cl"><span class="sb">      </span><span class="si">${</span><span class="nx">posts</span><span class="p">.</span><span class="nx">map</span><span class="p">(({</span> <span class="nx">id</span><span class="p">,</span> <span class="nx">coverImage</span><span class="p">,</span> <span class="nx">summary</span><span class="p">,</span> <span class="nx">title</span><span class="p">,</span> <span class="nx">url</span><span class="p">,</span> <span class="nx">liked</span> <span class="si">}</span><span class="sb">) =&gt; html`</span>
</span></span><span class="line"><span class="cl">      <span class="p">&lt;</span><span class="nt">li</span> <span class="na">id</span><span class="o">=</span><span class="s">&#34;${id}&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="p">&lt;</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">&#34;${url}&#34;</span><span class="p">&gt;&lt;</span><span class="nt">img</span> <span class="na">src</span><span class="o">=</span><span class="s">&#34;${coverImage}&#34;</span> <span class="na">role</span><span class="o">=</span><span class="s">&#34;presentation&#34;</span><span class="p">/&gt;</span> <span class="nx">$</span><span class="p">{</span><span class="nx">title</span><span class="p">}&lt;/</span><span class="nt">a</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="p">&lt;</span><span class="nt">p</span><span class="p">&gt;</span><span class="nx">$</span><span class="p">{</span><span class="nx">summary</span><span class="p">}&lt;/</span><span class="nt">p</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="p">&lt;</span><span class="nt">button</span> <span class="na">role</span><span class="o">=</span><span class="s">&#34;switch&#34;</span>
</span></span><span class="line"><span class="cl">            <span class="na">aria-checked</span><span class="o">=</span><span class="s">&#34;${liked}&#34;</span>
</span></span><span class="line"><span class="cl">            <span class="na">aria-label</span><span class="o">=</span><span class="s">&#34;toggle liked&#34;</span>
</span></span><span class="line"><span class="cl">            <span class="err">@</span><span class="na">click</span><span class="o">=</span><span class="s">&#34;${onLike}&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">          <span class="nx">$</span><span class="p">{</span><span class="nx">liked</span> <span class="o">?</span> <span class="s1">&#39;💔&#39;</span> <span class="o">:</span> <span class="s1">&#39;💓&#39;</span><span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="p">&lt;/</span><span class="nt">button</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="p">&lt;/</span><span class="nt">li</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="sb">`)}
</span></span></span><span class="line"><span class="cl"><span class="sb">    &lt;/ol&gt;
</span></span></span><span class="line"><span class="cl"><span class="sb">  `</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nx">Posts</span><span class="p">.</span><span class="nx">observedAttributes</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;limit&#39;</span><span class="p">,</span> <span class="s1">&#39;sort&#39;</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nx">customElements</span><span class="p">.</span><span class="nx">define</span><span class="p">(</span><span class="s1">&#39;posts-list&#39;</span><span class="p">,</span> <span class="nx">component</span><span class="p">(</span><span class="nx">Posts</span><span class="p">));</span>
</span></span></code></pre></div><p>In this code snippet, the <code>&lt;posts-list&gt;</code> component renders a list of post summaries, where each list-item bears the <code>id</code> of it&rsquo;s post. Ordinarily, we&rsquo;d be reticent to use element IDs so dynamically, but with Shadow DOM, the internals of <code>&lt;posts-list&gt;</code> are isolated from the rest of the document, so we as the author have complete control of the shadow root and can do what we like there without worrying about whether it might negatively affect the rest of the page.</p>
<p>And since that internal DOM is so strongly encapsulated, our colleagues on the Angular team can import it into their app with confidence that indeed nothing will go wrong, even if down the line we change the internal structure of the component.</p>
<code-tabs collection="frameworks" default-tab="preact">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">label</span><span class="p">&gt;</span>Posts per page
</span></span><span class="line"><span class="cl">  <span class="p">&lt;</span><span class="nt">input</span> <span class="na">type</span><span class="o">=</span><span class="s">&#34;number&#34;</span> <span class="na">step</span><span class="o">=</span><span class="s">&#34;10&#34;</span> <span class="err">[(</span><span class="na">ngModel</span><span class="err">)]=&#34;</span><span class="na">limit</span><span class="err">&#34;</span><span class="p">/&gt;</span>
</span></span><span class="line"><span class="cl"><span class="p">&lt;/</span><span class="nt">label</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">label</span><span class="p">&gt;</span>Sort
</span></span><span class="line"><span class="cl">  <span class="p">&lt;</span><span class="nt">select</span> <span class="err">[(</span><span class="na">ngModel</span><span class="err">)]=&#34;</span><span class="na">sort</span><span class="err">&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;</span><span class="nt">option</span> <span class="na">value</span><span class="o">=</span><span class="s">&#34;asc&#34;</span><span class="p">&gt;</span>Ascending<span class="p">&lt;/</span><span class="nt">option</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;</span><span class="nt">option</span> <span class="na">value</span><span class="o">=</span><span class="s">&#34;desc&#34;</span><span class="p">&gt;</span>Descending<span class="p">&lt;/</span><span class="nt">option</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="p">&lt;/</span><span class="nt">select</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="p">&lt;/</span><span class="nt">label</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">posts-list</span>
</span></span><span class="line"><span class="cl">    <span class="err">[</span><span class="na">limit</span><span class="err">]=&#34;</span><span class="na">limit</span><span class="err">&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="err">[</span><span class="na">sort</span><span class="err">]=&#34;</span><span class="na">sort</span><span class="err">&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="err">(</span><span class="na">like-post</span><span class="err">)=&#34;</span><span class="na">onLikePost</span><span class="err">($</span><span class="na">event</span><span class="err">)&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">&gt;&lt;/</span><span class="nt">posts-list</span><span class="p">&gt;</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-tsx" data-lang="tsx"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">PostContainer() {</span>
</span></span><span class="line"><span class="cl">  <span class="kr">const</span> <span class="p">[</span><span class="nx">limit</span><span class="p">,</span> <span class="nx">setLimit</span><span class="p">]</span> <span class="o">=</span> <span class="nx">useState</span><span class="p">(</span><span class="mi">10</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">  <span class="kr">const</span> <span class="p">[</span><span class="nx">sort</span><span class="p">,</span> <span class="nx">setSort</span><span class="p">]</span> <span class="o">=</span> <span class="nx">useState</span><span class="p">(</span><span class="s1">&#39;asc&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">  <span class="k">return</span> <span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;</span><span class="nt">label</span><span class="p">&gt;</span><span class="nx">Posts</span> <span class="nx">per</span> <span class="nx">page</span>
</span></span><span class="line"><span class="cl">      <span class="p">&lt;</span><span class="nt">input</span>
</span></span><span class="line"><span class="cl">          <span class="na">type</span><span class="o">=</span><span class="s">&#34;number&#34;</span>
</span></span><span class="line"><span class="cl">          <span class="na">step</span><span class="o">=</span><span class="s">&#34;10&#34;</span>
</span></span><span class="line"><span class="cl">          <span class="na">value</span><span class="o">=</span><span class="p">{</span><span class="nx">limit</span><span class="p">}</span>
</span></span><span class="line"><span class="cl">          <span class="na">onInput</span><span class="o">=</span><span class="p">{</span><span class="nx">e</span> <span class="o">=&gt;</span> <span class="nx">setLimit</span><span class="p">(</span><span class="nx">e</span><span class="p">.</span><span class="nx">target</span><span class="p">.</span><span class="nx">value</span><span class="p">)}/&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;/</span><span class="nt">label</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="p">&lt;</span><span class="nt">label</span><span class="p">&gt;</span><span class="nx">Sort</span>
</span></span><span class="line"><span class="cl">      <span class="p">&lt;</span><span class="nt">select</span> <span class="na">onInput</span><span class="o">=</span><span class="p">{</span><span class="nx">e</span> <span class="o">=&gt;</span> <span class="nx">setSort</span><span class="p">(</span><span class="nx">e</span><span class="p">.</span><span class="nx">target</span><span class="p">.</span><span class="nx">value</span><span class="p">)}&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="p">&lt;</span><span class="nt">option</span> <span class="na">value</span><span class="o">=</span><span class="s">&#34;asc&#34;</span><span class="p">&gt;</span><span class="nx">Ascending</span><span class="p">&lt;/</span><span class="nt">option</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="p">&lt;</span><span class="nt">option</span> <span class="na">value</span><span class="o">=</span><span class="s">&#34;desc&#34;</span><span class="p">&gt;</span><span class="nx">Descending</span><span class="p">&lt;/</span><span class="nt">option</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="p">&lt;/</span><span class="nt">select</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;/</span><span class="nt">label</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="p">&lt;</span><span class="nt">posts</span><span class="err">-</span><span class="na">list</span>
</span></span><span class="line"><span class="cl">        <span class="na">limit</span><span class="o">=</span><span class="p">{</span><span class="nx">limit</span><span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="na">sort</span><span class="o">=</span><span class="p">{</span><span class="nx">sort</span><span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="na">onlike-post</span><span class="o">=</span><span class="p">{</span><span class="nx">onLikePost</span><span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">&gt;</span><span class="o">&lt;</span><span class="err">/posts-list&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-tsx" data-lang="tsx"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">PostContainer() {</span>
</span></span><span class="line"><span class="cl">  <span class="kr">const</span> <span class="nx">postsListRef</span> <span class="o">=</span> <span class="nx">createRef</span><span class="p">(</span><span class="kc">null</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">  <span class="kr">const</span> <span class="p">[</span><span class="nx">limit</span><span class="p">,</span> <span class="nx">setLimit</span><span class="p">]</span> <span class="o">=</span> <span class="nx">useState</span><span class="p">(</span><span class="mi">10</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">  <span class="kr">const</span> <span class="p">[</span><span class="nx">sort</span><span class="p">,</span> <span class="nx">setSort</span><span class="p">]</span> <span class="o">=</span> <span class="nx">useState</span><span class="p">(</span><span class="s1">&#39;asc&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">  <span class="nx">useEffect</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="nx">postsListRef</span><span class="p">.</span><span class="nx">current</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="s1">&#39;like-post&#39;</span><span class="p">,</span> <span class="nx">onLikePost</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">  <span class="nx">useEffect</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="nx">postsListRef</span><span class="p">.</span><span class="nx">current</span><span class="p">.</span><span class="nx">limit</span> <span class="o">=</span> <span class="nx">limit</span><span class="p">,</span> <span class="p">[</span><span class="nx">limit</span><span class="p">]);</span>
</span></span><span class="line"><span class="cl">  <span class="nx">useEffect</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="nx">postsListRef</span><span class="p">.</span><span class="nx">current</span><span class="p">.</span><span class="nx">sort</span> <span class="o">=</span> <span class="nx">sort</span><span class="p">,</span> <span class="p">[</span><span class="nx">sort</span><span class="p">]);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="k">return</span> <span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;</span><span class="nt">label</span><span class="p">&gt;</span><span class="nx">Posts</span> <span class="nx">per</span> <span class="nx">page</span>
</span></span><span class="line"><span class="cl">      <span class="p">&lt;</span><span class="nt">input</span>
</span></span><span class="line"><span class="cl">          <span class="na">type</span><span class="o">=</span><span class="s">&#34;number&#34;</span>
</span></span><span class="line"><span class="cl">          <span class="na">step</span><span class="o">=</span><span class="s">&#34;10&#34;</span>
</span></span><span class="line"><span class="cl">          <span class="na">value</span><span class="o">=</span><span class="p">{</span><span class="nx">limit</span><span class="p">}</span>
</span></span><span class="line"><span class="cl">          <span class="na">onInput</span><span class="o">=</span><span class="p">{</span><span class="nx">e</span> <span class="o">=&gt;</span> <span class="nx">setLimit</span><span class="p">(</span><span class="nx">e</span><span class="p">.</span><span class="nx">target</span><span class="p">.</span><span class="nx">value</span><span class="p">)}/&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;/</span><span class="nt">label</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="p">&lt;</span><span class="nt">label</span><span class="p">&gt;</span><span class="nx">Sort</span>
</span></span><span class="line"><span class="cl">      <span class="p">&lt;</span><span class="nt">select</span> <span class="na">onInput</span><span class="o">=</span><span class="p">{</span><span class="nx">e</span> <span class="o">=&gt;</span> <span class="nx">setSort</span><span class="p">(</span><span class="nx">e</span><span class="p">.</span><span class="nx">target</span><span class="p">.</span><span class="nx">value</span><span class="p">)}&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="p">&lt;</span><span class="nt">option</span> <span class="na">value</span><span class="o">=</span><span class="s">&#34;asc&#34;</span><span class="p">&gt;</span><span class="nx">Ascending</span><span class="p">&lt;/</span><span class="nt">option</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="p">&lt;</span><span class="nt">option</span> <span class="na">value</span><span class="o">=</span><span class="s">&#34;desc&#34;</span><span class="p">&gt;</span><span class="nx">Descending</span><span class="p">&lt;/</span><span class="nt">option</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="p">&lt;/</span><span class="nt">select</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;/</span><span class="nt">label</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="p">&lt;</span><span class="nt">posts</span><span class="err">-</span><span class="na">list</span> <span class="na">ref</span><span class="o">=</span><span class="p">{</span><span class="nx">postsListRef</span><span class="p">}&gt;</span><span class="o">&lt;</span><span class="err">/posts-list&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">label</span><span class="p">&gt;</span>Posts per page
</span></span><span class="line"><span class="cl">  <span class="p">&lt;</span><span class="nt">input</span> <span class="na">type</span><span class="o">=</span><span class="s">&#34;number&#34;</span> <span class="na">step</span><span class="o">=</span><span class="s">&#34;10&#34;</span> <span class="na">bind:value</span><span class="o">=</span><span class="s">{limit}/</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="p">&lt;/</span><span class="nt">label</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">label</span><span class="p">&gt;</span>Sort
</span></span><span class="line"><span class="cl">  <span class="p">&lt;</span><span class="nt">select</span> <span class="na">bind:value</span><span class="o">=</span><span class="s">{sort}</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;</span><span class="nt">option</span> <span class="na">value</span><span class="o">=</span><span class="s">&#34;asc&#34;</span><span class="p">&gt;</span>Ascending<span class="p">&lt;/</span><span class="nt">option</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;</span><span class="nt">option</span> <span class="na">value</span><span class="o">=</span><span class="s">&#34;desc&#34;</span><span class="p">&gt;</span>Descending<span class="p">&lt;/</span><span class="nt">option</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="p">&lt;/</span><span class="nt">select</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="p">&lt;/</span><span class="nt">label</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">posts-list</span> <span class="na">limit</span><span class="o">=</span><span class="s">{limit}</span> <span class="na">sort</span><span class="o">=</span><span class="s">{sort}</span> <span class="na">on:like-post</span><span class="o">=</span><span class="s">{onLikePost}</span><span class="p">&gt;&lt;/</span><span class="nt">posts-list</span><span class="p">&gt;</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">label</span><span class="p">&gt;</span>Posts per page
</span></span><span class="line"><span class="cl">  <span class="p">&lt;</span><span class="nt">input</span> <span class="na">type</span><span class="o">=</span><span class="s">&#34;number&#34;</span> <span class="na">step</span><span class="o">=</span><span class="s">&#34;10&#34;</span> <span class="na">v-model</span><span class="o">=</span><span class="s">&#34;limit&#34;</span><span class="p">/&gt;</span>
</span></span><span class="line"><span class="cl"><span class="p">&lt;/</span><span class="nt">label</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">label</span><span class="p">&gt;</span>Sort
</span></span><span class="line"><span class="cl">  <span class="p">&lt;</span><span class="nt">select</span> <span class="na">v-model</span><span class="o">=</span><span class="s">&#34;sort&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;</span><span class="nt">option</span> <span class="na">value</span><span class="o">=</span><span class="s">&#34;asc&#34;</span><span class="p">&gt;</span>Ascending<span class="p">&lt;/</span><span class="nt">option</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;</span><span class="nt">option</span> <span class="na">value</span><span class="o">=</span><span class="s">&#34;desc&#34;</span><span class="p">&gt;</span>Descending<span class="p">&lt;/</span><span class="nt">option</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="p">&lt;/</span><span class="nt">select</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="p">&lt;/</span><span class="nt">label</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">posts-list</span> <span class="na">limit</span><span class="o">=</span><span class="s">&#34;limit&#34;</span> <span class="na">sort</span><span class="o">=</span><span class="s">&#34;sort&#34;</span> <span class="err">@</span><span class="na">like-post</span><span class="o">=</span><span class="s">&#34;onLikePost&#34;</span><span class="p">&gt;&lt;/</span><span class="nt">posts-list</span><span class="p">&gt;</span>
</span></span></code></pre></div></code-tabs>
<p>You can write complex single-page apps with just Apollo Elements. Each component manages it&rsquo;s own internal state while using a templating system like <code>lit-html</code> or an old-school JavaScript framework to hook up properties and events, and the Apollo cache for <a href="https://apolloelements.dev/guides/usage/local-state/">managing client-side state</a> more generally.</p>
<h2 id="learn-more">Learn More</h2>
<p>Interested to learn more? Read our <a href="https://apolloelements.dev/guides/">getting started guide</a> to find out how your team can bring GraphQL to your web app one web component at a time. Or if you&rsquo;ve already started, check out the <a href="https://apolloelements.dev/api/">API docs</a> for the low-down on how components work using your favourite web component library.</p>
<p>So dive in, start building GraphQL and web components into your app today!</p>
]]></content:encoded>
      <category>graphql</category>
      <category>webcomponents</category>
      <category>interop</category>
      <category>custom elements</category>
    </item><item>
      <title>Launching a Stellar Docs Site with Rocket</title>
      <link>https://apolloelements.dev/blog/launching-a-stellar-docs-site-with-rocket/</link>
      <pubDate>Tue, 29 Dec 2020 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/blog/launching-a-stellar-docs-site-with-rocket/</guid>
      <description>How I brought Apollo Element&#39;s documentation into the space age with 11ty and the Rocket meta-framework for web components.</description>
      
      <content:encoded><![CDATA[<p>Apollo Elements&rsquo; new docs site launches aboard the <a href="https://wip-rocket.netlify.app/">Modern Web Rocket</a>. It&rsquo;s a ground-up rewrite that puts users first and presents the best of what Apollo Elements has to offer. The new site has <a href="#live-demos-via-webcomponentsdev">live code demos</a>, <a href="/api/">API tables</a> generated from custom elements manifest files, a new light theme, <a href="#code-tabs">customizable snippet browser</a>, comprehensive component lifecycle documentation for <a href="/api/core/interfaces/query/lifecycle/">query</a>, <a href="/api/core/interfaces/mutation/lifecycle/">mutation</a>, and <a href="/api/core/interfaces/subscription/lifecycle/">subscription</a> elements, and more.</p>
<p>Read on to learn a little how the site was made, or just <a href="https://apolloelements.dev">dive in to the docs</a></p>
<h2 id="live-demos-via-webcomponentsdev">Live Demos via <a href="https://webcomponents.dev">webcomponents.dev</a></h2>
<p>The new site comes packed with live demos of query and mutation components. You&rsquo;ll find them in the guides pages and on the API docs, and even showing off framework interop on the front page. The &lt;div&gt;Riots team were incredibly helpful and accomodating. If you haven&rsquo;t tried out their stuff, give it a shot soon, it&rsquo;s quality software. One note, I have a lot of plans in this regard, so stay in touch.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ts" data-lang="ts"><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">useQuery</span><span class="p">,</span> <span class="nx">component</span><span class="p">,</span> <span class="nx">html</span> <span class="p">}</span> <span class="kr">from</span> <span class="s1">&#39;@apollo-elements/haunted&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">HelloQuery</span> <span class="p">}</span> <span class="kr">from</span> <span class="s1">&#39;./Hello.query.graphql&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">HelloQueryElement() {</span>
</span></span><span class="line"><span class="cl">  <span class="kr">const</span> <span class="p">{</span> <span class="nx">data</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">useQuery</span><span class="p">(</span><span class="nx">HelloQuery</span><span class="p">,</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nx">variables</span><span class="o">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nx">name</span><span class="o">:</span> <span class="s1">&#39;Partner&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nx">greeting</span><span class="o">:</span> <span class="s1">&#39;Howdy&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">  <span class="p">});</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="kr">const</span> <span class="nx">greeting</span> <span class="o">=</span> <span class="nx">data</span><span class="o">?</span><span class="p">.</span><span class="nx">hello</span><span class="o">?</span><span class="p">.</span><span class="nx">greeting</span> <span class="o">??</span> <span class="s1">&#39;hello&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="kr">const</span> <span class="nx">name</span> <span class="o">=</span> <span class="nx">data</span><span class="o">?</span><span class="p">.</span><span class="nx">hello</span><span class="o">?</span><span class="p">.</span><span class="nx">name</span> <span class="o">??</span> <span class="s1">&#39;world&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="k">return</span> <span class="nx">html</span><span class="sb">`
</span></span></span><span class="line"><span class="cl"><span class="sb">    &lt;span id=&#34;hello&#34;&gt;
</span></span></span><span class="line"><span class="cl"><span class="sb">      </span><span class="si">${</span><span class="nx">greeting</span><span class="si">}</span><span class="sb">, </span><span class="si">${</span><span class="nx">name</span><span class="si">}</span><span class="sb">!
</span></span></span><span class="line"><span class="cl"><span class="sb">    &lt;/span&gt;
</span></span></span><span class="line"><span class="cl"><span class="sb">  `</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nx">customElements</span><span class="p">.</span><span class="nx">define</span><span class="p">(</span><span class="s1">&#39;hello-query&#39;</span><span class="p">,</span> <span class="nx">component</span><span class="p">(</span><span class="nx">HelloQueryElement</span><span class="p">));</span>
</span></span></code></pre></div><h2 id="progressively-enhanced-code-snippets">Progressively Enhanced Code Snippets</h2>
<h3 id="code-copy">Code Copy</h3>
<p>Let&rsquo;s face it, when you come to a docs site, 90% of the time you&rsquo;re looking to copy a code snippet. I get it, &ldquo;great artists steal&rdquo;, etc. At first I wrapped markdown content in custom elements, and this did the trick.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-markdown" data-lang="markdown"><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">code-copy</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="s">```html
</span></span></span><span class="line"><span class="cl"><span class="s"></span><span class="p">&lt;</span><span class="nt">p</span><span class="p">&gt;</span>Hello, World!<span class="p">&lt;/</span><span class="nt">p</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="s">```</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">&lt;/</span><span class="nt">code-copy</span><span class="p">&gt;</span>
</span></span></code></pre></div><p>The &ldquo;copy code&rdquo; buttons sprinkled throughout the site are just that, content wrapped in custom elements.</p>
<p>The only downside to this approach was for me the author, since it added a bunch of noise to the markdown source. Using a technique called mdjs pioneered by my colleague Thomas Allmer, the founder of <a href="https://open-wc.org">Open Web Components</a>, I kept the custom elements but simplified the DX:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-markdown" data-lang="markdown"><span class="line"><span class="cl">``<span class="sb">`html copy
</span></span></span><span class="line"><span class="cl"><span class="sb">&lt;p&gt;Hello, World!&lt;/p&gt;
</span></span></span><span class="line"><span class="cl"><span class="sb">`</span>``
</span></span></code></pre></div><p>This produces the exact same HTML output as above, but with a much cleaner source format. The plugin which enables this lets me define arbitrary code mods for fenced code blocks, which I did for the code tabs and live demos.</p>
<h3 id="code-tabs">Code Tabs</h3>
<p>One of the guiding philosophies in this project is to give users more options. Want to create vanilla HTML elements? Use the <a href="/api/libraries/mixins/">mixins</a>! Don&rsquo;t want to use a global apollo client? Try the <a href="/api/components/apollo-client/"><code>&lt;apollo-client&gt;</code></a>. I wanted the docs site to reflect that, letting the user choose how they want to view the code examples.</p>
<p>Inspired by sites like the <a href="https://stripe.com/docs/api/authentication?lang=php">Stripe API Docs</a>, which let you choose which SDK to view snippets for, I developed the <code>&lt;code-tabs&gt;</code> web component. When users pick a library (e.g. <code>lit-apollo</code> or <code>haunted</code>), every other instance of <code>&lt;code-tabs&gt;</code> on the page updates and their preference is stored in localStorage.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-markdown" data-lang="markdown"><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">code-tabs</span> <span class="na">collection</span><span class="o">=</span><span class="s">&#34;web-langs&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">``<span class="sb">`html tab markup
</span></span></span><span class="line"><span class="cl"><span class="sb">&lt;title-crawl&gt;Hello, World&lt;/title-crawl&gt;
</span></span></span><span class="line"><span class="cl"><span class="sb">`</span>`<span class="sb">`
</span></span></span><span class="line"><span class="cl"><span class="sb">
</span></span></span><span class="line"><span class="cl"><span class="sb">`</span>`<span class="sb">`css tab style
</span></span></span><span class="line"><span class="cl"><span class="sb">title-crawl { color: rebeccapurple; }
</span></span></span><span class="line"><span class="cl"><span class="sb">`</span>`<span class="sb">`
</span></span></span><span class="line"><span class="cl"><span class="sb">
</span></span></span><span class="line"><span class="cl"><span class="sb">`</span>`<span class="sb">`js tab behaviour
</span></span></span><span class="line"><span class="cl"><span class="sb">import &#39;./title-crawl.js&#39;;
</span></span></span><span class="line"><span class="cl"><span class="sb">`</span>``
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">&lt;/</span><span class="nt">code-tabs</span><span class="p">&gt;</span>
</span></span></code></pre></div><p>Authors just specify which tab collection the element represents, and a Rocket/11ty plugin translates that to HTML. Specifically, each of those fenced code blocks gets translated to something like this HTML:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">code-tab</span> <span class="na">tab</span><span class="o">=</span><span class="s">&#34;html&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="na">data-item-index</span><span class="o">=</span><span class="s">&#34;0&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="na">data-id</span><span class="o">=</span><span class="s">&#34;markup&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="na">data-label</span><span class="o">=</span><span class="s">&#34;Markup&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="na">data-icon-href</span><span class="o">=</span><span class="s">&#34;/html-logo.svg&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="na">data-synonyms</span><span class="o">=</span><span class="s">&#34;html,structure&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="na">selected</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="p">&lt;</span><span class="nt">pre</span> <span class="na">class</span><span class="o">=</span><span class="s">&#34;language-html&#34;</span><span class="p">&gt;</span><span class="c">&lt;!-- parsed markdown snippet --&gt;</span><span class="p">&lt;/</span><span class="nt">pre</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="p">&lt;/</span><span class="nt">code-tab</span><span class="p">&gt;</span>
</span></span></code></pre></div><h2 id="where-weve-come-from">Where We&rsquo;ve Come From</h2>
<p>The original docs site was a simple affair composed of hand-written HTML, markdown code blocks, and API sheets generated by the good-old Polymer analyzer.</p>
<p>While it did the job, the tooling was growing rapidly out of date, so earlier in the year I upgraded the site using <a href="https://typedoc.org">TypeDoc</a> and the <a href="https://mipatterson.github.io/typedoc-plugin-pages/index.html">TypeDoc Pages</a> plugin for guides. The TypeDoc version of the site came with a bevy of new content: getting started guides, info about managing local state, considerations for building and bundling, etc. It was a major step forward for content, and the authoring experience with markdown and TypeDoc was great, but there were some major drawbacks.</p>
<p>Build times were slow - sometimes five minutes - due to some {% footnoteref &rsquo;typedoc-hacks&rsquo; &lsquo;I wrote some <a href="https://github.com/apollo-elements/apollo-elements/blob/5de7f7b7d2db6476675f304d6748c5af047ad1c2/scripts/fix-typedoc.ts#L74" target="_blank" rel="noopener noreferrer"><code>JSDOM</code> hacks</a> to remove the <code>HTMLElement</code> interface from the TypeScript declarations, since at the moment the TypeScript compiler insists on flattening mixin declarations.&rsquo; %}hacks{% endfootnoteref %} for cleaning up the final output. Worse was that users found it difficult to navigate, and ultimately the site failed to do what it set out to do - explain what Apollo Elements is and how to use it.</p>
<table>
  <thead>
      <tr>
          <th>Original</th>
          <th>TypeDoc</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><img src="./images/orig-site.png" alt="Screenshot of original docs site"></td>
          <td><img src="./images/typedoc-site.png" alt="Screenshot of typedoc site"></td>
      </tr>
  </tbody>
</table>
<p>I was pleased to get some specific and actionable feedback from several users. That spurred me on to take the next step. Fortunately, the tools I needed to do the job emerged just at that time.</p>
<h2 id="11ty-and-rocket">11ty and Rocket</h2>
<p>Throughout this period, my colleagues at <a href="https://open-wc.org">Open Web Components</a> were working on an alpha version of an 11ty meta-framework called <a href="https://wip-rocket.netlify.app/">Rocket</a> for publishing multipage sites, geared especially (though not exclusively) towards web component authors. I decided to take a look.</p>
<p>If you&rsquo;ve never heard of <a href="https://www.11ty.dev/">11ty</a> go check it out, it&rsquo;s been generating quite the buzz, and for good reason. It&rsquo;s superlative, astounding, ebullient fun. On more than one occasion while building this site I had to tear myself away to get other projects done. I also got to know <a href="https://mozilla.github.io/nunjucks/">nunjucks</a>, an HTML templating language with a silly name made by Mozilla. How cool!</p>
<p>{{ &lsquo;rocket&rsquo; | icon }}</p>
<p>Rocket is a modular system with overridable templates, which means you can pick and choose features you want a la carte, then customize them to suit your needs. And customize I did! As well as the code mods mentioned above, I added an 11ty filter to automatically <a href="https://github.com/jdvivar/eleventy-plugin-add-web-component-definitions/pull/5">import web component definitions</a> whenever they&rsquo;re used in a page&rsquo;s HTML, and another filter to <a href="https://github.com/apollo-elements/apollo-elements/blob/2fe8f5b983ea3c2403150c0a8ad3443e2c607c83/packages/docs/rocket-plugins/link-to-type.mjs#L1">automatically link type names</a> in TypeScript code blocks to their external API docs. All of those were good fun, but the secret sauce that makes this site useful is the <a href="/api/">API docs</a> section.</p>
<h2 id="custom-elements-manifest">Custom Elements Manifest</h2>
<p>The new site&rsquo;s API docs are based on the new v1 specification for <a href="https://github.com/webcomponents/custom-elements-manifest">custom elements manifests</a>, aka <code>custom-elements.json</code>, rather than direct introspection of classes à la TypeDoc. This means the docs are much more user-oriented, as they document the public methods and properties that users are most interested in, cutting out the noise of class heirarchies and overly-detailed type relationships.</p>
<p>There&rsquo;s strong tooling support for the previous v0 custom-elements.json format. While efforts are underway to develop an analyzer that outputs the new spec, I hand-wrote the manifests for this site, along with some automated transforms to express inheritance.</p>
<p>{{ &lsquo;robot&rsquo; | icon }}</p>
<p>Because Apollo Elements is a collection of packages that all implement the same interfaces, the data flow for custom elements manifests was mostly top-down. The hand-written <code>packages/interfaces/custom-elements-manifest.json</code>, is the primary source-of-truth. I copy it into the library packages, applying transforms that preserve inheritance and account for library-specific quirks to <code>docs/_data/@apollo-elements/*/custom-elements-manifest.json</code>.</p>
<p>There are some features of the docs which aren&rsquo;t specified by custom-elements-manifest, like <a href="https://2ality.com/2011/11/keyword-parameters.html">&rsquo;named parameters&rsquo;</a>. For those, I relied on the TypeScript type of the parameter, writing a transform which scans for param and return types, inserting a markdown document as the object&rsquo;s <code>description</code> field in the manifest. So far those references are by type name, and I maintain a single flat list of typenames, held as markdown documents in a directory. If I run into name collisions down the line, I&rsquo;ll have to rethink that.</p>
<p>From there, I created a self-contained Rocket preset containing njk templates, 11ty filters, and custom elements. The preset turns the manifest data into progressively-enhanced HTML, based on the markdown file structure in your 11ty directory. I hope to publish this preset soon, so other web component authors can use it on their sites.</p>
<p>Some major remaining hurdles:</p>
<ul>
<li>Customizing / hooking in to 11ty&rsquo;s layout phase from the markdown content (e.g. &ldquo;put this markdown content inside this layout block&rdquo; or &ldquo;render that layout block at this point in the markdown&rdquo; or &ldquo;use the layout content when building the page nav&rdquo;)</li>
<li>When tools catch up to the new spec, it seems to me that i&rsquo;ll still need to do some post processing in order to build in those markdown tables. The use case here is documenting &rsquo;named parameters&rsquo; or return types which are &lsquo;property bags&rsquo;</li>
<li>Some missing or unspecified flags on entities in the manifest spec (e.g. async, readonly) - issues opened (edited)</li>
<li>The structure of the API docs pages assumes one export per file and packages with index.js entrypoints. This doesn&rsquo;t cover every use case and will need to be reconsidered before publishing a generalized version.</li>
</ul>
<p>If you want to get involved, join the <a href="https://github.com/w3c/webcomponents-cg">web components community group</a>.</p>
<h2 id="challenges-and-awful-hacks">Challenges and Awful Hacks</h2>
<p>Along the way I met with some challenges. The <code>&lt;type-doc&gt;</code> web component I developed for the API docs produced a <abbr title="flash of unstyled content">FOUC</abbr> when the page loaded, before the custom element upgraded. To prevent this, I set its opacity to 0 until it became <code>:defined</code>, but this harmed <code>&lt;noscript&gt;</code> users. My solution was to add a special noscript stylesheet. Some more <a href="https://gist.github.com/bkardell/5583179826456ff799433c50b09410f1">work is needed on the platform side</a> to address this issue all the way, but this is a decent workaround in the mean time.</p>
<p>While I sorta dunked on TypeDoc a few paragraphs back for requiring hacks, they don&rsquo;t deserve it. TypeDoc is a great project and they&rsquo;re making really nice software, it just didn&rsquo;t exactly fit my use. And what&rsquo;s more, there were plenty of awful hacks needed on the 11ty side, to render the navigation menu using headings from the nunjucks layouts (i.e. not only from markdown content), and to copy in the custom element manifests on write. On the whole though, I found the workarounds I needed to employ with Rocket and 11ty to be fewer and less cringe-worthy, so 👍 to them!</p>
<h2 id="the-future">The Future</h2>
<p>There&rsquo;s still more work to do. Rocket is still in pre-release, and the work done here on Custom Elements manifests is preliminary as well. I&rsquo;ll need to publish and integrate the <code>&lt;code-copy&gt;</code> and <code>&lt;code-tabs&gt;</code> components into rocket, and gather some more use cases and insights around API docs, especially when it comes to mapping a single custom elements manifest to one-or-more docs pages.</p>
<h2 id="acknowledgements">Acknowledgements</h2>
<p>A number of people provided invaluable feedback on the site while it was under development, among them <a href="https://twitter.com/justinfagnani">Justin Fagnani</a> from the Polymer team, <a href="https://github.com/peschee">Peter Siska</a> from <a href="https://inventage.com/">Inventage</a>, and Vignesh from <a href="https://twitter.com/timecampus">Timecampus</a> provided invaluable feedback. Check out Vignesh&rsquo; <a href="https://medium.com/timecampus/graphql-diving-deep-c7c0abe608b2">blog series on GraphQL</a>. Uri and Dotan at <a href="https://the-guild.dev/">The Guild</a> provided encouragement and resources. If you&rsquo;re working with GraphQL, give The Guild a glance, you&rsquo;ll be glad you did. My collegues on the <a href="https://open-wc.org">Open Web Components</a> team were instrumental, as always, to everything I accomplished here.</p>
<style data-helmett>
  .icon.rocket {
    float: right;
    width: 150px;
    opacity: 0.75;
  }

  .icon.robot {
    width: 200px;
    opacity: 0.75;
    float: left;
    display: block;
    margin: 10px;
  }
</style>
]]></content:encoded>
      <category>graphql</category>
      <category>webcomponents</category>
      <category>rocket</category>
      <category>documentation</category>
      <category>11ty</category>
    </item><item>
      <title>Take GraphQL into Orbit with Apollo Elements 3</title>
      <link>https://apolloelements.dev/blog/take-graphql-into-orbit-with-apollo-elements-3/</link>
      <pubDate>Thu, 24 Sep 2020 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/blog/take-graphql-into-orbit-with-apollo-elements-3/</guid>
      <description>Build performant, data-driven apps with Apollo Client and Web Components</description>
      <enclosure url="https://dev-to-uploads.s3.amazonaws.com/i/r3qwfsz9gy2nlndy89gj.png" type="image/jpeg" />
      <content:encoded><![CDATA[<p>Apollo Elements 3 launches into orbit today with tonnes of new features. There&rsquo;s a <a href="https://apolloelements.dev">brand new docs site</a> complete with guides, full TypeScript support, app/component generators, and more.</p>
<p>Use Apollo Elements to write GraphQL-based apps using web components as the view layer. Apollo Elements supports <a href="https://lit.dev">lit</a>, <a href="https://hybrids.js.org">hybrids</a>, and gluon out of the box, or you can use the custom-element mixins to add support to any custom-element base class.</p>
<p>Apollo Elements 3 supports the new Apollo Client 3 with all it&rsquo;s enhancements to developer experience.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ts" data-lang="ts"><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">ApolloQuery</span> <span class="p">}</span> <span class="kr">from</span> <span class="s1">&#39;@apollo-elements/lit-apollo&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">customElement</span><span class="p">,</span> <span class="nx">html</span> <span class="p">}</span> <span class="kr">from</span> <span class="s1">&#39;lit-element&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">gql</span> <span class="p">}</span> <span class="kr">from</span> <span class="s1">&#39;@apollo/client/core&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">interface</span> <span class="nx">Data</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">name</span>: <span class="kt">string</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="nx">greeting</span>: <span class="kt">string</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">interface</span> <span class="nx">Variables</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">name?</span>: <span class="kt">string</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">@customElement</span><span class="p">(</span><span class="s1">&#39;hello-query&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="kr">class</span> <span class="nx">HelloQuery</span> <span class="kr">extends</span> <span class="nx">ApolloElement</span><span class="p">&lt;</span><span class="nt">Data</span><span class="p">,</span> <span class="na">Variables</span><span class="p">&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">query</span> <span class="o">=</span> <span class="nx">gql</span><span class="sb">`
</span></span></span><span class="line"><span class="cl"><span class="sb">    query HelloQuery($name: String) {
</span></span></span><span class="line"><span class="cl"><span class="sb">      name
</span></span></span><span class="line"><span class="cl"><span class="sb">      greeting
</span></span></span><span class="line"><span class="cl"><span class="sb">    }
</span></span></span><span class="line"><span class="cl"><span class="sb">  `</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="nx">render() {</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="nx">html</span><span class="sb">`
</span></span></span><span class="line"><span class="cl"><span class="sb">      &lt;p&gt;
</span></span></span><span class="line"><span class="cl"><span class="sb">        </span><span class="si">${</span><span class="k">this</span><span class="p">.</span><span class="nx">data</span><span class="o">?</span><span class="p">.</span><span class="nx">greeting</span> <span class="o">??</span> <span class="s1">&#39;Hello&#39;</span><span class="si">}</span><span class="sb">,
</span></span></span><span class="line"><span class="cl"><span class="sb">        </span><span class="si">${</span><span class="k">this</span><span class="p">.</span><span class="nx">data</span><span class="o">?</span><span class="p">.</span><span class="nx">name</span> <span class="o">??</span> <span class="s1">&#39;Friend&#39;</span><span class="si">}</span><span class="sb">
</span></span></span><span class="line"><span class="cl"><span class="sb">      &lt;/p&gt;
</span></span></span><span class="line"><span class="cl"><span class="sb">    `</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><h2 id="examples">Examples</h2>
<p>Check out these example apps:</p>
<ul>
<li><a href="https://leeway.apolloelements.dev">leeway</a> is a simple chat app that uses <a href="https://apolloelements.dev/guides/usage/subscriptions/">GraphQL subscriptions</a> for real-time updates</li>
<li><a href="https://launchctl.apolloelements.dev">launchctl</a> shows you information about SpaceX launches using the unofficial <a href="https://api.spacex.land/graphql">spacex.land</a> API</li>
</ul>
<h2 id="app-generator">App Generator</h2>
<p>Want to get started writing your GraphQL app in a snap? Try our new app generator</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">npm init @apollo-elements
</span></span></code></pre></div><p>So strap into your crash couch and feel that juice coming on, it&rsquo;s time for a hard burn past the GraphQL gate with <a href="https://apolloelements.dev">Apollo Elements</a></p>
]]></content:encoded>
      <category>graphql</category>
      <category>webcomponents</category>
      <category>opensource</category>
    </item><item>
      <title>Announcing Apollo Elements</title>
      <link>https://apolloelements.dev/blog/announcing-apollo-elements/</link>
      <pubDate>Wed, 16 Jan 2019 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/blog/announcing-apollo-elements/</guid>
      <description>Create web components that leverage the power of Apollo GraphQL.</description>
      <enclosure url="https://thepracticaldev.s3.amazonaws.com/i/rk6u6o9jibsv4vo3cpgb.png" type="image/jpeg" />
      <content:encoded><![CDATA[<p><sup dir="rtl"><abbr title="בסייעתא דשמייא">בס״ד</abbr></sup></p>
<blockquote>
<p><strong>Note</strong>: This is a historical blog post from 2019. Some information may be outdated. For current documentation and best practices, please visit the <a href="https://apolloelements.dev">Apollo Elements documentation</a>.</p></blockquote>
<p>Today I published version 0.0.1 of <code>apollo-elements</code>, a collection of packages that help you create web components connected to {% footnoteref &ldquo;apollo&rdquo; &ldquo;Apollo Elements is a community project maintained by myself, it&rsquo;s not affiliated with Meteor.&rdquo; %}Apollo GraphQL{% endfootnoteref %}.</p>
<p>{% github apollo-elements/apollo-elements %}</p>
<p>Apollo Elements handles the plumbing between web components libraries like <code>lit-element</code> or <code>hybrids</code> and Apollo Client, so you can concentrate on building your app.</p>
<p>If you&rsquo;re new to web components, take a <abbr title="peek">👀</abbr> at my &ldquo;Let&rsquo;s Build Web Components&rdquo; series to get up to speed:</p>
<p>{% dev <a href="https://dev.to/bennypowers/lets-build-web-components-part-1-the-standards-3e85">https://dev.to/bennypowers/lets-build-web-components-part-1-the-standards-3e85</a> %}</p>
<h2 id="connected-components">Connected Components</h2>
<p>In a component-based app, each component can derive its state from some separate state storage. For example, you can create components which connect to a Redux or MobX store and subscribe to changes to their piece of the state puzzle.</p>
<p>GraphQL&rsquo;s flexible and extensible syntax is a natural fit for component based design, and Apollo&rsquo;s powerful implementation lets us easily make the connection between GraphQL data and our components. Using <code>apollo-link-state</code>, you can even get rid of client-side state containers like redux altogether and <em>query your entire component state from the apollo cache</em>.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-graphql" data-lang="graphql"><span class="line"><span class="cl"><span class="kd">query</span><span class="w"> </span><span class="nc">UserProfilePage</span><span class="p">(</span><span class="nv">$userId</span><span class="p">:</span><span class="w"> </span><span class="nc">ID</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="py">session</span><span class="w"> </span><span class="nd">@client</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="py">token</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="py">expiresAt</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="py">id</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="py">user</span><span class="p">(</span><span class="py">id</span><span class="p">:</span><span class="w"> </span><span class="nv">$id</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nc">name</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="py">avatar</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="py">friends</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="py">name</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="py">id</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><h2 id="show-me-the-code">Show Me The Code</h2>
<p>Now, with Apollo Elements, you can get up and running building connected components. You provide a GraphQL document and a custom element {% footnoteref &ldquo;hybrids-class&rdquo; &ldquo;Or in the case of hybrids, all you need is a render function.&rdquo; %}class{% endfootnoteref %} that handles templating, and you&rsquo;re good to go.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">ApolloQuery</span><span class="p">,</span> <span class="nx">html</span> <span class="p">}</span> <span class="nx">from</span> <span class="s1">&#39;@apollo-elements/lit-apollo&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// A component that uses ApolloSubscription to update
</span></span></span><span class="line"><span class="cl"><span class="c1">// when users go on or offline.
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kr">import</span> <span class="s1">&#39;./user-online-status.js&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="s1">&#39;./loading-spinner.js&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="cm">/**
</span></span></span><span class="line"><span class="cl"><span class="cm"> * `&lt;user-profile-page&gt;` Shows a user&#39;s profile, as well as a list
</span></span></span><span class="line"><span class="cl"><span class="cm"> * of their friends which display&#39;s each one&#39;s online status via a
</span></span></span><span class="line"><span class="cl"><span class="cm"> * GraphQL subscription.
</span></span></span><span class="line"><span class="cl"><span class="cm"> * @extends ApolloQuery
</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span>
</span></span><span class="line"><span class="cl"><span class="kr">class</span> <span class="nx">UserProfilePage</span> <span class="kr">extends</span> <span class="nx">ApolloQuery</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">render</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kr">const</span> <span class="p">{</span> <span class="nx">loading</span><span class="p">,</span> <span class="nx">data</span> <span class="p">}</span> <span class="o">=</span> <span class="k">this</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="p">(</span>
</span></span><span class="line"><span class="cl">      <span class="p">(</span><span class="nx">loading</span> <span class="o">||</span> <span class="o">!</span><span class="nx">data</span><span class="p">)</span> <span class="o">?</span> <span class="nx">html</span><span class="sb">`&lt;loading-spinner&gt;&lt;/loading-spinner&gt;`</span>
</span></span><span class="line"><span class="cl">      <span class="o">!</span><span class="nx">data</span><span class="p">.</span><span class="nx">user</span> <span class="o">?</span> <span class="o">:</span> <span class="nx">html</span><span class="sb">`&lt;login-form&gt;&lt;/login-form&gt;`</span>
</span></span><span class="line"><span class="cl">    <span class="o">:</span> <span class="nx">html</span><span class="sb">`
</span></span></span><span class="line"><span class="cl"><span class="sb">        &lt;h1&gt;Hello, </span><span class="si">${</span><span class="nx">data</span><span class="p">.</span><span class="nx">user</span><span class="p">.</span><span class="nx">name</span><span class="si">}</span><span class="sb">&lt;/h1&gt;
</span></span></span><span class="line"><span class="cl"><span class="sb">        &lt;profile-image src=&#34;</span><span class="si">${</span><span class="nx">data</span><span class="p">.</span><span class="nx">user</span><span class="p">.</span><span class="nx">avatar</span><span class="si">}</span><span class="sb">&#34;&gt;&lt;/profile-image&gt;
</span></span></span><span class="line"><span class="cl"><span class="sb">        &lt;h2&gt;Who&#39;s Online?&lt;/h2&gt;
</span></span></span><span class="line"><span class="cl"><span class="sb">        &lt;dl&gt;</span><span class="si">${</span><span class="nx">data</span><span class="p">.</span><span class="nx">user</span><span class="p">.</span><span class="nx">friends</span><span class="p">.</span><span class="nx">map</span><span class="p">(({</span><span class="nx">id</span><span class="p">,</span> <span class="nx">name</span><span class="si">}</span><span class="sb">) =&gt; html`</span>
</span></span><span class="line"><span class="cl">          <span class="o">&lt;</span><span class="nx">dt</span><span class="o">&gt;</span><span class="nx">$</span><span class="p">{</span><span class="nx">name</span><span class="p">}</span><span class="o">&lt;</span><span class="err">/dt&gt;</span>
</span></span><span class="line"><span class="cl">          <span class="o">&lt;</span><span class="nx">dd</span><span class="o">&gt;&lt;</span><span class="nx">user</span><span class="o">-</span><span class="nx">online</span><span class="o">-</span><span class="nx">status</span> <span class="nx">id</span><span class="o">=</span><span class="s2">&#34;${id}&#34;</span><span class="o">&gt;&lt;</span><span class="err">/user-online-status&gt;&lt;/dd&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="sb">`)}&lt;/dl&gt;
</span></span></span><span class="line"><span class="cl"><span class="sb">      `</span>
</span></span><span class="line"><span class="cl">    <span class="p">);</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="nx">updated</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// get the currently logged-in user&#39;s id from the `@client` query.
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="kr">const</span> <span class="p">{</span> <span class="nx">id</span> <span class="p">}</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">id</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// setting variables updates the query.
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="k">if</span> <span class="p">(</span><span class="nx">id</span><span class="p">)</span> <span class="k">this</span><span class="p">.</span><span class="nx">variables</span> <span class="o">=</span> <span class="p">{</span> <span class="nx">id</span> <span class="p">};</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nx">customElements</span><span class="p">.</span><span class="nx">define</span><span class="p">(</span><span class="s1">&#39;user-profile-page&#39;</span><span class="p">,</span> <span class="nx">UserProfilePage</span><span class="p">);</span>
</span></span></code></pre></div><p>Once you&rsquo;ve added your elements to the page, set their <code>query</code> property to a GraphQL document and you&rsquo;re set.</p>
<h3 id="inline-graphql-scripts">Inline GraphQL Scripts</h3>
<p>You can even do neat little optional tricks like defining your queries declaratively in HTML with inline GraphQL:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">user-profile-page</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="p">&lt;</span><span class="nt">script</span> <span class="na">type</span><span class="o">=</span><span class="s">&#34;application/graphql&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nx">query</span> <span class="nx">UserProfilePage</span><span class="p">(</span><span class="nx">$userId</span><span class="o">:</span> <span class="nx">ID</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nx">session</span> <span class="err">@</span><span class="nx">client</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nx">token</span>
</span></span><span class="line"><span class="cl">        <span class="nx">expiresAt</span>
</span></span><span class="line"><span class="cl">        <span class="nx">id</span>
</span></span><span class="line"><span class="cl">      <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">      <span class="nx">user</span><span class="p">(</span><span class="nx">id</span><span class="o">:</span> <span class="nx">$id</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nx">name</span>
</span></span><span class="line"><span class="cl">        <span class="nx">avatar</span>
</span></span><span class="line"><span class="cl">        <span class="nx">friends</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">          <span class="nx">name</span>
</span></span><span class="line"><span class="cl">          <span class="nx">id</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">      <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">  <span class="p">&lt;/</span><span class="nt">script</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="p">&lt;/</span><span class="nt">user-profile-page</span><span class="p">&gt;</span>
</span></span></code></pre></div><p>Cute, right?</p>
<h2 id="support-for-multiple-web-component-libraries">Support for Multiple Web Component Libraries</h2>
<p>Apollo Elements grew out of <code>lit-apollo</code>, but I wasn&rsquo;t content with supporting a single component class. Version 0 shipped, renamed and rebranded, with support for <a href="https://dev.to/bennypowers/lets-build-web-components-part-5-litelement-906"><code>lit-element</code></a>, <a href="https://dev.to/bennypowers/lets-build-web-components-part-6-gluon-27ll"><code>GluonElement</code></a>, and <a href="https://dev.to/bennypowers/lets-build-web-components-part-7-hybrids-187l"><code>hybrids</code></a>. It also&rsquo;s got some <a href="https://dev.to/bennypowers/lets-build-web-components-part-4-polymer-library-4dk2">Polymer</a>-style two-way binding elements so you can expose the apollo state in your templates with <code>{{data}}</code> syntax.</p>
<p>But the goal here was to give you, the developer, more options. If none of the above are what you&rsquo;re looking for, Apollo Elements also provides <a href="http://justinfagnani.com/2015/12/21/real-mixins-with-javascript-classes/">class mixins</a> that let you get up and running with any vanilla-like component class, or even good-old-fashioned <code>HTMLElement</code>, if you really wanted.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">ApolloMutationMixin</span> <span class="p">}</span> <span class="nx">from</span> <span class="s1">&#39;@apollo-elements/mixins&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="nx">gql</span> <span class="nx">from</span> <span class="s1">&#39;graphql-tag&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">mutation</span> <span class="o">=</span> <span class="nx">gql</span><span class="sb">`
</span></span></span><span class="line"><span class="cl"><span class="sb">  mutation SendMessage($message: String!) {
</span></span></span><span class="line"><span class="cl"><span class="sb">    sendMessage(message: $message) {
</span></span></span><span class="line"><span class="cl"><span class="sb">      message
</span></span></span><span class="line"><span class="cl"><span class="sb">      date
</span></span></span><span class="line"><span class="cl"><span class="sb">    }
</span></span></span><span class="line"><span class="cl"><span class="sb">  }
</span></span></span><span class="line"><span class="cl"><span class="sb">`</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">template</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">createElement</span><span class="p">(</span><span class="s1">&#39;template&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="nx">template</span><span class="p">.</span><span class="nx">innerHTML</span> <span class="o">=</span> <span class="sb">`
</span></span></span><span class="line"><span class="cl"><span class="sb">  &lt;style&gt;
</span></span></span><span class="line"><span class="cl"><span class="sb">    :host([error]) #input {
</span></span></span><span class="line"><span class="cl"><span class="sb">      border: 1px solid red;
</span></span></span><span class="line"><span class="cl"><span class="sb">    }
</span></span></span><span class="line"><span class="cl"><span class="sb">
</span></span></span><span class="line"><span class="cl"><span class="sb">    details {
</span></span></span><span class="line"><span class="cl"><span class="sb">      display: none;
</span></span></span><span class="line"><span class="cl"><span class="sb">    }
</span></span></span><span class="line"><span class="cl"><span class="sb">
</span></span></span><span class="line"><span class="cl"><span class="sb">    :host([error]) details {
</span></span></span><span class="line"><span class="cl"><span class="sb">      display: block;
</span></span></span><span class="line"><span class="cl"><span class="sb">    }
</span></span></span><span class="line"><span class="cl"><span class="sb">  &lt;/style&gt;
</span></span></span><span class="line"><span class="cl"><span class="sb">  &lt;label&gt;Message&lt;input id=&#34;input&#34;/&gt;&lt;/label&gt;
</span></span></span><span class="line"><span class="cl"><span class="sb">  &lt;details&gt;
</span></span></span><span class="line"><span class="cl"><span class="sb">    &lt;summary&gt;Error!&lt;/summary&gt;
</span></span></span><span class="line"><span class="cl"><span class="sb">    &lt;span id=&#34;error&#34;&gt;&lt;/span&gt;
</span></span></span><span class="line"><span class="cl"><span class="sb">  &lt;/details&gt;
</span></span></span><span class="line"><span class="cl"><span class="sb">`</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">class</span> <span class="nx">ChatInput</span> <span class="kr">extends</span> <span class="nx">ApolloMutationMixin</span><span class="p">(</span><span class="nx">HTMLElement</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">get</span> <span class="nx">input</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">shadowRoot</span> <span class="o">&amp;&amp;</span> <span class="k">this</span><span class="p">.</span><span class="nx">shadowRoot</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">&#39;input&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="nx">constructor</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kr">super</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">    <span class="k">this</span><span class="p">.</span><span class="nx">mutation</span> <span class="o">=</span> <span class="nx">mutation</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">this</span><span class="p">.</span><span class="nx">onKeyup</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">onKeyup</span><span class="p">.</span><span class="nx">bind</span><span class="p">(</span><span class="k">this</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">this</span><span class="p">.</span><span class="nx">attachShadow</span><span class="p">({</span> <span class="nx">mode</span><span class="o">:</span> <span class="s1">&#39;open&#39;</span> <span class="p">})</span>
</span></span><span class="line"><span class="cl">    <span class="k">this</span><span class="p">.</span><span class="nx">shadowRoot</span><span class="p">.</span><span class="nx">appendChild</span><span class="p">(</span><span class="nx">template</span><span class="p">.</span><span class="nx">content</span><span class="p">.</span><span class="nx">cloneNode</span><span class="p">(</span><span class="kc">true</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">    <span class="k">this</span><span class="p">.</span><span class="nx">input</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="s1">&#39;keyup&#39;</span><span class="p">,</span> <span class="k">this</span><span class="p">.</span><span class="nx">onKeyup</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="nx">onKeyup</span><span class="p">({</span> <span class="nx">key</span><span class="p">,</span> <span class="nx">target</span><span class="o">:</span> <span class="p">{</span> <span class="nx">value</span><span class="o">:</span> <span class="nx">message</span> <span class="p">}</span> <span class="p">})</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="nx">key</span> <span class="o">!==</span> <span class="s1">&#39;Enter&#39;</span><span class="p">)</span> <span class="k">return</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">this</span><span class="p">.</span><span class="nx">variables</span> <span class="o">=</span> <span class="p">{</span> <span class="nx">message</span> <span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="k">this</span><span class="p">.</span><span class="nx">mutate</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="c1">// Override implementation of `onCompleted` if desired.
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="c1">// Alternatively, use a setter.
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="nx">onCompleted</span><span class="p">({</span> <span class="nx">message</span><span class="p">,</span> <span class="nx">date</span> <span class="p">})</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">this</span><span class="p">.</span><span class="nx">input</span><span class="p">.</span><span class="nx">value</span> <span class="o">=</span> <span class="s1">&#39;&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="c1">// Override implementation of `onError` if desired.
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="c1">// Alternatively, use a setter.
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="nx">onError</span><span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">this</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">&#39;error&#39;</span><span class="p">,</span> <span class="nx">error</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">this</span><span class="p">.</span><span class="nx">shadowRoot</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">&#39;error&#39;</span><span class="p">).</span><span class="nx">textContent</span> <span class="o">=</span>
</span></span><span class="line"><span class="cl">      <span class="sb">`Error when sending message: </span><span class="si">${</span> <span class="nx">error</span> <span class="si">}</span><span class="sb">`</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Plans are in the works to support even more web component libraries and frameworks in the future, so watch the repo for releases.</p>
<p>So go ahead - install the package which fits your project best:</p>
<ul>
<li><a href="https://npmjs.org/package/@apollo-elements/mixins"><code>@apollo-elements/mixins</code></a> for class mixins</li>
<li><a href="https://npmjs.org/package/@apollo-elements/lit-apollo"><code>@apollo-elements/lit-apollo</code></a> for lit-element</li>
<li><a href="https://npmjs.org/package/@apollo-elements/hybrids"><code>@apollo-elements/hybrids</code></a> for Hybrids</li>
<li><a href="https://npmjs.org/package/@apollo-elements/gluon"><code>@apollo-elements/gluon</code></a> for Gluon</li>
<li><a href="https://npmjs.org/package/@apollo-elements/polymer"><code>@apollo-elements/polymer</code></a> for Polymer-style notifying elements</li>
</ul>
<h2 id="demo">Demo</h2>
<p>Want to see it in action? I built a simple chat app demo that uses GraphQL subscriptions and renders it&rsquo;s components using lit-element.</p>
<p><a href="https://lit-apollo-subscriptions.herokuapp.com"><code>#leeway</code></a> is a progressive web app that uses <code>lit-apollo</code> to make it easier for you to avoid doing actual work. Check out the <a href="https://gitlab.com/bennyp/demo-lit-apollo-subscriptions">source repo</a> for an example of how to build apps with Apollo Elements. The demo includes:</p>
<ul>
<li><abbr title="server side rendering">SSR</abbr></li>
<li>Code Splitting</li>
<li>Aggressive minification, including <code>lit-html</code> template literals</li>
<li>CSS-in-CSS ( e.g. <code>import shared from '../shared-styles.css';</code>)</li>
<li>GQL-in-GQL ( e.g. <code>import query from './my-component-query.graphql';</code>)</li>
<li>GraphQL Subscriptions over websocket</li>
</ul>
<p><a href="https://github.com/apollo-elements/apollo-elements/files/2825459/lit-apollo-subscriptions.herokuapp.com-20190203T132249.zip"><img src="https://user-images.githubusercontent.com/1466420/52176144-5c25f280-27b7-11e9-8e14-290651f98e36.png" alt="Lighthouse Scores: 98 (performance), 100 (accessibility), 93 (best practises), 100 (SEO), 12/12 (PWA)"></a></p>
<p>So try out <code>apollo-elements</code> today!</p>
]]></content:encoded>
      <category>webcomponents</category>
      <category>graphql</category>
      <category>apollo</category>
      <category>opensource</category>
    </item><item>
      <title></title>
      <link>https://apolloelements.dev/api/core/helpers/events/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/api/core/helpers/events/</guid>
      <description>Events for Apollo Elements</description>
      
      <content:encoded><![CDATA[<!-- ----------------------------------------------------------------------------------------
     Welcome! This file includes automatically generated API documentation.
     To edit the docs that appear within, find the original source file under `packages/*`,
     corresponding to the package name and module in this YAML front-matter block.
     Thank you for your interest in Apollo Elements 😁
------------------------------------------------------------------------------------------ -->
<h1 id="core--helpers--events">Core &raquo; Helpers &raquo; Events</h1>
<p><code>&lt;apollo-client&gt;</code> listens for <code>apollo-element-connected</code> and <code>apollo-element-disconnected</code> events to manage their client reference.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ts" data-lang="ts"><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">APOLLO_ELEMENTS</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Set</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">window</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="s1">&#39;apollo-element-connected&#39;</span><span class="p">,</span> <span class="nx">event</span> <span class="o">=&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="nx">APOLLO_ELEMENTS</span><span class="p">.</span><span class="nx">add</span><span class="p">(</span><span class="nx">event</span><span class="p">.</span><span class="nx">detail</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">window</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="s1">&#39;apollo-element-disconnected&#39;</span><span class="p">,</span> <span class="nx">event</span> <span class="o">=&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="nx">APOLLO_ELEMENTS</span><span class="p">.</span><span class="k">delete</span><span class="p">(</span><span class="nx">event</span><span class="p">.</span><span class="nx">detail</span><span class="p">));</span>
</span></span></code></pre></div>]]></content:encoded>
    </item><item>
      <title></title>
      <link>https://apolloelements.dev/api/libraries/hybrids/hybrids-app/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/api/libraries/hybrids/hybrids-app/</guid>
      <description>&lt;script type=&#34;module&#34; src=&#34;client.js&#34;&gt;&lt;/script&gt;
&lt;script type=&#34;module&#34; src=&#34;users-list.js&#34;&gt;&lt;/script&gt;
&lt;users-list&gt;&lt;/users-list&gt;</description>
      
      <content:encoded><![CDATA[<script type="module" src="client.js"></script>
<script type="module" src="users-list.js"></script>
<users-list></users-list>
]]></content:encoded>
    </item><item>
      <title></title>
      <link>https://apolloelements.dev/api/libraries/hybrids/hybrids-query/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/api/libraries/hybrids/hybrids-query/</guid>
      <description>&lt;script type=&#34;module&#34; src=&#34;client.js&#34;&gt;&lt;/script&gt;
&lt;script type=&#34;module&#34; src=&#34;users-list.js&#34;&gt;&lt;/script&gt;
&lt;users-list&gt;&lt;/users-list&gt;</description>
      
      <content:encoded><![CDATA[<script type="module" src="client.js"></script>
<script type="module" src="users-list.js"></script>
<users-list></users-list>
]]></content:encoded>
    </item><item>
      <title></title>
      <link>https://apolloelements.dev/api/libraries/hybrids/mutation-factory/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/api/libraries/hybrids/mutation-factory/</guid>
      <description>&lt;script type=&#34;module&#34; src=&#34;client.js&#34;&gt;&lt;/script&gt;
&lt;script type=&#34;module&#34; src=&#34;add-user.js&#34;&gt;&lt;/script&gt;
&lt;add-user&gt;&lt;/add-user&gt;</description>
      
      <content:encoded><![CDATA[<script type="module" src="client.js"></script>
<script type="module" src="add-user.js"></script>
<add-user></add-user>
]]></content:encoded>
    </item><item>
      <title></title>
      <link>https://apolloelements.dev/api/libraries/hybrids/subscription-factory/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/api/libraries/hybrids/subscription-factory/</guid>
      <description>&lt;script type=&#34;module&#34; src=&#34;client.js&#34;&gt;&lt;/script&gt;
&lt;script type=&#34;module&#34; src=&#34;user-added.js&#34;&gt;&lt;/script&gt;
&lt;user-added&gt;&lt;/user-added&gt;
&lt;button disabled&gt;Add User&lt;/button&gt;
&lt;small&gt;&lt;em&gt;This demo is blocked by an &lt;a target=&#34;_blank&#34; rel=&#34;nofollow noreferer&#34; href=&#34;https://github.com/apollographql/apollo-feature-requests/issues/299&#34;&gt;issue in &lt;code&gt;SchemaLink&lt;/code&gt;&lt;/a&gt;.&lt;/small&gt;</description>
      
      <content:encoded><![CDATA[<script type="module" src="client.js"></script>
<script type="module" src="user-added.js"></script>
<user-added></user-added>
<button disabled>Add User</button>
<small><em>This demo is blocked by an <a target="_blank" rel="nofollow noreferer" href="https://github.com/apollographql/apollo-feature-requests/issues/299">issue in <code>SchemaLink</code></a>.</small>
]]></content:encoded>
    </item><item>
      <title></title>
      <link>https://apolloelements.dev/api/libraries/mixins/apollo-client-mixin/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/api/libraries/mixins/apollo-client-mixin/</guid>
      <description>&lt;!-- ----------------------------------------------------------------------------------------
     Welcome! This file includes automatically generated API documentation.
     To edit the docs that appear within, find the original source file under `packages/*`,
     corresponding to the package name and module in this YAML front-matter block.
     Thank you for your interest in Apollo Elements 😁
------------------------------------------------------------------------------------------ --&gt;
&lt;h1 id=&#34;web-component-libraries--class-mixins--apolloclientmixin&#34;&gt;Web Component Libraries &amp;raquo; Class Mixins &amp;raquo; ApolloClientMixin&lt;/h1&gt;
&lt;p&gt;Mixin which associates an &lt;code&gt;ApolloClient&lt;/code&gt; instance with a custom element class.&lt;/p&gt;
&lt;p&gt;See &lt;a href=&#34;https://apolloelements.dev/guides/usage/apollo-client/&#34;&gt;Usage: Apollo Client&lt;/a&gt; for examples and alternatives.&lt;/p&gt;</description>
      
      <content:encoded><![CDATA[<!-- ----------------------------------------------------------------------------------------
     Welcome! This file includes automatically generated API documentation.
     To edit the docs that appear within, find the original source file under `packages/*`,
     corresponding to the package name and module in this YAML front-matter block.
     Thank you for your interest in Apollo Elements 😁
------------------------------------------------------------------------------------------ -->
<h1 id="web-component-libraries--class-mixins--apolloclientmixin">Web Component Libraries &raquo; Class Mixins &raquo; ApolloClientMixin</h1>
<p>Mixin which associates an <code>ApolloClient</code> instance with a custom element class.</p>
<p>See <a href="/guides/usage/apollo-client/">Usage: Apollo Client</a> for examples and alternatives.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">ApolloQueryElement</span> <span class="p">}</span> <span class="nx">from</span> <span class="s1">&#39;@apollo-elements/interfaces&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">ApolloClientMixin</span> <span class="p">}</span> <span class="nx">from</span> <span class="s1">&#39;@apollo-elements/mixins/apollo-client-mixin&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">createApolloClient</span> <span class="p">}</span> <span class="nx">from</span> <span class="s1">&#39;@apollo-elements/core/lib/create-apollo-client&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">client</span> <span class="o">=</span> <span class="nx">createApolloClient</span><span class="p">({</span> <span class="nx">uri</span><span class="o">:</span> <span class="s1">&#39;/graphql&#39;</span> <span class="p">});</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">export</span> <span class="kr">class</span> <span class="nx">WithClientElement</span> <span class="kr">extends</span>
</span></span><span class="line"><span class="cl">  <span class="nx">ApolloClientMixin</span><span class="p">(</span><span class="nx">ApolloQueryElement</span><span class="p">,</span> <span class="nx">client</span><span class="p">)</span> <span class="p">{</span> <span class="p">}</span>
</span></span></code></pre></div>]]></content:encoded>
    </item><item>
      <title></title>
      <link>https://apolloelements.dev/api/libraries/mixins/type-policies-mixin/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/api/libraries/mixins/type-policies-mixin/</guid>
      <description>&lt;!-- ----------------------------------------------------------------------------------------
     Welcome! This file includes automatically generated API documentation.
     To edit the docs that appear within, find the original source file under `packages/*`,
     corresponding to the package name and module in this YAML front-matter block.
     Thank you for your interest in Apollo Elements 😁
------------------------------------------------------------------------------------------ --&gt;
&lt;h1 id=&#34;web-component-libraries--class-mixins--typepoliciesmixin&#34;&gt;Web Component Libraries &amp;raquo; Class Mixins &amp;raquo; TypePoliciesMixin&lt;/h1&gt;
&lt;p&gt;Optional mixin which lets you declare type policies for a component&amp;rsquo;s query.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;ApolloQueryElement&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;@apollo-elements/interfaces&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;TypePoliciesMixin&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;@apollo-elements/mixins/type-policies-mixin&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;export&lt;/span&gt; &lt;span class=&#34;kr&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;HelloQueryElement&lt;/span&gt; &lt;span class=&#34;kr&#34;&gt;extends&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;TypePoliciesMixin&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;ApolloQueryElement&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;typePolicies&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nx&#34;&gt;Greeting&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nx&#34;&gt;fields&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nx&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;next&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;next&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;??&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;friend&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nx&#34;&gt;greeting&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;next&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;next&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;??&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;friend&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
      
      <content:encoded><![CDATA[<!-- ----------------------------------------------------------------------------------------
     Welcome! This file includes automatically generated API documentation.
     To edit the docs that appear within, find the original source file under `packages/*`,
     corresponding to the package name and module in this YAML front-matter block.
     Thank you for your interest in Apollo Elements 😁
------------------------------------------------------------------------------------------ -->
<h1 id="web-component-libraries--class-mixins--typepoliciesmixin">Web Component Libraries &raquo; Class Mixins &raquo; TypePoliciesMixin</h1>
<p>Optional mixin which lets you declare type policies for a component&rsquo;s query.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">ApolloQueryElement</span> <span class="p">}</span> <span class="nx">from</span> <span class="s1">&#39;@apollo-elements/interfaces&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">TypePoliciesMixin</span> <span class="p">}</span> <span class="nx">from</span> <span class="s1">&#39;@apollo-elements/mixins/type-policies-mixin&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">export</span> <span class="kr">class</span> <span class="nx">HelloQueryElement</span> <span class="kr">extends</span> <span class="nx">TypePoliciesMixin</span><span class="p">(</span><span class="nx">ApolloQueryElement</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">typePolicies</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nx">Greeting</span><span class="o">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nx">fields</span><span class="o">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nx">name</span><span class="p">(</span><span class="nx">next</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="nx">next</span> <span class="o">??</span> <span class="s1">&#39;friend&#39;</span><span class="p">;</span> <span class="p">},</span>
</span></span><span class="line"><span class="cl">        <span class="nx">greeting</span><span class="p">(</span><span class="nx">next</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="nx">next</span> <span class="o">??</span> <span class="s1">&#39;friend&#39;</span><span class="p">;</span> <span class="p">},</span>
</span></span><span class="line"><span class="cl">      <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div>]]></content:encoded>
    </item><item>
      <title></title>
      <link>https://apolloelements.dev/api/libraries/mixins/validate-variables-mixin/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/api/libraries/mixins/validate-variables-mixin/</guid>
      <description>&lt;!-- ----------------------------------------------------------------------------------------
     Welcome! This file includes automatically generated API documentation.
     To edit the docs that appear within, find the original source file under `packages/*`,
     corresponding to the package name and module in this YAML front-matter block.
     Thank you for your interest in Apollo Elements 😁
------------------------------------------------------------------------------------------ --&gt;
&lt;h1 id=&#34;web-component-libraries--class-mixins--validatevariablesmixin&#34;&gt;Web Component Libraries &amp;raquo; Class Mixins &amp;raquo; ValidateVariablesMixin&lt;/h1&gt;
&lt;p&gt;Optional mixin which prevents queries from automatically subscribing until their non-nullable variables are defined.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;ApolloQueryElement&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;@apollo-elements/interfaces&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;ValidateVariablesMixin&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;@apollo-elements/mixins/validate-variables-mixin&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;gql&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;@apollo/client/core&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;export&lt;/span&gt; &lt;span class=&#34;kr&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;ValidatedQueryElement&lt;/span&gt; &lt;span class=&#34;kr&#34;&gt;extends&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;ValidateVariablesMixin&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;ApolloQueryElement&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;query&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;gql&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;`
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;    query UsersByName($name: String!) {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;      user { id name }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sb&#34;&gt;  `&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
      
      <content:encoded><![CDATA[<!-- ----------------------------------------------------------------------------------------
     Welcome! This file includes automatically generated API documentation.
     To edit the docs that appear within, find the original source file under `packages/*`,
     corresponding to the package name and module in this YAML front-matter block.
     Thank you for your interest in Apollo Elements 😁
------------------------------------------------------------------------------------------ -->
<h1 id="web-component-libraries--class-mixins--validatevariablesmixin">Web Component Libraries &raquo; Class Mixins &raquo; ValidateVariablesMixin</h1>
<p>Optional mixin which prevents queries from automatically subscribing until their non-nullable variables are defined.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">ApolloQueryElement</span> <span class="p">}</span> <span class="nx">from</span> <span class="s1">&#39;@apollo-elements/interfaces&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">ValidateVariablesMixin</span> <span class="p">}</span> <span class="nx">from</span> <span class="s1">&#39;@apollo-elements/mixins/validate-variables-mixin&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">gql</span> <span class="p">}</span> <span class="nx">from</span> <span class="s1">&#39;@apollo/client/core&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">export</span> <span class="kr">class</span> <span class="nx">ValidatedQueryElement</span> <span class="kr">extends</span> <span class="nx">ValidateVariablesMixin</span><span class="p">(</span><span class="nx">ApolloQueryElement</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">query</span> <span class="o">=</span> <span class="nx">gql</span><span class="sb">`
</span></span></span><span class="line"><span class="cl"><span class="sb">    query UsersByName($name: String!) {
</span></span></span><span class="line"><span class="cl"><span class="sb">      user { id name }
</span></span></span><span class="line"><span class="cl"><span class="sb">    }
</span></span></span><span class="line"><span class="cl"><span class="sb">  `</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div>]]></content:encoded>
    </item><item>
      <title></title>
      <link>https://apolloelements.dev/guides/cool-tricks/async-client/async-client-html/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/guides/cool-tricks/async-client/async-client-html/</guid>
      <description>&lt;apollo-client&gt;
  &lt;apollo-query no-auto-subscribe&gt;
    &lt;template&gt;
      &lt;template type=&#34;if&#34; if=&#34;{{ data }}&#34;&gt;
        &lt;h1&gt;👋 {{ data.userSession.name }}!&lt;/h1&gt;
        &lt;p&gt;
          &lt;span&gt;Your last activity was&lt;/span&gt;
          &lt;time&gt;{{ getTime(data) }}&lt;/time&gt;
        &lt;/p&gt;
      &lt;/template&gt;
    &lt;/template&gt;
  &lt;apollo-query&gt;
&lt;/apollo-client&gt;

&lt;script&gt;
  (async function() {
    const { formatDistance } = await import(&#39;date-fns/esm&#39;);
    const { getClient } = await import(&#39;./client&#39;);
    const { UserSessionQuery } = await import(&#39;./UserSession.query.graphql.js&#39;);

    const root = document.currentScript.getRootNode();
    const queryEl = root.querySelector(&#39;apollo-query&#39;);
    const clientEl = root.querySelector(&#39;apollo-client&#39;);

    clientEl.client = await getClient();

    queryEl.extras = {
      getTime(data) {
        if (!data || !data.userSession.lastActive)
          return &#39;&#39;
        else {
          return formatDistance(
            data.userSession.lastActive,
            Date.now(), {
              addSuffix: true
          });
        }
      },
    };

    queryEl.query = UserSessionQuery;
    queryEl.subscribe();

  })();
&lt;/script&gt;</description>
      
      <content:encoded><![CDATA[<apollo-client>
  <apollo-query no-auto-subscribe>
    <template>
      <template type="if" if="{{ data }}">
        <h1>👋 {{ data.userSession.name }}!</h1>
        <p>
          <span>Your last activity was</span>
          <time>{{ getTime(data) }}</time>
        </p>
      </template>
    </template>
  <apollo-query>
</apollo-client>

<script>
  (async function() {
    const { formatDistance } = await import('date-fns/esm');
    const { getClient } = await import('./client');
    const { UserSessionQuery } = await import('./UserSession.query.graphql.js');

    const root = document.currentScript.getRootNode();
    const queryEl = root.querySelector('apollo-query');
    const clientEl = root.querySelector('apollo-client');

    clientEl.client = await getClient();

    queryEl.extras = {
      getTime(data) {
        if (!data || !data.userSession.lastActive)
          return ''
        else {
          return formatDistance(
            data.userSession.lastActive,
            Date.now(), {
              addSuffix: true
          });
        }
      },
    };

    queryEl.query = UserSessionQuery;
    queryEl.subscribe();

  })();
</script>

]]></content:encoded>
    </item><item>
      <title></title>
      <link>https://apolloelements.dev/guides/cool-tricks/code-splitting/admin-profile-page-html/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/guides/cool-tricks/code-splitting/admin-profile-page-html/</guid>
      <description>&lt;p&gt;HTML apps should set all their type policies on the &lt;code&gt;apollo-client&lt;/code&gt; element&lt;/p&gt;
&lt;apollo-client&gt;...&lt;/apollo-client&gt;
&lt;script&gt;
  import(&#39;./typePolicies&#39;)
    .then(({ UserTypePolicies }) =&gt; {
      document
        .currentScript
        .getRootNode()
        .querySelector(&#39;apollo-client&#39;)
        .typePolicies = UserTypePolicies;
    });
&lt;/script&gt;</description>
      
      <content:encoded><![CDATA[<p>HTML apps should set all their type policies on the <code>apollo-client</code> element</p>
<apollo-client>...</apollo-client>
<script>
  import('./typePolicies')
    .then(({ UserTypePolicies }) => {
      document
        .currentScript
        .getRootNode()
        .querySelector('apollo-client')
        .typePolicies = UserTypePolicies;
    });
</script>
]]></content:encoded>
    </item><item>
      <title></title>
      <link>https://apolloelements.dev/guides/cool-tricks/code-splitting/profile-page-html/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/guides/cool-tricks/code-splitting/profile-page-html/</guid>
      <description>&lt;p&gt;HTML apps should set all their type policies on the &lt;code&gt;apollo-client&lt;/code&gt; element&lt;/p&gt;
&lt;apollo-client&gt;...&lt;/apollo-client&gt;
&lt;script&gt;
  import(&#39;./typePolicies&#39;)
    .then(({ UserTypePolicies }) =&gt; {
      document
        .currentScript
        .getRootNode()
        .querySelector(&#39;apollo-client&#39;)
        .typePolicies = UserTypePolicies;
    });
&lt;/script&gt;</description>
      
      <content:encoded><![CDATA[<p>HTML apps should set all their type policies on the <code>apollo-client</code> element</p>
<apollo-client>...</apollo-client>
<script>
  import('./typePolicies')
    .then(({ UserTypePolicies }) => {
      document
        .currentScript
        .getRootNode()
        .querySelector('apollo-client')
        .typePolicies = UserTypePolicies;
    });
</script>
]]></content:encoded>
    </item><item>
      <title></title>
      <link>https://apolloelements.dev/guides/cool-tricks/inline-graphql-scripts/greet-me-html/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/guides/cool-tricks/inline-graphql-scripts/greet-me-html/</guid>
      <description>&lt;apollo-query&gt;
  &lt;script type=&#34;application/graphql&#34;&gt;
    query Greeting {
      greeting {
        name
        greeting
      }
    }
  &lt;/script&gt;
  &lt;template&gt;
    &lt;p&gt;
      {{ data.greeting || &#39;Hello&#39; }},
      {{ data.name || &#39;friend&#39; }}
    &lt;/p&gt;
  &lt;/template&gt;
&lt;/apollo-query&gt;</description>
      
      <content:encoded><![CDATA[<apollo-query>
  <script type="application/graphql">
    query Greeting {
      greeting {
        name
        greeting
      }
    }
  </script>
  <template>
    <p>
      {{ data.greeting || 'Hello' }},
      {{ data.name || 'friend' }}
    </p>
  </template>
</apollo-query>
]]></content:encoded>
    </item><item>
      <title></title>
      <link>https://apolloelements.dev/guides/cool-tricks/validating-variables/should-subscribe-html/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/guides/cool-tricks/validating-variables/should-subscribe-html/</guid>
      <description>&lt;p&gt;
  You can subclass &lt;code&gt;ApolloQueryElement&lt;/code&gt;
  to override methods.
&lt;/p&gt;

&lt;should-subscribe-query&gt;&lt;/should-subscribe-query&gt;

&lt;script type=&#34;module&#34;&gt;
import { ApolloQueryElement } from &#39;@apollo-elements/components/apollo-query&#39;;
import { routeVar } from &#39;../variables&#39;;

customElements.define(
  &#39;should-subscribe-query&#39;,
  class ShouldSubscribeQueryElement extends ApolloQueryElement {
    shouldSubscribe() {
      return !!(routeVar().params?.postId);
    }
  });
&lt;/script&gt;</description>
      
      <content:encoded><![CDATA[<p>
  You can subclass <code>ApolloQueryElement</code>
  to override methods.
</p>

<should-subscribe-query></should-subscribe-query>

<script type="module">
import { ApolloQueryElement } from '@apollo-elements/components/apollo-query';
import { routeVar } from '../variables';

customElements.define(
  'should-subscribe-query',
  class ShouldSubscribeQueryElement extends ApolloQueryElement {
    shouldSubscribe() {
      return !!(routeVar().params?.postId);
    }
  });
</script>]]></content:encoded>
    </item><item>
      <title></title>
      <link>https://apolloelements.dev/guides/cool-tricks/validating-variables/validate-variables-mixin-atomico/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/guides/cool-tricks/validating-variables/validate-variables-mixin-atomico/</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;There&amp;rsquo;s no &lt;code&gt;ValidateVariablesMixin&lt;/code&gt; for atomico, so use one of the other techniques.&lt;/p&gt;&lt;/blockquote&gt;</description>
      
      <content:encoded><![CDATA[<blockquote>
<p>There&rsquo;s no <code>ValidateVariablesMixin</code> for atomico, so use one of the other techniques.</p></blockquote>
]]></content:encoded>
    </item><item>
      <title></title>
      <link>https://apolloelements.dev/guides/cool-tricks/validating-variables/validate-variables-mixin-haunted/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/guides/cool-tricks/validating-variables/validate-variables-mixin-haunted/</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;There&amp;rsquo;s no &lt;code&gt;ValidateVariablesMixin&lt;/code&gt; for haunted, so use one of the other techniques.&lt;/p&gt;&lt;/blockquote&gt;</description>
      
      <content:encoded><![CDATA[<blockquote>
<p>There&rsquo;s no <code>ValidateVariablesMixin</code> for haunted, so use one of the other techniques.</p></blockquote>
]]></content:encoded>
    </item><item>
      <title></title>
      <link>https://apolloelements.dev/guides/cool-tricks/validating-variables/validate-variables-mixin-html/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/guides/cool-tricks/validating-variables/validate-variables-mixin-html/</guid>
      <description>&lt;p&gt;
  You can subclass &lt;code&gt;ApolloQueryElement&lt;/code&gt;
  to apply mixins.
&lt;/p&gt;

&lt;validated-variables-query&gt;&lt;/validated-variables-query&gt;

&lt;script type=&#34;module&#34;&gt;
import { ApolloQueryElement } from &#39;@apollo-elements/components/apollo-query&#39;;
customElements.define(
  &#39;validated-variables-query&#39;,
  class ValidatedApolloQuery extends ValidateVariablesMixin(ApolloQueryElement) {});
&lt;/script&gt;</description>
      
      <content:encoded><![CDATA[<p>
  You can subclass <code>ApolloQueryElement</code>
  to apply mixins.
</p>

<validated-variables-query></validated-variables-query>

<script type="module">
import { ApolloQueryElement } from '@apollo-elements/components/apollo-query';
customElements.define(
  'validated-variables-query',
  class ValidatedApolloQuery extends ValidateVariablesMixin(ApolloQueryElement) {});
</script>]]></content:encoded>
    </item><item>
      <title></title>
      <link>https://apolloelements.dev/guides/cool-tricks/validating-variables/validate-variables-mixin-hybrids/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/guides/cool-tricks/validating-variables/validate-variables-mixin-hybrids/</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;There&amp;rsquo;s no &lt;code&gt;ValidateVariablesMixin&lt;/code&gt; for hybrids, so use one of the other techniques.&lt;/p&gt;&lt;/blockquote&gt;</description>
      
      <content:encoded><![CDATA[<blockquote>
<p>There&rsquo;s no <code>ValidateVariablesMixin</code> for hybrids, so use one of the other techniques.</p></blockquote>
]]></content:encoded>
    </item><item>
      <title></title>
      <link>https://apolloelements.dev/guides/getting-started/building-for-production/building-html/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/guides/getting-started/building-for-production/building-html/</guid>
      <description>&lt;p&gt;
  These techniques are less relevant to HTML components,
  so check out the other tabs.
&lt;/p&gt;</description>
      
      <content:encoded><![CDATA[<p>
  These techniques are less relevant to HTML components,
  so check out the other tabs.
</p>
]]></content:encoded>
    </item><item>
      <title></title>
      <link>https://apolloelements.dev/guides/usage/apollo-client/client-mixin-html/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/guides/usage/apollo-client/client-mixin-html/</guid>
      <description>&lt;blink&gt;
There is no equivalent of &lt;code&gt;ApolloClientMixin&lt;/code&gt; for HTML,
so just use the &lt;code&gt;&amp;lt;apollo-client&amp;gt;&lt;/code&gt; element.
&lt;/blink&gt;</description>
      
      <content:encoded><![CDATA[<blink>
There is no equivalent of <code>ApolloClientMixin</code> for HTML,
so just use the <code>&lt;apollo-client&gt;</code> element.
</blink>
]]></content:encoded>
    </item><item>
      <title></title>
      <link>https://apolloelements.dev/guides/usage/apollo-client/controller-client-html/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/guides/usage/apollo-client/controller-client-html/</guid>
      <description>&lt;blink&gt;
The HTML Apollo Elements use the ApolloElement interface. See the previous segments.
&lt;/blink&gt;</description>
      
      <content:encoded><![CDATA[<blink>
The HTML Apollo Elements use the ApolloElement interface. See the previous segments.
</blink>
]]></content:encoded>
    </item><item>
      <title></title>
      <link>https://apolloelements.dev/guides/usage/astronauts-html/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/guides/usage/astronauts-html/</guid>
      <description>&lt;apollo-query&gt;
  &lt;!-- Use a script child like so,
       or set the `query` DOM property on the element --&gt;
  &lt;script type=&#34;application/json&#34;&gt;
    query Users {
      users {
        id
        name
        picture
      }
    }
  &lt;/script&gt;
  &lt;template&gt;
    &lt;h2&gt;Astronauts&lt;/h2&gt;
    &lt;template type=&#34;repeat&#34; repeat=&#34;{{ data.users }}&#34;&gt;
      &lt;astro-naut id=&#34;{{ item.id }}&#34; name=&#34;{{ item.name }}&#34;&gt;
        &lt;img src=&#34;{{ item.picture }}&#34;
             alt=&#34;Portrait of {{ item.name }}&#34;/&gt;
      &lt;/astro-naut&gt;
    &lt;/template&gt;
  &lt;/template&gt;
&lt;/apollo-query&gt;</description>
      
      <content:encoded><![CDATA[<apollo-query>
  <!-- Use a script child like so,
       or set the `query` DOM property on the element -->
  <script type="application/json">
    query Users {
      users {
        id
        name
        picture
      }
    }
  </script>
  <template>
    <h2>Astronauts</h2>
    <template type="repeat" repeat="{{ data.users }}">
      <astro-naut id="{{ item.id }}" name="{{ item.name }}">
        <img src="{{ item.picture }}"
             alt="Portrait of {{ item.name }}"/>
      </astro-naut>
    </template>
  </template>
</apollo-query>
]]></content:encoded>
    </item><item>
      <title></title>
      <link>https://apolloelements.dev/guides/usage/local-state/advanced-local-state/final-html/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/guides/usage/local-state/advanced-local-state/final-html/</guid>
      <description>&lt;apollo-query id=&#34;create-network&#34;&gt;
  &lt;script type=&#34;application/graphql&#34;&gt;
    query AllSites {
      sites {
        id
        name
        selected @client
      }
    }
  &lt;/script&gt;
  &lt;template&gt;
    &lt;select-list @change=&#34;{%raw%}{{ onSelectedChanged }}{%endraw%}&#34;&gt;
      &lt;template type=&#34;repeat&#34; repeat=&#34;{%raw%}{{ data.sites }}{%endraw%}&#34;&gt;
        &lt;select-item
            item-id=&#34;{%raw%}{{ item.id }}{%endraw%}&#34;
            item-name=&#34;{%raw%}{{ item.name }}{%endraw%}&#34;
            ?selected=&#34;{%raw%}{{ item.selected }}{%endraw%}&#34;
        &gt;&lt;/select-item&gt;
      &lt;/template&gt;
    &lt;/select-list&gt;

    &lt;apollo-mutation @will-mutate=&#34;{%raw%}{{ onWillMutate }}{%endraw%}&#34;&gt;
      &lt;script type=&#34;application/graphql&#34;&gt;
        mutation CreateNetworkMutation($sites: Site[]) {
          createNetwork(sites: $sites)
        }
      &lt;/script&gt;
      &lt;button trigger&gt;Create&lt;/button&gt;
    &lt;/apollo-mutation&gt;
  &lt;/template&gt;
&lt;/apollo-query&gt;

&lt;script type=&#34;module&#34;&gt;
  const createNetwork = document.querySelector(&#39;#create-network&#39;);

  createNetwork.onSelectedChanged = function onSelectedChanged(event) {
    const selectListEl = event.target;
    const itemId = selectListEl.selected.itemId;
    client.writeFragment({
      id: `Site:${itemId}`,
      fragment,
      data: {
        selected: event.detail.selected
      },
    });
  };

  createNetwork.onWillMutate = function onWillMutate(event) {
    const sites = createNetwork.data.sites
      .filter(x =&gt; x.selected)
      .map(x =&gt; x.id);
    event.target.variables = { sites };
  };
&lt;/script&gt;</description>
      
      <content:encoded><![CDATA[<apollo-query id="create-network">
  <script type="application/graphql">
    query AllSites {
      sites {
        id
        name
        selected @client
      }
    }
  </script>
  <template>
    <select-list @change="{%raw%}{{ onSelectedChanged }}{%endraw%}">
      <template type="repeat" repeat="{%raw%}{{ data.sites }}{%endraw%}">
        <select-item
            item-id="{%raw%}{{ item.id }}{%endraw%}"
            item-name="{%raw%}{{ item.name }}{%endraw%}"
            ?selected="{%raw%}{{ item.selected }}{%endraw%}"
        ></select-item>
      </template>
    </select-list>

    <apollo-mutation @will-mutate="{%raw%}{{ onWillMutate }}{%endraw%}">
      <script type="application/graphql">
        mutation CreateNetworkMutation($sites: Site[]) {
          createNetwork(sites: $sites)
        }
      </script>
      <button trigger>Create</button>
    </apollo-mutation>
  </template>
</apollo-query>

<script type="module">
  const createNetwork = document.querySelector('#create-network');

  createNetwork.onSelectedChanged = function onSelectedChanged(event) {
    const selectListEl = event.target;
    const itemId = selectListEl.selected.itemId;
    client.writeFragment({
      id: `Site:${itemId}`,
      fragment,
      data: {
        selected: event.detail.selected
      },
    });
  };

  createNetwork.onWillMutate = function onWillMutate(event) {
    const sites = createNetwork.data.sites
      .filter(x => x.selected)
      .map(x => x.id);
    event.target.variables = { sites };
  };
</script>
]]></content:encoded>
    </item><item>
      <title></title>
      <link>https://apolloelements.dev/guides/usage/local-state/theme-toggle-html/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/guides/usage/local-state/theme-toggle-html/</guid>
      <description>&lt;apollo-query&gt;
  &lt;template&gt;
    &lt;button @click=&#34;{{ toggleTheme }}&#34;&gt;
      Change to {{ data.theme === &#39;dark&#39; ? &#39;light&#39; : &#39;dark&#39; }} theme
    &lt;/button&gt;
  &lt;/template&gt;
&lt;/apollo-query&gt;

&lt;script&gt;
  document.currentScript.getRootNode()
    .querySelector(&#39;apollo-query&#39;)
    .extras = {
      toggleTheme() {
        // TBD
      }
    }
&lt;/script&gt;</description>
      
      <content:encoded><![CDATA[<apollo-query>
  <template>
    <button @click="{{ toggleTheme }}">
      Change to {{ data.theme === 'dark' ? 'light' : 'dark' }} theme
    </button>
  </template>
</apollo-query>

<script>
  document.currentScript.getRootNode()
    .querySelector('apollo-query')
    .extras = {
      toggleTheme() {
        // TBD
      }
    }
</script>
]]></content:encoded>
    </item><item>
      <title></title>
      <link>https://apolloelements.dev/guides/usage/local-state/toggle-cache-html/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/guides/usage/local-state/toggle-cache-html/</guid>
      <description>&lt;apollo-client&gt;
  &lt;apollo-query&gt;
    &lt;!-- ... --&gt;
  &lt;/apollo-query&gt;
&lt;/apollo-client&gt;

&lt;script&gt;
  {
    const queryEl =
      document.currentScript.getRootNode()
        .querySelector(&#39;apollo-query&#39;)
    queryEl.extras = {
      toggleTheme() {
        const theme = queryEl.data.theme === &#39;light&#39; ? &#39;dark&#39; : &#39;light&#39;;
        queryEl.client.writeQuery({
          query: queryEl.query,
          data: { theme },
        });
      }
    };
  }
&lt;/script&gt;</description>
      
      <content:encoded><![CDATA[<apollo-client>
  <apollo-query>
    <!-- ... -->
  </apollo-query>
</apollo-client>

<script>
  {
    const queryEl =
      document.currentScript.getRootNode()
        .querySelector('apollo-query')
    queryEl.extras = {
      toggleTheme() {
        const theme = queryEl.data.theme === 'light' ? 'dark' : 'light';
        queryEl.client.writeQuery({
          query: queryEl.query,
          data: { theme },
        });
      }
    };
  }
</script>
]]></content:encoded>
    </item><item>
      <title></title>
      <link>https://apolloelements.dev/guides/usage/local-state/type-policies-html/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/guides/usage/local-state/type-policies-html/</guid>
      <description>&lt;apollo-client&gt;
  &lt;apollo-query&gt;
    &lt;!-- ... --&gt;
  &lt;/apollo-query&gt;
&lt;/apollo-client&gt;

&lt;script&gt;
  import(&#39;./typePolicies&#39;)
    .then(({ typePolicies }) =&gt; {
      // In the case of HTML components,
      // register type policies on the &lt;apollo-client&gt; element
      document.currentScript.getRootNode()
        .querySelector(&#39;apollo-client&#39;)
        .typePolicies = typePolicies;
    });
&lt;/script&gt;</description>
      
      <content:encoded><![CDATA[<apollo-client>
  <apollo-query>
    <!-- ... -->
  </apollo-query>
</apollo-client>

<script>
  import('./typePolicies')
    .then(({ typePolicies }) => {
      // In the case of HTML components,
      // register type policies on the <apollo-client> element
      document.currentScript.getRootNode()
        .querySelector('apollo-client')
        .typePolicies = typePolicies;
    });
</script>
]]></content:encoded>
    </item><item>
      <title></title>
      <link>https://apolloelements.dev/guides/usage/mutations/add-user-html/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/guides/usage/mutations/add-user-html/</guid>
      <description>&lt;apollo-mutation&gt;
  &lt;template&gt;
    &lt;p-card&gt;
      &lt;h2 slot=&#34;heading&#34;&gt;Add User&lt;/h2&gt;

      &lt;dl ?hidden=&#34;{%raw%}{{ !data }}{%endraw%}&#34;&gt;
        &lt;dt&gt;Name&lt;/dt&gt;  &lt;dd&gt;{%raw%}{{ data.name }}{%endraw%}&lt;/dd&gt;
        &lt;dt&gt;Added&lt;/dt&gt; &lt;dd&gt;{%raw%}{{ dateString(data.timestamp) }}{%endraw%}&lt;/dd&gt;
      &lt;/dl&gt;

      &lt;slot slot=&#34;actions&#34;&gt;&lt;/slot&gt;
    &lt;/p-card&gt;
  &lt;/template&gt;

  &lt;mwc-textfield outlined
      label=&#34;User Name&#34;
      data-variable=&#34;name&#34;&gt;&lt;/mwc-textfield&gt;

  &lt;mwc-button label=&#34;Add User&#34; trigger&gt;&lt;/mwc-button&gt;
&lt;/apollo-mutation&gt;

&lt;script&gt;
  document.currentScript.getRootNode()
    .querySelector(&#39;apollo-mutation&#39;)
    .extras = {
      dateString(timestamp) {
        return new Date(timestamp).toDateString();
      }
    }
&lt;/script&gt;</description>
      
      <content:encoded><![CDATA[<apollo-mutation>
  <template>
    <p-card>
      <h2 slot="heading">Add User</h2>

      <dl ?hidden="{%raw%}{{ !data }}{%endraw%}">
        <dt>Name</dt>  <dd>{%raw%}{{ data.name }}{%endraw%}</dd>
        <dt>Added</dt> <dd>{%raw%}{{ dateString(data.timestamp) }}{%endraw%}</dd>
      </dl>

      <slot slot="actions"></slot>
    </p-card>
  </template>

  <mwc-textfield outlined
      label="User Name"
      data-variable="name"></mwc-textfield>

  <mwc-button label="Add User" trigger></mwc-button>
</apollo-mutation>

<script>
  document.currentScript.getRootNode()
    .querySelector('apollo-mutation')
    .extras = {
      dateString(timestamp) {
        return new Date(timestamp).toDateString();
      }
    }
</script>
]]></content:encoded>
    </item><item>
      <title></title>
      <link>https://apolloelements.dev/guides/usage/mutations/cache-management/blog-post-html/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/guides/usage/mutations/cache-management/blog-post-html/</guid>
      <description>&lt;apollo-mutation&gt;
  &lt;template&gt;
    &lt;loading-overlay ?active=&#34;{{ loading }}&#34;&gt;&lt;/loading-overlay&gt;

    &lt;label&gt;New Post &lt;textarea data-variable=&#34;content&#34;&gt;&lt;/textarea&gt;&lt;/label&gt;

    &lt;button ?hidden=&#34;{{ data }}&#34; trigger&gt;Post!&lt;/button&gt;

    &lt;article ?hidden=&#34;{{ !data }}&#34;&gt;
      &lt;strong&gt;Post Succeeded!&lt;/strong&gt;
      &lt;p&gt;{{ data.summary }}&lt;/p&gt;
    &lt;/article&gt;
  &lt;/template&gt;
&lt;/apollo-mutation&gt;</description>
      
      <content:encoded><![CDATA[<apollo-mutation>
  <template>
    <loading-overlay ?active="{{ loading }}"></loading-overlay>

    <label>New Post <textarea data-variable="content"></textarea></label>

    <button ?hidden="{{ data }}" trigger>Post!</button>

    <article ?hidden="{{ !data }}">
      <strong>Post Succeeded!</strong>
      <p>{{ data.summary }}</p>
    </article>
  </template>
</apollo-mutation>
]]></content:encoded>
    </item><item>
      <title></title>
      <link>https://apolloelements.dev/guides/usage/mutations/cache-management/cache-update-html/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/guides/usage/mutations/cache-management/cache-update-html/</guid>
      <description>&lt;script&gt;
  document.currentScript.getRootNode()
    .querySelector(&#39;apollo-mutation&#39;)
    .updater = function updater(cache, result) {
      // 1: Read the cache synchronously to get the current list of posts
      const query = LatestPostsQuery;
      const cached = cache.readQuery({ query: LatestPostsQuery });

      // 2: Calculate the expected result of LatestPostsQuery,
      //    considering the mutation result
      const data = { posts: [result.data.postBlogPost, ...cached.posts] }

      // 3: Perform the cache update by calling `writeQuery`
      cache.writeQuery({ query, data });
    };
&lt;/script&gt;</description>
      
      <content:encoded><![CDATA[<script>
  document.currentScript.getRootNode()
    .querySelector('apollo-mutation')
    .updater = function updater(cache, result) {
      // 1: Read the cache synchronously to get the current list of posts
      const query = LatestPostsQuery;
      const cached = cache.readQuery({ query: LatestPostsQuery });

      // 2: Calculate the expected result of LatestPostsQuery,
      //    considering the mutation result
      const data = { posts: [result.data.postBlogPost, ...cached.posts] }

      // 3: Perform the cache update by calling `writeQuery`
      cache.writeQuery({ query, data });
    };
</script>
]]></content:encoded>
    </item><item>
      <title></title>
      <link>https://apolloelements.dev/guides/usage/mutations/cache-management/optimistic-response-html/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/guides/usage/mutations/cache-management/optimistic-response-html/</guid>
      <description>&lt;script&gt;
  document.currentScript.getRootNode()
    .querySelector(&#39;apollo-mutation&#39;)
    .optimisticResponse = variables =&gt; ({
      postBlogPost: {
        __typename: &#39;BlogPost&#39;,
        url: &#39;#&#39;,
        // implementation left as an exercise to the reader
        summary: summarize(variables.content),
        datePosted: new Date().toISOString(),
        content,
      },
    });
&lt;/script&gt;</description>
      
      <content:encoded><![CDATA[<script>
  document.currentScript.getRootNode()
    .querySelector('apollo-mutation')
    .optimisticResponse = variables => ({
      postBlogPost: {
        __typename: 'BlogPost',
        url: '#',
        // implementation left as an exercise to the reader
        summary: summarize(variables.content),
        datePosted: new Date().toISOString(),
        content,
      },
    });
</script>
]]></content:encoded>
    </item><item>
      <title></title>
      <link>https://apolloelements.dev/guides/usage/mutations/composition/apollo-mutation-html/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/guides/usage/mutations/composition/apollo-mutation-html/</guid>
      <description>&lt;apollo-query&gt;
  &lt;script type=&#34;application/graphql&#34;&gt;
    query User($userId: ID!) {
      user(userId: $userId) { id isMe name birthday picture }
    }
  &lt;/script&gt;
  &lt;template&gt;
    &lt;h2&gt;Profile&lt;/h2&gt;

    &lt;dl ?hidden=&#34;{{ loading || !data }}&#34;&gt;
      &lt;dt&gt;Name&lt;/dt&gt;
      &lt;dd&gt;{{ data.user.name }}&lt;/dd&gt;

      &lt;dt&gt;Picture&lt;/dt&gt;
      &lt;dd&gt;&lt;img .src=&#34;{{ data.user.picture }}&#34;/&gt;&lt;/dd&gt;

      &lt;dt&gt;Birthday&lt;/dt&gt;
      &lt;dd&gt;{{ data.user.birthday }}&lt;/dd&gt;
    &lt;/dl&gt;

    &lt;form ?hidden=&#34;{{ !data.user.isMe }}&#34;&gt;
      &lt;h3&gt;Edit&lt;/h3&gt;
      &lt;apollo-mutation input-key=&#34;input&#34;&gt;
        &lt;script type=&#34;application/graphql&#34;&gt;
          mutation UpdateProfileMutation($input: UpdateProfileInput) {
            id
            name
            picture
            birthday
          }
        &lt;/script&gt;
        &lt;label for=&#34;name&#34;&gt;Name&lt;/label&gt;
        &lt;input id=&#34;name&#34;
               data-variable=&#34;name&#34;
               .value=&#34;{{ data.user.name }}&#34;/&gt;

        &lt;label for=&#34;picture&#34;&gt;Picture (URL)&lt;/label&gt;
        &lt;input id=&#34;picture&#34;
               data-variable=&#34;picture&#34;
               .value=&#34;{{ data.user.picture }}&#34;/&gt;

        &lt;label for=&#34;birthday&#34;&gt;Birthday&lt;/label&gt;
        &lt;input id=&#34;birthday&#34;
               data-variable=&#34;birthday&#34; type=&#34;date&#34;
               .value=&#34;{{ data.user.birthday }}&#34;/&gt;

        &lt;button trigger&gt;Save&lt;/button&gt;
      &lt;/apollo-mutation&gt;
    &lt;/form&gt;
  &lt;/template&gt;
&lt;/apollo-query&gt;</description>
      
      <content:encoded><![CDATA[<apollo-query>
  <script type="application/graphql">
    query User($userId: ID!) {
      user(userId: $userId) { id isMe name birthday picture }
    }
  </script>
  <template>
    <h2>Profile</h2>

    <dl ?hidden="{{ loading || !data }}">
      <dt>Name</dt>
      <dd>{{ data.user.name }}</dd>

      <dt>Picture</dt>
      <dd><img .src="{{ data.user.picture }}"/></dd>

      <dt>Birthday</dt>
      <dd>{{ data.user.birthday }}</dd>
    </dl>

    <form ?hidden="{{ !data.user.isMe }}">
      <h3>Edit</h3>
      <apollo-mutation input-key="input">
        <script type="application/graphql">
          mutation UpdateProfileMutation($input: UpdateProfileInput) {
            id
            name
            picture
            birthday
          }
        </script>
        <label for="name">Name</label>
        <input id="name"
               data-variable="name"
               .value="{{ data.user.name }}"/>

        <label for="picture">Picture (URL)</label>
        <input id="picture"
               data-variable="picture"
               .value="{{ data.user.picture }}"/>

        <label for="birthday">Birthday</label>
        <input id="birthday"
               data-variable="birthday" type="date"
               .value="{{ data.user.birthday }}"/>

        <button trigger>Save</button>
      </apollo-mutation>
    </form>
  </template>
</apollo-query>
]]></content:encoded>
    </item><item>
      <title></title>
      <link>https://apolloelements.dev/guides/usage/mutations/composition/mutation-controller-html/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/guides/usage/mutations/composition/mutation-controller-html/</guid>
      <description>&lt;blink&gt;The Apollo HTML elements use the controllers under the hood&lt;/blink&gt;
&lt;marquee&gt;Just follow the previous example.&lt;/marquee&gt;</description>
      
      <content:encoded><![CDATA[<blink>The Apollo HTML elements use the controllers under the hood</blink>
<marquee>Just follow the previous example.</marquee>
]]></content:encoded>
    </item><item>
      <title></title>
      <link>https://apolloelements.dev/guides/usage/mutations/html/html/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/guides/usage/mutations/html/html/</guid>
      <description>&lt;apollo-mutation&gt;
  &lt;button trigger&gt;Publish&lt;/button&gt;
  &lt;script type=&#34;application/graphql&#34;&gt;
    mutation CreatePost($input: CreatePostInput) {
      createPost(input: $input) {
        id
        body
        title
      }
    }
  &lt;/script&gt;
&lt;/apollo-mutation&gt;

&lt;script&gt;
  document.currentScript.getRootNode()
    .querySelector(&#39;apollo-mutation&#39;)
    .addEventListener(&#39;will-mutate&#39;, function onWillMutate(event) {
      onWillMutate(event) {
        // Post exists, don&#39;t mutate.
        // Toggle the host component&#39;s edit state instead.
        if (new URL(location.href).searchParams.has(&#39;postId&#39;)) {
          event.preventDefault();
          this.querySelector(&#39;[trigger]&#39;).textContent = &#39;Edit&#39;;
        }
      }
    });
&lt;/script&gt;</description>
      
      <content:encoded><![CDATA[<apollo-mutation>
  <button trigger>Publish</button>
  <script type="application/graphql">
    mutation CreatePost($input: CreatePostInput) {
      createPost(input: $input) {
        id
        body
        title
      }
    }
  </script>
</apollo-mutation>

<script>
  document.currentScript.getRootNode()
    .querySelector('apollo-mutation')
    .addEventListener('will-mutate', function onWillMutate(event) {
      onWillMutate(event) {
        // Post exists, don't mutate.
        // Toggle the host component's edit state instead.
        if (new URL(location.href).searchParams.has('postId')) {
          event.preventDefault();
          this.querySelector('[trigger]').textContent = 'Edit';
        }
      }
    });
</script>
]]></content:encoded>
    </item><item>
      <title></title>
      <link>https://apolloelements.dev/guides/usage/queries/fetch-policy-html/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/guides/usage/queries/fetch-policy-html/</guid>
      <description>&lt;apollo-query fetch-policy=&#34;cache-only&#34;&gt;
  &lt;script type=&#34;application/graphql&#34;&gt;...&lt;/script&gt;

  &lt;template&gt;...&lt;/template&gt;
&lt;/apollo-query&gt;</description>
      
      <content:encoded><![CDATA[<apollo-query fetch-policy="cache-only">
  <script type="application/graphql">...</script>

  <template>...</template>
</apollo-query>
]]></content:encoded>
    </item><item>
      <title></title>
      <link>https://apolloelements.dev/guides/usage/queries/hello-query-html/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/guides/usage/queries/hello-query-html/</guid>
      <description>&lt;apollo-query&gt;
  &lt;script type=&#34;application/graphql&#34;&gt;
    query HelloQuery {
      hello { name greeting }
    }
  &lt;/script&gt;
  &lt;template&gt;
    &lt;article class=&#34;{{ loading ? &#39;skeleton&#39; : &#39;&#39; }}&#34;&gt;
      &lt;p id=&#34;error&#34; ?hidden=&#34;{{ !error }}&#34;&gt;{{ error.message }}&lt;/p&gt;
      &lt;p&gt;
        {{ data.greeting || &#39;Hello&#39; }},
        {{ data.name || &#39;Friend&#39; }}
      &lt;/p&gt;
    &lt;/article&gt;
  &lt;/template&gt;
&lt;/apollo-query&gt;</description>
      
      <content:encoded><![CDATA[<apollo-query>
  <script type="application/graphql">
    query HelloQuery {
      hello { name greeting }
    }
  </script>
  <template>
    <article class="{{ loading ? 'skeleton' : '' }}">
      <p id="error" ?hidden="{{ !error }}">{{ error.message }}</p>
      <p>
        {{ data.greeting || 'Hello' }},
        {{ data.name || 'Friend' }}
      </p>
    </article>
  </template>
</apollo-query>
]]></content:encoded>
    </item><item>
      <title></title>
      <link>https://apolloelements.dev/guides/usage/queries/no-auto-subscribe-html/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/guides/usage/queries/no-auto-subscribe-html/</guid>
      <description>&lt;apollo-query no-auto-subscribe&gt;
  &lt;script type=&#34;application/graphql&#34;&gt;...&lt;/script&gt;

  &lt;template&gt;...&lt;/template&gt;
&lt;/apollo-query&gt;</description>
      
      <content:encoded><![CDATA[<apollo-query no-auto-subscribe>
  <script type="application/graphql">...</script>

  <template>...</template>
</apollo-query>
]]></content:encoded>
    </item><item>
      <title></title>
      <link>https://apolloelements.dev/guides/usage/queries/should-subscribe-html/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/guides/usage/queries/should-subscribe-html/</guid>
      <description>&lt;no-auto-fetch-query&gt;...&lt;/no-auto-fetch-query&gt;
&lt;script type=&#34;module&#34;&gt;
  import { ApolloQueryElement } from &#39;@apollo-elements/components&#39;;

  class NoAutoFetchQuery extends ApolloQueryElement {
    /**
     * Prevent fetching if the URL contains a `?noAutoFetch` query param
     */
    shouldSubscribe() {
      const { searchParams } = new URL(location.href);
      return !searchParams.has(&#39;noAutoFetch&#39;);
    }
  }

  customElements.define(&#39;no-auto-fetch-query&#39;, NoAutoFetchQuery);
&lt;/script&gt;</description>
      
      <content:encoded><![CDATA[<no-auto-fetch-query>...</no-auto-fetch-query>
<script type="module">
  import { ApolloQueryElement } from '@apollo-elements/components';

  class NoAutoFetchQuery extends ApolloQueryElement {
    /**
     * Prevent fetching if the URL contains a `?noAutoFetch` query param
     */
    shouldSubscribe() {
      const { searchParams } = new URL(location.href);
      return !searchParams.has('noAutoFetch');
    }
  }

  customElements.define('no-auto-fetch-query', NoAutoFetchQuery);
</script>
]]></content:encoded>
    </item><item>
      <title></title>
      <link>https://apolloelements.dev/guides/usage/queries/variables-html/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/guides/usage/queries/variables-html/</guid>
      <description>&lt;apollo-query&gt;
  &lt;script type=&#34;application/graphql&#34;&gt;
    query HelloQuery {
      hello { name greeting }
    }
  &lt;/script&gt;
  &lt;script type=&#34;application/json&#34;&gt;
    {
      &#34;greeting&#34;: &#34;How&#39;s it going&#34;,
      &#34;name&#34;: &#34;Dude&#34;
    }
  &lt;/script&gt;
  &lt;template&gt;
    &lt;article class=&#34;{{ loading ? &#39;skeleton&#39; : &#39;&#39; }}&#34;&gt;
      &lt;p id=&#34;error&#34; ?hidden=&#34;{{ !error }}&#34;&gt;{{ error.message }}&lt;/p&gt;
      &lt;p&gt;
        {{ data.greeting || &#39;Hello&#39; }},
        {{ data.name || &#39;Friend&#39; }}
      &lt;/p&gt;
    &lt;/article&gt;
  &lt;/template&gt;
&lt;/apollo-query&gt;</description>
      
      <content:encoded><![CDATA[<apollo-query>
  <script type="application/graphql">
    query HelloQuery {
      hello { name greeting }
    }
  </script>
  <script type="application/json">
    {
      "greeting": "How's it going",
      "name": "Dude"
    }
  </script>
  <template>
    <article class="{{ loading ? 'skeleton' : '' }}">
      <p id="error" ?hidden="{{ !error }}">{{ error.message }}</p>
      <p>
        {{ data.greeting || 'Hello' }},
        {{ data.name || 'Friend' }}
      </p>
    </article>
  </template>
</apollo-query>
]]></content:encoded>
    </item><item>
      <title></title>
      <link>https://apolloelements.dev/guides/usage/subscriptions/subscribe-to-more-html/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/guides/usage/subscriptions/subscribe-to-more-html/</guid>
      <description>&lt;apollo-client id=&#34;messages-client&#34;&gt;
  &lt;apollo-query id=&#34;messages-query&#34;&gt;
    &lt;script type=&#34;application/graphql&#34; src=&#34;Messages.query.graphql&#34;&gt;&lt;/script&gt;
    &lt;template&gt;
      &lt;link rel=&#34;stylesheet&#34; href=&#34;messages.css&#34;/&gt;
      &lt;ol&gt;
        &lt;template type=&#34;repeat&#34; repeat=&#34;{{ data.messages ?? [] }}&#34;&gt;
          &lt;li&gt;
            &lt;h4&gt;
              &lt;time datetime=&#34;{{ date }}&#34;&gt;{{ formatDate(item.date) }}&lt;/time&gt;
              &lt;span class=&#34;user&#34;&gt;{{ item.user }} said:&lt;/span&gt;
            &lt;/h4&gt;
            &lt;p&gt;{{ item.message }}&lt;/p&gt;
          &lt;/li&gt;
        &lt;/template&gt;
      &lt;/ol&gt;
    &lt;/template&gt;
  &lt;/apollo-query&gt;
&lt;/apollo-client&gt;
&lt;script type=&#34;module&#34;&gt;
  import &#39;@apollo-elements/components&#39;;
  import { client } from &#39;./client&#39;;
  import { MessageSentSubscription } from &#39;./MessageSent.subscription.graphql.js&#39;;

  const element = document.getElementById(&#39;messages-query&#39;);

  element.formatDate = function formatDate(iso) {
    try { return new Date(iso).toDateString(); }
    catch { return &#39;&#39;; }
  };

  element.subscribeToMore({
    document: MessageSentSubscription
    updateQuery(prev, { subscriptionData }) {
      if (!subscriptionData.data) return prev;
      return {
        ...prev,
        messages: [...prev.messages, subscriptionData.data.messageSent]
      };
    },
  }) = subscribeToMore;

  document.getElementById(&#39;messages-client&#39;).client = client;
&lt;/script&gt;</description>
      
      <content:encoded><![CDATA[<apollo-client id="messages-client">
  <apollo-query id="messages-query">
    <script type="application/graphql" src="Messages.query.graphql"></script>
    <template>
      <link rel="stylesheet" href="messages.css"/>
      <ol>
        <template type="repeat" repeat="{{ data.messages ?? [] }}">
          <li>
            <h4>
              <time datetime="{{ date }}">{{ formatDate(item.date) }}</time>
              <span class="user">{{ item.user }} said:</span>
            </h4>
            <p>{{ item.message }}</p>
          </li>
        </template>
      </ol>
    </template>
  </apollo-query>
</apollo-client>
<script type="module">
  import '@apollo-elements/components';
  import { client } from './client';
  import { MessageSentSubscription } from './MessageSent.subscription.graphql.js';

  const element = document.getElementById('messages-query');

  element.formatDate = function formatDate(iso) {
    try { return new Date(iso).toDateString(); }
    catch { return ''; }
  };

  element.subscribeToMore({
    document: MessageSentSubscription
    updateQuery(prev, { subscriptionData }) {
      if (!subscriptionData.data) return prev;
      return {
        ...prev,
        messages: [...prev.messages, subscriptionData.data.messageSent]
      };
    },
  }) = subscribeToMore;

  document.getElementById('messages-client').client = client;
</script>
]]></content:encoded>
    </item><item>
      <title></title>
      <link>https://apolloelements.dev/guides/usage/subscriptions/subscription-controller-html/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/guides/usage/subscriptions/subscription-controller-html/</guid>
      <description>&lt;apollo-client id=&#34;messages-client&#34;&gt;
  &lt;apollo-query id=&#34;messages-query&#34;&gt;
    &lt;script type=&#34;application/graphql&#34; src=&#34;Messages.query.graphql&#34;&gt;&lt;/script&gt;
    &lt;template&gt;
      &lt;link rel=&#34;stylesheet&#34; href=&#34;messages.css&#34;/&gt;
      &lt;ol&gt;
        &lt;template type=&#34;repeat&#34; repeat=&#34;{{ data.messages ?? [] }}&#34;&gt;
          &lt;li&gt;
            &lt;h4&gt;
              &lt;time datetime=&#34;{{ date }}&#34;&gt;{{ formatDate(item.date) }}&lt;/time&gt;
              &lt;span class=&#34;user&#34;&gt;{{ item.user }} said:&lt;/span&gt;
            &lt;/h4&gt;
            &lt;p&gt;{{ item.message }}&lt;/p&gt;
          &lt;/li&gt;
        &lt;/template&gt;
      &lt;/ol&gt;
    &lt;/template&gt;
  &lt;/apollo-query&gt;

  &lt;apollo-subscription id=&#34;messages-subscription&#34;&gt;
    &lt;script type=&#34;application/graphql&#34; src=&#34;MessageSent.subscription.graphql&#34;&gt;&lt;/script&gt;
    &lt;template&gt;
      &lt;mwc-snackbar labeltext=&#34;{{ data.messagesSent.user }} sent a message!&#34;&gt;&lt;/mwc-snackbar&gt;
    &lt;/template&gt;
  &lt;/apollo-subcription&gt;

&lt;/apollo-client&gt;
&lt;script type=&#34;module&#34;&gt;
  import &#39;@apollo-elements/components&#39;;
  import &#39;@material/mwc-snackbar&#39;;

  import { client } from &#39;./client&#39;;

  const q = document.getElementById(&#39;messages-query&#39;);
  const s = document.getElementById(&#39;messages-subscription&#39;);

  q.formatDate = function formatDate(iso) { /*...*/ };

  s.addEventListener(&#39;apollo-subscription-result&#39;, async event =&gt; {
    // update the query element
    const { client, subscriptionResult: { data: { messageSent } } } = event.detail;
    const { query } = q;
    const cached = client.readQuery({ query });
    client.writeQuery({ query, data: { messages: [...cached.messages, messageSent] } });

    // Display the notification
    await s.updateComplete;
    s.$(&#39;mwc-snackbar&#39;).show();
  });

  document.getElementById(&#39;messages-client&#39;).client = client;
&lt;/script&gt;</description>
      
      <content:encoded><![CDATA[<apollo-client id="messages-client">
  <apollo-query id="messages-query">
    <script type="application/graphql" src="Messages.query.graphql"></script>
    <template>
      <link rel="stylesheet" href="messages.css"/>
      <ol>
        <template type="repeat" repeat="{{ data.messages ?? [] }}">
          <li>
            <h4>
              <time datetime="{{ date }}">{{ formatDate(item.date) }}</time>
              <span class="user">{{ item.user }} said:</span>
            </h4>
            <p>{{ item.message }}</p>
          </li>
        </template>
      </ol>
    </template>
  </apollo-query>

  <apollo-subscription id="messages-subscription">
    <script type="application/graphql" src="MessageSent.subscription.graphql"></script>
    <template>
      <mwc-snackbar labeltext="{{ data.messagesSent.user }} sent a message!"></mwc-snackbar>
    </template>
  </apollo-subcription>

</apollo-client>
<script type="module">
  import '@apollo-elements/components';
  import '@material/mwc-snackbar';

  import { client } from './client';

  const q = document.getElementById('messages-query');
  const s = document.getElementById('messages-subscription');

  q.formatDate = function formatDate(iso) { /*...*/ };

  s.addEventListener('apollo-subscription-result', async event => {
    // update the query element
    const { client, subscriptionResult: { data: { messageSent } } } = event.detail;
    const { query } = q;
    const cached = client.readQuery({ query });
    client.writeQuery({ query, data: { messages: [...cached.messages, messageSent] } });

    // Display the notification
    await s.updateComplete;
    s.$('mwc-snackbar').show();
  });

  document.getElementById('messages-client').client = client;
</script>
]]></content:encoded>
    </item><item>
      <title>ApolloElement</title>
      <link>https://apolloelements.dev/api/core/interfaces/element/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/api/core/interfaces/element/</guid>
      <description>&lt;!-- ----------------------------------------------------------------------------------------
     Welcome! This file includes automatically generated API documentation.
     To edit the docs that appear within, find the original source file under `packages/*`,
     corresponding to the package name and module in this YAML front-matter block.
     Thank you for your interest in Apollo Elements 😁
------------------------------------------------------------------------------------------ --&gt;
&lt;p&gt;Common base interface for Apollo Elements. Provides reactivity for &lt;code&gt;data&lt;/code&gt;, &lt;code&gt;error&lt;/code&gt;, &lt;code&gt;errors&lt;/code&gt;, &lt;code&gt;loading&lt;/code&gt;, and &lt;code&gt;variables&lt;/code&gt; fields.&lt;/p&gt;
&lt;h2 id=&#34;type-parameters&#34;&gt;Type Parameters&lt;/h2&gt;
&lt;p&gt;Every implemention of &lt;code&gt;ApolloElement&lt;/code&gt; takes either one or two type parameters. A single parameter is either a &lt;code&gt;TypedDocumentNode&lt;/code&gt; or the operation&amp;rsquo;s result type, in which case the variables type defaults to &lt;code&gt;OperationVariables&lt;/code&gt;, which is an object of arbitrary string keys and unknown values. If you pass two parameters, the first is the operation&amp;rsquo;s result type, the second is the operation&amp;rsquo;s variables type.&lt;/p&gt;</description>
      
      <content:encoded><![CDATA[<!-- ----------------------------------------------------------------------------------------
     Welcome! This file includes automatically generated API documentation.
     To edit the docs that appear within, find the original source file under `packages/*`,
     corresponding to the package name and module in this YAML front-matter block.
     Thank you for your interest in Apollo Elements 😁
------------------------------------------------------------------------------------------ -->
<p>Common base interface for Apollo Elements. Provides reactivity for <code>data</code>, <code>error</code>, <code>errors</code>, <code>loading</code>, and <code>variables</code> fields.</p>
<h2 id="type-parameters">Type Parameters</h2>
<p>Every implemention of <code>ApolloElement</code> takes either one or two type parameters. A single parameter is either a <code>TypedDocumentNode</code> or the operation&rsquo;s result type, in which case the variables type defaults to <code>OperationVariables</code>, which is an object of arbitrary string keys and unknown values. If you pass two parameters, the first is the operation&rsquo;s result type, the second is the operation&rsquo;s variables type.</p>
<p>The following examples demonstrate passing type arguments to a query component.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ts" data-lang="ts"><span class="line"><span class="cl"><span class="kr">import</span> <span class="kr">type</span> <span class="p">{</span> <span class="nx">ResultOf</span><span class="p">,</span> <span class="nx">VariablesOf</span> <span class="p">}</span> <span class="kr">from</span> <span class="s1">&#39;@graphql-typed-document-node/core&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">gql</span><span class="p">,</span> <span class="nx">TypedDocumentNode</span> <span class="p">}</span> <span class="kr">from</span> <span class="s1">&#39;@apollo/client/core&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">interface</span> <span class="nx">Data</span> <span class="p">{</span> <span class="nx">int</span>: <span class="kt">number</span><span class="p">;</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="kr">interface</span> <span class="nx">Variables</span> <span class="p">{</span> <span class="nx">int</span>: <span class="kt">number</span><span class="p">;</span> <span class="p">}</span>
</span></span></code></pre></div><h3 id="example-passing-two-type-arguments">Example: Passing Two Type Arguments</h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ts" data-lang="ts"><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">UntypedQuery</span> <span class="o">=</span> <span class="nx">gql</span><span class="sb">`query Query($int: Int) { int }`</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">class</span> <span class="nx">UntypedElement</span> <span class="kr">extends</span> <span class="nx">ApolloQuery</span><span class="p">&lt;</span><span class="nt">Data</span><span class="p">,</span> <span class="na">Variables</span><span class="p">&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">query</span> <span class="o">=</span> <span class="nx">UntypedQuery</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="nx">checkClassFieldTypes() {</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// @ts-expect-error: `int` should be a number
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="k">this</span><span class="p">.</span><span class="nx">data</span> <span class="o">=</span> <span class="p">{</span> <span class="nx">int</span><span class="o">:</span> <span class="s1">&#39;a&#39;</span> <span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// @ts-expect-error: `int` should be a number
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="k">this</span><span class="p">.</span><span class="nx">variables</span> <span class="o">=</span> <span class="p">{</span> <span class="nx">int</span><span class="o">:</span> <span class="s1">&#39;b&#39;</span> <span class="p">};</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><h3 id="example-passing-a-single-type-arguments">Example: Passing a Single Type Arguments</h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ts" data-lang="ts"><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">TypedQuery</span>: <span class="kt">TypedDocumentNode</span><span class="p">&lt;</span><span class="nt">Data</span><span class="p">,</span> <span class="na">Variables</span><span class="p">&gt;</span> <span class="o">=</span> <span class="nx">UntypedQuery</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">class</span> <span class="nx">TypedElement</span> <span class="kr">extends</span> <span class="nx">ApolloQuery</span><span class="p">&lt;</span><span class="nt">typeof</span> <span class="na">TypedQuery</span><span class="p">&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">query</span> <span class="o">=</span> <span class="nx">TypedQuery</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="nx">checkClassFieldTypes() {</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// @ts-expect-error: `int` should be a number
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="k">this</span><span class="p">.</span><span class="nx">data</span> <span class="o">=</span> <span class="p">{</span> <span class="nx">int</span><span class="o">:</span> <span class="s1">&#39;a&#39;</span> <span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// @ts-expect-error: `int` should be a number
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="k">this</span><span class="p">.</span><span class="nx">variables</span> <span class="o">=</span> <span class="p">{</span> <span class="nx">int</span><span class="o">:</span> <span class="s1">&#39;b&#39;</span> <span class="p">};</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div>]]></content:encoded>
    </item><item>
      <title>Search</title>
      <link>https://apolloelements.dev/search/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://apolloelements.dev/search/</guid>
      <description>Search the Apollo Elements documentation</description>
      
      <content:encoded><![CDATA[<p>Use the search box above to find specific topics, components, or guides in the Apollo Elements documentation.</p>
]]></content:encoded>
    </item>
  </channel>
</rss>