Queries: apollo-query Element
Use the <apollo-query>
element from @apollo-elements/components
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 <apollo-query>
and HTML templates.
This page is a HOW-TO guide. For detailed docs on the <apollo-query>
element's API, see the API docs
Templates use stampino and jexpr for efficiently updating data expressions. See their respective READMEs for more information.
What that means is you can define the element's dynamic template using good-old HTML:
<apollo-query>
<script type="application/json">
query Notifications {
me { id name }
notifications { href title }
}
</script>
<template>
<style>
:host([loading]) {
opacity: 0;
}
</style>
<link rel="stylesheet" href="/components/notifications.css">
<h2>Welcome, {{ data.me.name }}!</h2>
<p>You have {{ data.notifications.length }} notifications.</p>
<ol class="notifications-list">
<template type="repeat" repeat="{{ data.notifications }}">
<li>
<a href="{{ item.href }}">{{ item.title }}</a>
</li>
</template>
<ol>
</template>
</apollo-query>
Template Expressions
jexpr
expressions are like handlebars, nunjucks, polymer, etc. expressions. You can do most things you can do in JavaScript using jexpr
. Read more at the jexpr README or try it out for yourself on the Stampino REPL
Template Bindings
Template bindings follow similar conventions to lit-html. You can bind to nodes or element children, attributes, DOM properties, or even event listeners.
Content Binding
Bind to element content by adding an expression as a child of the element.
<apollo-query>
<template>
<samp>{{ data.content }}<samp>
</template>
</apollo-query>
Attribute Binding
You can bind to attributes by adding an expression in an attribute position. For boolean attributes (where their presence indicates true
and their absence false
), prefix a ?
to the attribute name.
<apollo-query>
<template>
<label>
Message
<input value="{{ data.message.content }}"/>
</label>
<button ?hidden="{{ data.isEditing }}">Edit</button>
</template>
</apollo-query>
Property Binding
Bind to DOM properties by prefixing .
to the property name.
<apollo-query>
<template>
<figure>
<img .src="{{ data.user.avatar }}" alt="avatar"/>
</figure>
</template>
</apollo-query>
Event Binding
If you pass a method to your model (e.g. by passing extra model content in the element's extras
DOM property), you can add event listeners to elements by prefixing @
to the event name in an attribute position.
<apollo-query>
<template>
<button @click="{{ onClick }}">Ping</button>
</template>
</apollo-query>
<script>
{
const queryEl = document.currentScript.getRootNode()
.querySelector('apollo-query')
queryEl.extras = {
onClick(event) {
fetch(`/ping?user=${queryEl.data.userId}`)
}
};
}
</script>
Custom Template Handlers
You can set the templateHanders
property on an <apollo-query>
element to customize rendering behaviour by adding your own custom template types.
The Stampino API is still undergoing revision. For advanced usages, we recommend writing a custom element class for now.
<apollo-query no-auto-subscribe>
<template>
<template type="flashy">
<samp>{{ data.content }}<samp>
</template>
</template>
</apollo-query>
<script>
(async function() {
import('lit').then(({ html }) => {
document.currentScript.getRootNode()
.querySelector('apollo-query')
.templateHandlers = {
flashy(template, model, handlers, renderers) => {
return html``;
},
};
document.currentScript.getRootNode()
.querySelector('apollo-query')
.subscribe();
});
})();
</script>
Next Steps
- Read the
<apollo-query>
API docs - Learn how to write mutation components