This repository has been archived on 2026-05-05. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
Will Anderson 143137e2b4 add ssr-counter example demonstrating SSR + hydration end-to-end
Counter.el defines Counter, CounterPair, and App components with {#if}
conditionals, event handlers, and child component composition.

render.js (generated by elc-ui --target=server) is the Node.js render
script the server calls. app.js (generated by elc-ui --target=web) is the
compiled browser module. hydrate.js attaches the runtime to the
server-rendered DOM without replacing it.

index.html shows the integration point with instructions for injecting
server output and the two CLI commands needed to regenerate both targets.
2026-05-04 12:49:19 -05:00

119 lines
5.0 KiB
JavaScript

import { Component, Graph, Renderer, Router, mount } from '../../dist/el-ui.js';
class Counter extends Component {
constructor(props = {}) {
super();
this.props = props;
this._graph = new Graph();
this._stateNodes = {};
this._state = {};
this._stateNodes['count'] = this._graph.seed({ type: 'state', name: 'count', content: 0 });
this._state['count'] = 0;
this._stateNodes['history'] = this._graph.seed({ type: 'state', name: 'history', content: "" });
this._state['history'] = "";
for (const [key, nodeId] of Object.entries(this._stateNodes)) {
this._graph.subscribe(nodeId, (node) => {
this._state[key] = node.content;
if (this._renderer) this._renderer.patch();
});
}
}
setState(name, value) {
if (this._stateNodes[name] !== undefined) {
this._graph.update(this._stateNodes[name], value);
}
}
increment() {
const __self = this;
const count = this._state['count'];
const history = this._state['history'];
const initialValue = this.props['initialValue'] !== undefined ? this.props['initialValue'] : 0;
const label = this.props['label'] !== undefined ? this.props['label'] : "Counter";
__self.setState('count', count + 1)
__self.setState('history', history + "+" + count + " ")
}
decrement() {
const __self = this;
const count = this._state['count'];
const history = this._state['history'];
const initialValue = this.props['initialValue'] !== undefined ? this.props['initialValue'] : 0;
const label = this.props['label'] !== undefined ? this.props['label'] : "Counter";
__self.setState('count', count - 1)
__self.setState('history', history + "-" + count + " ")
}
reset() {
const __self = this;
const count = this._state['count'];
const history = this._state['history'];
const initialValue = this.props['initialValue'] !== undefined ? this.props['initialValue'] : 0;
const label = this.props['label'] !== undefined ? this.props['label'] : "Counter";
__self.setState('count', 0)
__self.setState('history', "")
}
render() {
const __self = this;
const count = this._state['count'];
const history = this._state['history'];
const initialValue = this.props['initialValue'] !== undefined ? this.props['initialValue'] : 0;
const label = this.props['label'] !== undefined ? this.props['label'] : "Counter";
return `<div class="counter" data-el-tag="div"><h2 class="counter-label" data-el-tag="h2">${label }</h2><div class="count-display" data-el-tag="div"><span class="${count > 0 ? "count positive" : count < 0 ? "count negative" : "count zero"}" data-el-tag="span">${count }</span></div><div class="buttons" data-el-tag="div"><button class="btn btn-decrement" data-el-click="() => decrement()" data-el-tag="button">-</button><button class="btn btn-reset" data-el-click="() => reset()" data-el-tag="button">reset</button><button class="btn btn-increment" data-el-click="() => increment()" data-el-tag="button">+</button></div>${(history != "") ? `<div class="history" data-el-tag="div"><span class="history-label" data-el-tag="span">history:</span><code data-el-tag="code">${history }</code></div>` : ``}${(count == 0) ? `<p class="hint" data-el-tag="p">Press + or - to begin.</p>` : ``}</div>`;
}
}
class CounterPair extends Component {
constructor(props = {}) {
super();
this.props = props;
this._graph = new Graph();
this._stateNodes = {};
this._state = {};
}
setState(name, value) {
if (this._stateNodes[name] !== undefined) {
this._graph.update(this._stateNodes[name], value);
}
}
render() {
const __self = this;
return `<div class="counter-pair" data-el-tag="div">${__self._child(Counter, { label: "Left" })}${__self._child(Counter, { label: "Right" })}</div>`;
}
}
class App extends Component {
constructor(props = {}) {
super();
this.props = props;
this._graph = new Graph();
this._stateNodes = {};
this._state = {};
}
setState(name, value) {
if (this._stateNodes[name] !== undefined) {
this._graph.update(this._stateNodes[name], value);
}
}
render() {
const __self = this;
return `<div class="app" data-el-tag="div"><header class="app-header" data-el-tag="header"><h1 data-el-tag="h1">el-ui SSR + Hydration</h1><p class="subtitle" data-el-tag="p">Server-rendered, client-hydrated with spreading activation</p></header><main class="app-main" data-el-tag="main">${__self._child(Counter, { label: "Main Counter" })}${__self._child(CounterPair, { })}</main></div>`;
}
}
export { Counter, CounterPair, App };