This page is a series of examples of increasing levels of complexity of component.
This list is still a work in progress, with broad outlines for functionality in some cases rather than completed examples. Every example in here is very buildable though right now, and the full examples will fill out here shortly.
Have a minute? Have a go at building one of the extras and filling this out yourself!
The simplest web component just acts as a simple placeholder for some static content.
With the web component below, rendering <my-greeting></my-greeting>
will result in
<my-greeting>Hi there</my-greeting>
.
var components = require("server-components");
var StaticElement = components.newElement();
StaticElement.createdCallback = function () {
this.innerHTML = "Hi there";
};
components.registerElement("my-greeting", { prototype: StaticElement });
This is very basic, and toy cases like this aren't immediately useful, but this can be helpful for standard chunks of boilerplate that you need to include repeatedly.
Static page footers or sets of standard static meta tags can be easily swapped out, so you can ignore all their cruft entirely and focus on the real content of your page.
As a more reusable example, you could create a <country-selector><country-selector>
component, which
rendered a select dropdown with a list of every country.
Slightly more interesting web components emerge when we consider rendering dynamic content. A simple example is below: a visitor counter. All the rage in the 90s, with web components these can make a comeback!
var components = require("server-components");
var CounterElement = components.newElement();
var currentCount = 0;
CounterElement.createdCallback = function () {
currentCount += 1;
this.innerHTML = "There have been " + currentCount + " visitors.";
};
components.registerElement("visitor-counter", { prototype: CounterElement });
After a few visitors, this will render <visitor-counter></visitor-counter>
into something like
<visitor-counter>There have been 435 visitors</visitor-counter>
.
Some caveats:
-
Storage here is just in a variable, not any persistent storage outside the server process, so this counter will get reset whenever we restart the server.
-
We count every time the component is rendered as a page load. If you have this component on the same page repeatedly you'll be double counting.
TODO: A component that renders a QR code
<qr-code url="http://google.com"></qr-code>
becomes
<qr-code url="http://google.com><img src="data:image/gif;base64,R0lGODlhEAAQAM..."></img></qr-code>"
Components can be parameterized in all sorts of ways. One interesting pattern is to wrap some normal HTML content in a component, and use that to transform the content.
For example, you might want a component that wraps HTML, parses all the text within, and replaces URL strings with actual links (using the excellent Linkify library, but here in a server side DOM, not a real one):
var components = require("server-components");
var linkify = require("linkifyjs/element");
var LinkifyElement = components.newElement();
LinkifyElement.createdCallback = function (document) {
// Delegate the whole thing to a real normal front-end library!
linkify(this, { target: () => null, linkClass: "autolinked" }, document);
};
components.registerElement("linkify-urls", { prototype: LinkifyElement });
With this, we can pass HTML into Server Components that looks like
<linkify-urls>Have you heard of www.facebook.com?</linkify-urls>
and then serve up to our users:
<linkify-urls>
Have you heard of
<a href="http://www.facebook.com" class="autolinked">www.facebook.com</a>?
</linkify-urls>
TODO: A component that queries twitter, and renders the output to the page
<recent-tweets max=10></recent-tweets>
TODO: An element that renders social media icons, from its own set of bundled icons
<social-media-icons twitter="pimterry"></social-media-icons>
becomes
<social-media-icons twitter="pimterry">
<a href="http://twitter.com/pimterry">
<img src="/components/social-media-icons/twitter.png" alt="My Twitter" />
</a>
</social-media-icons>
## Element interactions through DOM properties
TODO: A component that renders a table of contents from the headings on the page
```html
<table-of-contents></table-of-contents>
<h1>Newsflash!</h1>
...
<h2>A subtitle</h2>
...
<h3>More news</h3>
...
<h2>And even more!</h2>
becomes
<table-of-contents>
<ol>
<li>
<a href="#h1-1">Newsflash</a>
<ol>
<li>
<a href="#h2-1">A subheading</a>
<ol>
<li><a href="#h3-1">More news</a></li>
</ol>
</li>
<li><a href="#h2-2">And even more!</a></li>
</ol>
</li>
</ol>
</table-of-contents>
<h1 id='h1-1'>Newsflash!</h1>
...
<h2 id='h2-1'>A subheading</h2>
...
<h3 id='h3-1'>More news</h3>
...
<h2 id='h2-2'>And even more!</h2>
TODO: A component that listens for content, and a series of subcomponents that load external data and trigger DOM events when it arrives.
<item-feed>
<twitter-item-source username="pimterry"></twitter-item-source>
<bbc-news-item-source></bbc-news-item-source>
<rss-feed-item-source url="http://example.com/feed.xml"></rss-feed-item-source>
</item-feed>