Web Components
Primate runs Web Components with client-side rendering.
Setup
Install
npm install @primate/webc
Configure
import config from "primate/config";
import webc from "@primate/webc";
export default config({
modules: [webc()],
});
Components
Create Web Components in components
using Primate's Component class.
<!-- components/post-index.webc -->
<script>
import Component from "@primate/webc/Component";
export default class PostIndex extends Component {
mounted(root) {
root.querySelector("h1").addEventListener("click",
_ => console.log("title clicked!"));
}
render() {
const { posts } = this.props;
return `<h1>All posts</h1>
${posts.map(post =>
`<h2><a href="/post/view/${post.id}">${post.title}</a></h2>`
).join("")}
`;
}
}
</script>
Serve the component from a route:
// routes/posts.ts
import response from "primate/response";
import route from "primate/route";
route.get(() => {
const posts = [
{ id: 1, title: "First Post" },
{ id: 2, title: "Second Post" },
];
return response.view("post-index.webc", { posts });
});
Props
Props passed to response.view
are available as this.props
in the component.
Pass props from a route:
import response from "primate/response";
import route from "primate/route";
route.get(() => {
return response.view("user.webc", {
user: { name: "John", role: "Developer" },
permissions: ["read", "write"],
});
});
Access the props in the component:
<!-- components/user.webc -->
<script>
import Component from "@primate/webc/Component";
export default class User extends Component {
render() {
const { user, permissions } = this.props;
return `
<div>
<h2>${user.name}</h2>
<p>Role: ${user.role}</p>
<ul>
${permissions.map(permission => `<li>${permission}</li>`).join("")}
</ul>
</div>
`;
}
}
</script>
Lifecycle
Web Components support lifecycle methods for managing component state and behavior.
<!-- components/counter.webc -->
<script>
import Component from "@primate/webc/Component";
export default class Counter extends Component {
mounted(root) {
// Called when component is mounted on client
console.log("Counter mounted");
}
render() {
const { value } = this.props;
return `
<div>
<button onclick="this.dispatchEvent(new CustomEvent('decrement'))">
-
</button>
<span>${value}</span>
<button onclick="this.dispatchEvent(new CustomEvent('increment'))">
+
</button>
</div>
`;
}
}
</script>
Configuration
Option | Type | Default | Description |
---|---|---|---|
fileExtensions | string[] |
[".webc"] |
Associated file extensions |
Example
import config from "primate/config";
import webc from "@primate/webc";
export default config({
modules: [
webc({
// add `.webc.html` to associated file extensions
extensions: [".webc", ".webc.html"],
}),
],
});