Frontend-Integrationsbeispiele
Das Widget ist ein standardmäßiges Custom Element, also funktioniert es in jedem Framework ohne Wrapper zum Installieren. Die Form ist immer dieselbe: lad das Paket einmal (clientseitige Integration), render <caputchin-widget sitekey="cpt_pub_..."> in deinem Formular und lies das versteckte caputchin-token-Feld aus, das es einfügt, wenn der Besucher die Aufgabe löst. Für ein Spiel tausch <caputchin-game ... game="caputchin/games/leaf-memory"> ein.
Die Beispiele unten unterscheiden sich nur in der Syntax jedes Frameworks und seiner einen Custom-Element-Eigenheit.
Reines HTML
Das eingefügte Feld reitet mit einem normalen Formular-POST mit, also gibt es nichts zu verdrahten:
<script src="https://cdn.jsdelivr.net/npm/@caputchin/widget@3/dist/widget.js"></script>
<form action="/contact" method="POST">
<input name="email" type="email" required />
<caputchin-widget sitekey="cpt_pub_..."></caputchin-widget>
<button type="submit">Send</button>
</form>React
Importier einmal beim Start, dann lies das Feld beim Absenden aus FormData:
import "@caputchin/widget";
export function ContactForm() {
async function handleSubmit(e) {
e.preventDefault();
const data = new FormData(e.currentTarget);
await fetch("/api/contact", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({ email: data.get("email"), token: data.get("caputchin-token") }),
});
}
return (
<form onSubmit={handleSubmit}>
<input name="email" type="email" required />
<caputchin-widget sitekey="cpt_pub_..." />
<button type="submit">Send</button>
</form>
);
}Wenn du TypeScript mit React nutzt, deklarier beide Elemente einmal, damit JSX sie akzeptiert:
// caputchin.d.ts
import type { DetailedHTMLProps, HTMLAttributes } from "react";
declare module "react" {
namespace JSX {
interface IntrinsicElements {
"caputchin-widget": DetailedHTMLProps<HTMLAttributes<HTMLElement> & { sitekey: string }, HTMLElement>;
"caputchin-game": DetailedHTMLProps<HTMLAttributes<HTMLElement> & { sitekey: string; game?: string; games?: string }, HTMLElement>;
}
}
}Diese declare module "react"-Form ist spezifisch für Reacts JSX. In reinem TypeScript sind die Elemente einfach HTMLElement und brauchen keine Deklaration, und die anderen Frameworks unten typisieren Custom Elements auf ihre eigene Weise, also brauchst du diesen Block nur in einem React-Projekt.
Vue
Sag Vues Compiler, dass caputchin--Tags Custom Elements sind, damit er nicht versucht, sie als Komponenten aufzulösen:
// vite.config.js
export default {
plugins: [vue({ template: { compilerOptions: { isCustomElement: (tag) => tag.startsWith("caputchin-") } } })],
};<script setup>
import "@caputchin/widget";
function onSubmit(e) {
const data = new FormData(e.target);
// send data.get("caputchin-token") to your backend
}
</script>
<template>
<form @submit.prevent="onSubmit">
<input name="email" type="email" required />
<caputchin-widget sitekey="cpt_pub_..."></caputchin-widget>
<button type="submit">Send</button>
</form>
</template>Svelte
Svelte rendert Custom Elements wie sie sind, keine Konfiguration nötig:
<script>
import "@caputchin/widget";
function onSubmit(e) {
const data = new FormData(e.currentTarget);
// send data.get("caputchin-token") to your backend
}
</script>
<form on:submit|preventDefault={onSubmit}>
<input name="email" type="email" required />
<caputchin-widget sitekey="cpt_pub_..."></caputchin-widget>
<button type="submit">Send</button>
</form>Angular
Füg CUSTOM_ELEMENTS_SCHEMA zum Modul oder zur Standalone-Komponente hinzu, damit Angular das unbekannte Tag erlaubt, und importier das Paket einmal (in main.ts):
import { Component, CUSTOM_ELEMENTS_SCHEMA } from "@angular/core";
import "@caputchin/widget";
@Component({
selector: "contact-form",
schemas: [CUSTOM_ELEMENTS_SCHEMA],
template: `
<form (submit)="onSubmit($event)">
<input name="email" type="email" required />
<caputchin-widget sitekey="cpt_pub_..."></caputchin-widget>
<button type="submit">Send</button>
</form>
`,
})
export class ContactFormComponent {
onSubmit(e: Event) {
const data = new FormData(e.target as HTMLFormElement);
// send data.get("caputchin-token") to your backend
}
}Next.js
Derselbe React-Code funktioniert. Das Custom Element rendert beim Server-Rendering als leeres Tag und wird auf dem Client aktualisiert, sobald das Paket lädt, also ist über das Importieren von @caputchin/widget in einer Client-Komponente hinaus nichts Besonderes nötig (oder lad das CDN-Script mit next/script).
Siehe auch
- Clientseitige Integration für die Lade-Optionen.
- Serverseitige Integration für die Backend-Hälfte.