Mengirimkan formulir
Dalam contoh ini, kami menunjukkan cara mengirimkan formulir menggunakan API OneEntry.
✅ Tujuan skenario:
- Mendapatkan konfigurasi formulir dari Platform OneEntry
- Mengumpulkan data input pengguna dari formulir kontak.
- Memastikan data diformat dan divalidasi dengan benar sebelum pengiriman.
- Mengirimkan data yang dikumpulkan ke API OneEntry.
✅ Apa yang Anda butuhkan:
- PROJECT_URL dan APP_TOKEN yang valid untuk otentikasi dengan API OneEntry.
- Formulir yang telah dikonfigurasi sebelumnya di OneEntry yang diidentifikasi dengan penanda (misalnya, 'contact_us').
- Bidang formulir yang telah dikonfigurasi sebelumnya.
📌 Penting:
- Tangani potensi kesalahan selama permintaan API dengan baik untuk memberikan umpan balik kepada pengguna.
- Jaga privasi dan keamanan data, terutama saat menangani informasi sensitif seperti alamat email.
- Pastikan bidang formulir dan penandanya tetap sinkron dengan konfigurasi backend untuk menghindari ketidakcocokan.
- Contoh-contoh ini tidak mencakup penanganan kesalahan.
- Anda dapat mengelola kesalahan menggunakan blok try-catch atau dengan menggunakan konstruksi seperti await Promise.catch((error) => error).
📚 Lihat di dokumentasi:
📦 Referensi SDK:
Coba secara langsung
Jalankan metode ini secara interaktif di JS SDK sandbox — sambungkan Project URL dan App Token Anda pada kunjungan pertama, lalu buka:
- Mengirimkan formulir — Dalam contoh ini, kami menunjukkan cara mengirimkan formulir menggunakan API OneEntry.
Skenario
1. Impor defineOneEntry dari SDK dan definisikan PROJECT_URL dan APP_TOKEN
Contoh:
import { defineOneEntry } from 'oneentry';
const PROJECT_URL = 'your-project-url';
const APP_TOKEN = 'your-app-token';
2. Membuat klien API dengan defineOneEntry()
Contoh:
const { Forms, FormData } = defineOneEntry(PROJECT_URL, {
token: APP_TOKEN,
});
3. Dapatkan formulir dengan Forms.getFormByMarker()
Contoh:
useEffect(() => {
Forms.getFormByMarker('contact_us').then((data: any) => {
setForm(data);
const initial: Record<string, string> = {};
data?.attributes?.forEach((a: any) => { initial[a.marker] = ''; });
setValues(initial);
console.log('Form Entity ', data);
}).catch(console.error);
}, []);
Hasil:
{
"id": 3,
"attributeSetId": 2,
"type": "data",
"localizeInfos": {
"title": "Contact us",
"titleForSite": "",
"successMessage": "Message about successful data processing",
"unsuccessMessage": "Message about unsuccessful data processing",
"urlAddress": "",
"database": "0",
"script": "0"
},
"version": 5,
"position": 1,
"identifier": "contact_us",
"processingType": "script",
"templateId": null,
"attributes": [
{
"type": "string",
"marker": "first_name",
"position": 1,
"settings": {},
"isVisible": true,
"listTitles": [],
"validators": {
"requiredValidator": {
"strict": true
}
},
"initialValue": null,
"localizeInfos": {
"title": "First name"
},
"additionalFields": {}
},
{
"type": "string",
"marker": "email",
"position": 2,
"settings": {},
"isVisible": true,
"listTitles": [],
"validators": {
"requiredValidator": {
"strict": true
},
"emailInspectionValidator": true
},
"initialValue": null,
"localizeInfos": {
"title": "Email"
},
"additionalFields": {}
},
{
"type": "string",
"marker": "surname",
"position": 3,
"settings": {},
"isVisible": true,
"listTitles": [],
"validators": {
"stringInspectionValidator": {
"stringMax": 0,
"stringMin": 0,
"stringLength": 0
}
},
"initialValue": null,
"localizeInfos": {
"title": "Surname"
},
"additionalFields": {}
},
{
"type": "list",
"marker": "topic",
"position": 4,
"settings": {},
"isVisible": true,
"listTitles": [
{
"title": "Article",
"value": "article",
"extended": {
"type": null,
"value": null
},
"position": 1
},
{
"title": "Article-2",
"value": "article-2",
"extended": {
"type": null,
"value": null
},
"position": 2
}
],
"validators": {
"requiredValidator": {
"strict": true
}
},
"initialValue": null,
"localizeInfos": {
"title": "Topic"
},
"additionalFields": {}
},
{
"type": "text",
"marker": "text",
"position": 5,
"settings": {},
"isVisible": true,
"listTitles": [],
"validators": {},
"initialValue": null,
"localizeInfos": {
"title": "Text"
},
"additionalFields": {}
},
{
"type": "button",
"marker": "send",
"position": 7,
"settings": {},
"isVisible": true,
"listTitles": [],
"validators": {},
"initialValue": null,
"localizeInfos": {
"title": "Send"
},
"additionalFields": {}
}
],
"total": "1",
"moduleFormConfigs": [
{
"id": 2,
"moduleIdentifier": "content",
"isGlobal": false,
"isClosed": false,
"viewOnlyUserData": false,
"commentOnlyUserData": false,
"entityIdentifiers": [
{
"id": "services",
"isNested": false
}
],
"ratingCalculation": "average",
"allowHalfRatings": null,
"maxRatingScale": null,
"isAnonymous": null,
"allowRerating": null,
"isRating": null
}
]
}
4. Dapatkan pengaturan tambahan untuk pengiriman formulir
Contoh:
const moduleConfig = form.moduleFormConfigs?.[0];
const sortedFields = [...(form.attributes || [])].sort(
(a: any, b: any) => a.position - b.position,
);
5. Dapatkan data bidang dari Formulir frontend
Contoh:
const formData = sortedFields
.filter((f: any) => values[f.marker])
.map((f: any) => ({
marker: f.marker,
type: f.type,
value: prepareValue(f.type, values[f.marker] || ''),
}));
Hasil:
[
{
"marker": "first_name",
"type": "string",
"value": "test"
},
{
"marker": "email",
"type": "string",
"value": "test@example.com"
},
{
"marker": "surname",
"type": "string",
"value": "test"
},
{
"marker": "topic",
"type": "list",
"value": [
"article"
]
},
{
"marker": "text",
"type": "text",
"value": [
{
"plainValue": "test"
}
]
}
]
6. kirim FormsData dengan FormData.postFormsData()
Contoh:
const result = await FormData.postFormsData({
formIdentifier: 'contact_us',
formData,
formModuleConfigId: moduleConfig?.id || 0,
moduleEntityIdentifier: moduleConfig?.entityIdentifiers?.[0]?.id || '',
replayTo: null,
status: 'sent',
}).catch((e: any) => e);
Hasil:
{
"formData": {
"formIdentifier": "contact_us",
"time": "2026-06-06T10:10:05.844Z",
"formData": [
{
"marker": "first_name",
"type": "string",
"value": "test"
},
{
"marker": "email",
"type": "string",
"value": "test@example.com"
},
{
"marker": "surname",
"type": "string",
"value": "test"
},
{
"marker": "topic",
"type": "list",
"value": [
"article"
]
},
{
"marker": "text",
"type": "text",
"value": [
{
"plainValue": "test"
}
]
}
],
"entityIdentifier": "services",
"fingerprint": "UQ_zhfcsr_mpdtr691jq7d",
"isUserAdmin": false,
"formModuleId": 2,
"userIdentifier": null,
"parentId": null,
"id": 172
},
"actionMessage": "Message about successful data processing"
}
Contoh akhir
import React from 'react';
// Note: React is a sandbox global — in your project use named imports from 'react'
const { useState, useEffect } = React;
// 1. Import defineOneEntry from SDK and define PROJECT_URL and APP_TOKEN
import { defineOneEntry } from 'oneentry';
const PROJECT_URL = 'your-project-url';
const APP_TOKEN = 'your-app-token';
// 2. Creating an API client with [defineOneEntry()](/docs/index/#Installation)
const { Forms, FormData } = defineOneEntry(PROJECT_URL, {
token: APP_TOKEN,
});
// Prepare value for API submission by field type
function prepareValue(type: string, value: string) {
if (type === 'text') return [{ plainValue: value }];
if (type === 'list' || type === 'radioButton') return [value];
return value;
}
const typeMap: Record<string, string> = {
integer: 'number',
real: 'number',
float: 'number',
date: 'date',
time: 'time',
dateTime: 'datetime-local',
};
const ContactForm = () => {
const [form, setForm] = useState<any>(null);
const [values, setValues] = useState<Record<string, string>>({});
const [status, setStatus] = useState<'idle' | 'loading' | 'success' | 'error'>('idle');
const [errorMsg, setErrorMsg] = useState('');
// 3. Get form with [Forms.getFormByMarker()](/docs/forms/getFormByMarker)
useEffect(() => {
Forms.getFormByMarker('contact_us').then((data: any) => {
setForm(data);
const initial: Record<string, string> = {};
data?.attributes?.forEach((a: any) => { initial[a.marker] = ''; });
setValues(initial);
console.log('Form Entity ', data);
}).catch(console.error);
}, []);
if (!form) return <div>Loading...</div>;
const sortedFields = [...(form.attributes || [])].sort(
(a: any, b: any) => a.position - b.position,
);
const handleSubmit = async (e: any) => {
e.preventDefault();
if (!form) return;
setStatus('loading');
// 4. Get additional settings for the form submission
const moduleConfig = form.moduleFormConfigs?.[0];
const sortedFields = [...(form.attributes || [])].sort(
(a: any, b: any) => a.position - b.position,
);
// 5. Get fields data from frontend Form
const formData = sortedFields
.filter((f: any) => values[f.marker])
.map((f: any) => ({
marker: f.marker,
type: f.type,
value: prepareValue(f.type, values[f.marker] || ''),
}));
console.log('Form Data ', formData);
// 6. post FormsData with [FormData.postFormsData()](/docs/forms-data/postFormsData)
const result = await FormData.postFormsData({
formIdentifier: 'contact_us',
formData,
formModuleConfigId: moduleConfig?.id || 0,
moduleEntityIdentifier: moduleConfig?.entityIdentifiers?.[0]?.id || '',
replayTo: null,
status: 'sent',
}).catch((e: any) => e);
if (result?.statusCode >= 400) {
setErrorMsg(result.message || 'Submission failed');
setStatus('error');
} else {
setStatus('success');
console.log('Submit result: ', result);
}
};
return (
<form onSubmit={handleSubmit}>
<h2>{form.localizeInfos?.title || 'Contact Form'}</h2>
{sortedFields.map((field: any) => {
const label = field.localizeInfos?.title || field.marker;
const value = values[field.marker] || '';
const required = !!field.validators?.requiredValidator?.strict;
const placeholder = field.additionalFields?.placeholder?.value || '';
const onChange = (val: string) =>
setValues((prev) => ({ ...prev, [field.marker]: val }));
if (field.type === 'text') {
return (
<div key={field.marker}>
<label htmlFor={field.marker}>{label}</label>
<textarea
id={field.marker}
value={value}
placeholder={placeholder}
required={required}
onChange={(e: { target: { value: string; }; }) => onChange(e.target.value)}
/>
</div>
);
}
if (field.type === 'list') {
return (
<div key={field.marker}>
<label htmlFor={field.marker}>{label}</label>
<select
id={field.marker}
value={value}
required={required}
onChange={(e: { target: { value: string; }; }) => onChange(e.target.value)}
>
<option value="">— Select —</option>
{(field.listTitles || []).map((opt: any) => (
<option key={opt.value} value={opt.value}>{opt.title}</option>
))}
</select>
</div>
);
}
if (field.type === 'radioButton') {
return (
<fieldset key={field.marker}>
<legend>{label}</legend>
{(field.listTitles || []).map((opt: any) => (
<label key={opt.value}>
<input
type="radio"
name={field.marker}
value={opt.value}
checked={value === opt.value}
onChange={() => onChange(opt.value)}
/>
{opt.title}
</label>
))}
</fieldset>
);
}
if (field.type === 'button') {
return (
<button
key={field.marker}
type="submit"
disabled={status === 'loading'}
>
{label}
</button>
);
}
return (
<div key={field.marker}>
<label htmlFor={field.marker}>{label}</label>
<input
id={field.marker}
type={typeMap[field.type] || 'text'}
value={value}
placeholder={placeholder}
required={required}
onChange={(e: { target: { value: string; }; }) => onChange(e.target.value)}
/>
</div>
);
})}
{status === 'error' && <p role="alert">{errorMsg}</p>}
{status === 'success' && <p role="status">Form submitted successfully!</p>}
</form>
);
};
export default ContactForm;