انتقل إلى المحتوى الرئيسي

إرسال نموذج مع نوع حقل كيان (صفحات، منتجات...)

في هذا المثال، نوضح كيفية إرسال نموذج يتضمن نوع حقل كيان، مثل الصفحات أو المنتجات، باستخدام واجهة برمجة التطبيقات OneEntry.

✅ هدف السيناريو:

  • الحصول على تكوين النموذج من منصة OneEntry
  • يقوم المستخدم باختيار أحد عناصر الكيان
  • إرسال البيانات المجمعة إلى واجهة برمجة التطبيقات OneEntry.

✅ ما تحتاجه:

  • عنوان URL صالح للمشروع (PROJECT_URL) ورمز التطبيق (APP_TOKEN) للمصادقة مع واجهة برمجة التطبيقات OneEntry.
  • نموذج مُعد مسبقًا في OneEntry مع علامة (مثل، كيان) وحقول تتضمن واحدة من نوع "كيان".
  • حقول نموذج مُعدة مسبقًا تتضمن واحدة من نوع "كيان".

📌 مهم:

  • هذه الأمثلة لا تتضمن معالجة الأخطاء.
  • يمكنك إدارة الأخطاء باستخدام كتلة try-catch أو من خلال استخدام بناء مثل await Promise.catch((error) => error).

📚 انظر في الوثائق:

📦 مرجع SDK:

جربها مباشرة

قم بتشغيل هذه الطريقة بشكل تفاعلي في صندوق JS SDK — قم بتوصيل عنوان URL لمشروعك ورمز التطبيق في الزيارة الأولى، ثم افتح:

السيناريو

1. استيراد defineOneEntry من SDK وتعريف PROJECT_URL و APP_TOKEN

مثال:

import { defineOneEntry } from 'oneentry';

const PROJECT_URL = 'your-project-url';
const APP_TOKEN = 'your-app-token';

2. إنشاء عميل API باستخدام defineOneEntry()

مثال:

const { Forms, FormData } = defineOneEntry(PROJECT_URL, {
token: APP_TOKEN,
});

3. الحصول على النموذج باستخدام Forms.getFormByMarker()

مثال:

useEffect(() => {
Forms.getFormByMarker('entity').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. الحصول على إعدادات إضافية لإرسال النموذج

مثال:

const moduleFormConfig = form.moduleFormConfigs?.[0];
if (!moduleFormConfig) {
setErrorMsg('Form has no moduleFormConfigs');
setStatus('error');
return;
}
النتيجة:
{
"id": 1,
"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
}

5. الحصول على بيانات الحقول من نموذج الواجهة الأمامية — اختر خيار كيان واحد لكل حقل من نوع الكيان (اختيار المستخدم من القائمة المعروضة)

مثال:

const fieldsData = sortedFields
.filter((f: any) => values[f.marker])
.map((f: any) => ({
marker: f.marker,
type: f.type,
value: prepareValue(f.type, values[f.marker] || ''),
}));
النتيجة:
[
{
"marker": "entity",
"type": "entity",
"value": [
"p-2-7"
]
}
]

6. نشر FormsData باستخدام FormData.postFormsData()

مثال:

const response = await FormData.postFormsData({
formIdentifier: 'entity',
formData: fieldsData,
formModuleConfigId: moduleFormConfig.id,
moduleEntityIdentifier: moduleFormConfig.entityIdentifiers?.[0]?.id || '',
replayTo: null,
status: 'sent',
}).catch((e: any) => e);
النتيجة:
{
"formData": {
"formIdentifier": "entity",
"time": "2026-06-06T10:21:42.166Z",
"formData": [
{
"marker": "entity",
"type": "entity",
"value": [
"p-2-7"
]
}
],
"entityIdentifier": "services",
"fingerprint": "UQ_zhfcsr_mpdtr691jq7d",
"isUserAdmin": false,
"formModuleId": 1,
"userIdentifier": null,
"parentId": null,
"id": 174
},
"actionMessage": ""
}

المثال النهائي

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];
if (type === 'entity') return [/^\d+$/.test(value) ? Number(value) : value];
return value;
}

const EntityForm = () => {
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('entity').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 moduleFormConfig = form.moduleFormConfigs?.[0];
if (!moduleFormConfig) {
setErrorMsg('Form has no moduleFormConfigs');
setStatus('error');
return;
}

// 5. Get fields data from the frontend form — pick one entity option per entity-typed field (the user's selection from the rendered select)
const fieldsData = sortedFields
.filter((f: any) => values[f.marker])
.map((f: any) => ({
marker: f.marker,
type: f.type,
value: prepareValue(f.type, values[f.marker] || ''),
}));

// 6. post FormsData with [FormData.postFormsData()](/docs/forms-data/postFormsData)
const response = await FormData.postFormsData({
formIdentifier: 'entity',
formData: fieldsData,
formModuleConfigId: moduleFormConfig.id,
moduleEntityIdentifier: moduleFormConfig.entityIdentifiers?.[0]?.id || '',
replayTo: null,
status: 'sent',
}).catch((e: any) => e);

if (response?.statusCode >= 400) {
setErrorMsg(response.message || 'Submission failed');
setStatus('error');
} else {
setStatus('success');
console.log('Submit response: ', response);
}
};

return (
<form onSubmit={handleSubmit}>
<h2>{form.localizeInfos?.title || 'Entity 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 === 'entity') {
const options = field.listTitles || [];
if (options.length > 0) {
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>
{options.map((opt: any) => {
// For entity fields, listTitles[].value is an object ({ id, depth, ... }),
// so use its primitive `id` for the key/value (a page id like 25 or product like "p-1-123").
const optValue = opt.value && typeof opt.value === 'object' ? opt.value.id : opt.value;
return (
<option key={optValue} value={optValue}>{opt.title}</option>
);
})}
</select>
</div>
);
}
return (
<div key={field.marker}>
<label htmlFor={field.marker}>{label}</label>
<input
id={field.marker}
type="text"
value={value}
placeholder={placeholder || 'Page id (e.g. 25) or product (e.g. p-1-123)'}
required={required}
onChange={(e: { target: { value: string; }; }) => onChange(e.target.value)}
/>
</div>
);
}

return (
<div key={field.marker}>
<label htmlFor={field.marker}>{label}</label>
<input
id={field.marker}
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>}

<button type="submit" disabled={status === 'loading'}>
{status === 'loading' ? 'Submitting...' : 'Submit'}
</button>
</form>
);
};

export default EntityForm;