Formlar
Formlar
Bir sitenin satıcının formunu nasıl yüklediği, adımlarını ve kurallarını nasıl render ettiği, dosyaları nasıl yüklediği ve başvuruları kendi sunucusundan nasıl gönderdiği; alan türleri, kural anlamları, spam kontrolleri, anahtarlar ve sınırlar.
Markdown olarak görüntüleForms modülü, satıcının client dashboard'da iletişim, teklif ve ön görüşme formları oluşturmasını ve yanıtları dashboard'daki gelen kutusunda almasını sağlar. Siteniz soruları koda gömmez: yayınlanmış formu anahtarı (key) ile yükler, render eder ve ziyaretçinin yanıtlarını geri gönderir. Borkol yanıtları sunucuda yeniden kontrol eder, başvuruyu saklar, numaralandırır, satıcıya ve ziyaretçiye e-posta gönderir ve bir webhook tetikler.
Dört endpoint'in tamamı /v1/api/forms altında yer alır, mağaza için forms modülünün etkin olmasını gerektirir (aksi halde 403 {"error":"Module not enabled: forms"}) ve dakikada 120 isteklik mağaza geneli rate limit'e tabidir (bkz. Hatalar ve Rate Limit'ler).
| Endpoint | Scope | Amaç |
|---|---|---|
GET /v1/api/forms/{key} | forms:read | Etkin bir formun yayınlanmış sürümünü tek bir dilde yükleyin. Bkz. Form yükleme. |
GET /v1/api/forms/address-lookup | forms:read | Bir address alanı için posta kodu ve bina numarasından sokak ve şehri bulun. Bkz. Adres arama. |
POST /v1/api/forms/{key}/uploads | forms:write | Bir file alanı için tek bir dosya saklayın ve başvuru için bir token alın. Bkz. Yüklemeler. |
POST /v1/api/forms/{key}/submissions | forms:write | Bir ziyaretçinin yanıtlarını gönderin. Bkz. Başvurular. |
forms:write anahtarlarını sunucunuzda tutun
forms:write yetkisine sahip bir anahtar, satıcı adına dosya yükleyebilir ve başvuru gönderebilir; her başvuru e-posta gönderir. Bir forms:write anahtarını asla tarayıcı koduna, mobil uygulama paketine veya ziyaretçinin okuyabileceği başka bir yere koymayın. Formu yüklemeyi, dosya yüklemeyi ve gönderimi sunucunuzdan (bir route handler, server action veya backend endpoint'i ile) yapın; tarayıcının yalnızca kendi sunucunuzla konuşmasını sağlayın. Üç çağrının hepsini sunucunuz yaptığı için hem forms:read hem forms:write yetkisine sahip tek bir sunucu tarafı anahtar (örneğin BORKOL_FORMS_KEY ortam değişkeninde) yeterlidir. Formları yüklemek için yalnızca forms:read yetkili ayrı bir anahtar isteğe bağlıdır.
Bu durumda her istek sunucunuzun adresinden geldiği için, yükleme ve gönderim isteklerinde ziyaretçinin IP adresini X-Borkol-Visitor-Ip header'ında iletin. Borkol, saatlik sınırları ziyaretçi adresi başına uygular (bkz. Ziyaretçi IP'si ve saatlik sınır).
Akış
- Yükleyin: sunucunuzda
GET /v1/api/forms/{key}?locale=nl. Sonucu önbelleğe alın;form.publishedwebhook'u geldiğinde yenileyin. - Render edin: adımları sırayla gösterin. Bir adımı veya alanı yalnızca
show_ifkuralı sağlandığı sürece gösterin (bkz. Kurallar). İsterseniz yanıtları sayfa URL'sinden önceden doldurun (bkz. URL'den önceden doldurma). - Kontrol edin: ziyaretçi ilerlemeden önce her adımı sunucunun kullandığı kurallarla kontrol edin.
@borkol/formspaketi bu kuralları uygular (bkz. @borkol/forms paketi). - Dosya yükleyin: ziyaretçinin bir
filealanı için seçtiği her dosyayı yükleyin; sunucunuzdanPOST /v1/api/forms/{key}/uploadsbir token döndürür (bkz. Yüklemeler). - Spam kontrolü: form
settings.turnstile_site_keydöndürüyorsa Cloudflare Turnstile widget'ını gösterin ve token'ını gönderin (bkz. Turnstile). - Gönderin: yanıtlar, yükleme token'ları, Turnstile token'ı, ziyaretçinin dili, sayfa bilgileri ve ziyaretçi IP header'ı ile sunucunuzdan
POST /v1/api/forms/{key}/submissions. - Tamamlayın:
201yanıtındathank_you.messagedeğerini gösterin veya ziyaretçiyithank_you.redirect_urladresine gönderin.422yanıtında her hatayı kendi sorusunda gösterin ve Turnstile widget'ını sıfırlayın.429yanıtında ziyaretçiden daha sonra tekrar denemesini isteyin.
Formlar, sürümler ve durum
Bir formun bir anahtarı, bir adı, bir durumu ve numaralı sürümleri vardır.
- Anahtarı satıcı seçer: harfle başlayan küçük harf, rakam ve kısa çizgi, en fazla 64 karakter (örneğin
quote-request). Mağaza içinde benzersizdir ve form yayınlandıktan sonra değiştirilemez. - Satıcı Yayımlayın düğmesine her tıkladığında mevcut taslak yeni ve dondurulmuş bir sürüm (1, 2, 3, ...) olur. Public API her zaman yalnızca en son yayınlanmış sürümü sunar; yayınlanmamış düzenlemeler sitenize asla ulaşmaz.
- Bir form
draft,activeveyaarchiveddurumundadır. Yalnızca en az bir kez yayınlanmış etkin bir form yüklenebilir ve gönderilebilir; diğer her durumda yanıt404olur. Yayınlamak formu etkinleştirmez; etkinleştirmek veya arşivlemek de hiçbir şey yayınlamaz. - Her başvuru hangi sürüme karşı doldurulduğunu kaydeder; böylece sonraki sürümler soruları değiştirse bile satıcının gelen kutusu ziyaretçinin gördüğü soruları ve seçenek etiketlerini göstermeye devam eder.
Tanım: adımlar ve alanlar
Formun gövdesi bir adımlar listesidir; her adımın bir alanlar listesi vardır. Bir formda en fazla 20 adım ve toplamda 150 girdi alanı (heading ve paragraph sayılmaz) olabilir. Adım ve alan anahtarları form içinde benzersizdir ve /^[a-z][a-z0-9_]*$/ desenine uyar (en fazla 50 karakter). Yanıtlar alan anahtarı altında gönderilir ve saklanır.
Bir adım:
| Alan | Tür | Açıklama |
|---|---|---|
key | string | Adım anahtarı. |
title | string | İstenen dildeki adım başlığı. |
show_if | object veya null | Adımın gösterilip gösterilmeyeceğine karar veren kural; her zaman gösteriliyorsa null. |
fields | array | Adımın alanları, sırasıyla. |
Bir alan:
| Alan | Tür | Açıklama |
|---|---|---|
key | string | Alan anahtarı; yanıt bu anahtar altında gönderilir. |
kind | string | Aşağıdaki türlerden biri. |
label | string | Soru. heading ve paragraph için gösterilecek metindir; consent için onay kutusunun yanındaki metindir; hidden için satıcının gelen kutusunda gördüğü addır (render etmeyin). |
help | string veya null | Sorunun altındaki yardım metni. |
placeholder | string veya null | Giriş alanının yer tutucusu. |
required | boolean | Görünür bir alanın yanıtlanmasının zorunlu olup olmadığı. Eksik bir değeri false olarak kabul edin. |
show_if | object veya null | Alanın kuralı; (görünür bir adım içinde) her zaman gösteriliyorsa null. |
config | object | Türe özgü ayarlar; yoksa {}. |
Her metin zaten tek bir dile indirgenmiştir (bkz. Diller).
Alan türleri
Giriş türleri bir yanıt toplar; heading ve paragraph yalnızca metin gösterir ve asla gönderilmez.
| Tür | config | Yanıt değeri |
|---|---|---|
text | prefill? | string, en fazla 255 karakter. |
textarea | prefill? | string, en fazla 10000 karakter. |
number | prefill? | JSON sayısı (tam sayı veya ondalık). 0 bir yanıt sayılır. |
email | prefill? | string: geçerli bir e-posta adresi, en fazla 255 karakter. |
phone | prefill? | string: rakam, boşluk ve ()-. karakterlerinden oluşan, başında isteğe bağlı + olan 5 ile 30 karakter. |
date | prefill? | string YYYY-MM-DD. |
select | options (string listesi), prefill? | string: options değerlerinden biri. Seçenek metinleri her dilde yazıldığı gibi gösterilir. |
link | prefill? | object {url, label?}: url en fazla 2000 karakterdir ve https://, http://, / (köke göreli), mailto: veya tel: ile başlar; label isteğe bağlıdır, en fazla 200 karakter. |
choice | options, multiple?, min?, max?, prefill? | Bir seçenek value değeri (string) veya multiple: true ile seçenek değerlerinden oluşan bir liste (tekrarlar kaldırılır); ayarlanmışsa en az min, en fazla max öğe. |
consent | {} | true. Zorunlu olması, kutunun işaretlenmesi gerektiği anlamına gelir. |
hidden | source?: query (varsayılan) veya site | string, en fazla 500 karakter. Asla render edilmez; bkz. Gizli alanlar. |
file | accept (image, pdf veya ikisi), max_files (1 ile 10), max_mb (1 ile 20) | Yükleme token'larının listesi; answers içinde değil, files içinde gönderilir; aşağıdaki nota bakın. |
address | country (ISO 3166-1 alpha-2, örneğin NL), lookup?, service_area? | object {postal_code, house_number, addition?, street, city, lat?, lon?}; aşağıdaki adres alanları notuna bakın. |
heading | {} | Yok. label değerini başlık olarak gösterin. |
paragraph | {} | Yok. label değerini metin olarak gösterin (en fazla 5000 karakter, satır sonları olan düz metin). |
Bir choice seçeneği {value, label, description, icon} şeklindedir: value gönderdiğiniz değerdir (en fazla 100 karakter), label seçenek metnidir, description isteğe bağlı ikinci satırdır (string veya null), icon isteğe bağlı bir simge adıdır (/^[a-z][a-z0-9-]{0,39}$/) veya null. Bir choice alanında 1 ile 30 seçenek bulunur; bir select alanında en fazla 100 karakterlik 1 ile 50 seçenek metni bulunur.
Bir koleksiyondan seçenekler. Bir choice alanı seçeneklerini sabit bir liste yerine bir nesne koleksiyonundan alabilir. Bu durumda config, elle yazılmış bir options listesi yerine options_source taşır:
{
"multiple": false,
"options_source": {
"object_type": "services",
"label": "title",
"description": "summary",
"sort": "position",
"limit": 30
}
}| Ad | Tür | Zorunlu | Açıklama |
|---|---|---|---|
object_type | string | Evet | Mağazanın bir nesne türünün anahtarı. |
label | string | Evet | Seçenek etiketi olarak kullanılan bir metin özelliğinin anahtarı. |
description | string veya null | Hayır | Seçenek açıklaması olarak kullanılan bir metin özelliğinin anahtarı. |
sort | string veya null | Hayır | Bir sayı özelliğinin anahtarı. Seçenekler buna göre artan sırada dizilir, değeri olmayan kayıtlar sonda; sort yoksa oluşturulma sırasını izler. |
limit | integer | Hayır | Kaç seçenek sunulacağı, 1 ile 100. Varsayılan 30. |
GET /v1/api/forms/{key} yanıtında sunucu seçenekleri zaten doldurmuştur: config.options güncel seçenekleri her zamanki {value, label, description, icon} biçiminde taşır (icon null olur) ve config.options_source nesnenin içinde kalır. options değerini render edin, options_source değerini yok sayın. Seçenekler, türün herkese açık görünen kayıtlarıdır (taslaklar ve zamanlanmış kayıtlar dışarıda kalır). value, türün adresleri varsa kaydın mağazanın varsayılan dilindeki adresi (slug), yoksa kayıt kimliğidir; varsayılan dilde adresi olmayan kayıt dışarıda bırakılır. label ve description istenen dilde okunur, yoksa varsayılan dile düşülür. Her istekte yeniden aranırlar, yani seçenekler koleksiyonu izler: önbelleğe alınmış bir formu bir object_record.published, object_record.updated, object_record.unpublished veya object_record.deleted webhook'u geldiğinde yenileyin. Bir başvuru o andaki seçeneklere göre kontrol edilir; artık seçenek olmayan bir yanıt Choose one of the options. hatasını verir. multiple: true ile min ve max en fazla limit olabilir. Bir alanda options veya options_source bulunur, ikisi birden asla.
Bir consent etiketi markdown ile yazılmış tek bir bağlantı içerebilir, [gizlilik politikası](https://example.com/privacy), her zaman https://. Bunu bağlantı olarak render edin.
Dosya alanları. Bir file alanı iki adımda yanıtlanır. Önce her dosyayı POST /v1/api/forms/{key}/uploads (multipart field ve file) ile yükleyin; bu endpoint türü dosyanın içeriğine göre, boyutu max_mb değerine göre kontrol eder ve bir token döndürür. Ardından token'ları başvurunun files nesnesinde, alan anahtarından token listesine (en fazla max_files) eşleyerek gönderin, asla answers içinde değil: bir dosya alanı için answers içinde gönderilen değer yok sayılır. Bir token 24 saat geçerlidir, tek bir forma ve tek bir alana aittir ve yalnızca bir başvuru için çalışır. Bkz. Yüklemeler.
Adres alanları. Bir address alanı, answers içinde tek bir nesneyle yanıtlanır. postal_code, house_number, street ve city zorunludur (eksik bir parça This field is required. hatasını verir); addition isteğe bağlıdır; lat ve lon isteğe bağlı sayılardır (enlem -90 ile 90, boylam -180 ile 180). Baştaki ve sondaki boşluklar kırpılır ve boş bir parça eksik sayılır. Sunucu country değerini config.country içinden ekler. Hollanda (NL) posta kodu dört rakam ve iki harftir, boşluklu, tireli veya bitişik olabilir ve 1234 AB olarak saklanır; diğer ülkelerde posta kodu 2 ile 12 karakterdir. Kırpmadan sonra postal_code en fazla 12, house_number en fazla 20, addition en fazla 10, street ve city ise en fazla 255'er karakterdir. Değerdeki diğer her sorun (nesne olmaması, geçersiz posta kodu, fazla uzun bir parça, aralık dışı koordinatlar) Must be a valid address. hatasını verir. Bir kural bir adresi yalnızca filled veya empty ile test edebilir.
config.lookup: true ile formunuz, posta kodu ve bina numarasından street, city, lat ve lon değerlerini GET /v1/api/forms/address-lookup ile doldurabilir. Arama yalnızca NL için vardır; satıcı başka bir ülke için açamaz. Ziyaretçi sokak ve şehri kendisi de yazabilir, örneğin arama hiçbir şey bulmazsa.
config.service_area şu biçimdedir: {origin: {lat, lon, label?}, radius_km, mode, message}. radius_km 0'dan büyük ve en fazla 1000'dir, mode notice veya block olur, message ise bölge dışındaki bir adres için gösterilecek metindir. Sunucu, origin noktasından adres koordinatlarına kuş uçuşu mesafeyi kilometre olarak (tek ondalık) ölçer ve başvurunun meta.address alanında her adres alanı için {distance_km, in_area} saklar; satıcı bunu gelen kutusunda görür. Koordinatların nasıl belirlendiği ve block modunun bir başvuruyu ne zaman reddettiği Adres alanları ve hizmet bölgesi bölümünde anlatılır.
Neyin boş sayıldığı
Bir yanıt null, yalnızca boşluk, sekme veya satır sonlarından oluşan bir string, boş liste [], boş nesne {} veya false ise boştur. 0 dahil diğer her şey bir yanıttır. Zorunlu ve görünür bir alana verilen boş yanıt bir hatadır; isteğe bağlı bir alana verilen boş yanıt ise yalnızca saklanmaz.
Kurallar
Bir adım veya alandaki show_if, onun gösterilip gösterilmeyeceğine karar verir. Tek bir koşul veya tek bir koşul grubudur:
{ "field": "services", "op": "contains", "value": "website" }
{ "all": [
{ "field": "services", "op": "contains", "value": "website" },
{ "field": "budget", "op": "not_equals", "value": "small" }
] }
{ "any": [
{ "field": "job_type", "op": "equals", "value": "roof" },
{ "field": "job_type", "op": "equals", "value": "paint" }
] }all, her koşul sağlandığında; any, en az biri sağlandığında geçer. Gruplar iç içe olamaz. Bir koşul, formda daha önce gelen bir giriş alanını belirtir: bir alanın kuralı için kendisinden önceki bir soru (önceki bir adımda veya aynı adımda daha yukarıda); bir adımın kuralı için önceki bir adımdaki bir soru.
op | Şu durumda geçer |
|---|---|
equals | Liste yanıtının tam olarak bir öğesi vardır ve bu öğe value değerine eşittir; diğer yanıtlar value değerine eşittir. Boş bir yanıt hiçbir zaman eşit değildir. |
not_equals | equals geçmez (yani boş bir yanıt geçer). |
contains | Liste yanıtında value değerine eşit bir öğe vardır; diğer yanıtlar value değerine eşittir. |
filled | Yanıt boş değildir. value yok sayılır. |
empty | Yanıt boştur. value yok sayılır. |
equals, not_equals ve contains için value bir string, sayı veya boolean'dır. Değerler metin olarak karşılaştırılır: string'ler olduğu gibi, true ve false sırasıyla "true" ve "false" olarak, tam sayılar ondalıksız (2, 2.0 ve "2" eşittir), diğer sayılar en kısa biçimleriyle (2.5). true, "true" değerine eşittir ama 1 değerine eşit değildir; nesneler ve null hiçbir şeye eşit değildir.
Formu sırayla dolaşın. Bir adım, kuralı geçtiğinde gösterilir; bir alan, adımı gösterildiğinde ve kendi kuralı geçtiğinde gösterilir. Bir koşul, bir alanın yanıtını yalnızca o alan gösterildiği sürece okur: gizli bir alanın yanıtı boş okunur; bu yüzden bir alanı gizlemek ona bağlı her şeyi de gizler. Sunucu gönderim sırasında tam olarak bu kuralları uygular: o anda gizli olan alanlara verilen yanıtlar hata vermeden atılır ve zorunlu değildir. Gizli bir dosya alanı için gönderilen yükleme token'ları da atılır ve talep edilmez.
Gizli alanlar
Bir hidden alanı asla gösterilmez, ancak değeri başvuruyla birlikte saklanır (örneğin bir kampanya kodu veya ziyaretçinin geldiği sayfa).
source: "query"(varsayılan): değeri, sayfa URL'sindeki alan anahtarıyla aynı adı taşıyan sorgu parametresinden alın; örneğincampaignanahtarlı bir alan için?campaign=spring.source: "site": değeri form gösterilirken siteniz kendisi belirler.
Değer en fazla 500 karakterlik bir string'dir. Görünürlük kuralları gizli alanlar için de geçerlidir.
URL'den önceden doldurma
config.prefill değeri true olan bir alan, sayfa URL'sindeki alan anahtarıyla aynı adı taşıyan sorgu parametresinden doldurulabilir (?email=ada@example.com). Ziyaretçi yine de değiştirebilir; sunucu bunu normal bir yanıt olarak ele alır. Onay ve dosya alanları asla önceden doldurulmaz.
Diller
Form metinleri dashboard'da dil başına yazılır. GET /v1/api/forms/{key}?locale= her metni o dilde döndürür; yoksa mağazanın varsayılan diline, o da yoksa metni olan herhangi bir dile geri döner. Mağaza için etkin olmayan bir locale varsayılan dili sunar (hata vermez). Başvuruda da aynı locale değerini gönderin: yanıttaki teşekkür mesajının ve ziyaretçiye giden onay e-postasının dilini belirler.
Ziyaretçi IP'si ve saatlik sınır
Her formun, satıcının belirlediği ziyaretçi başına saatlik bir başvuru sınırı vardır (1 ile 100 arası, varsayılan 5). 422 ile doğrulamadan geçemeyenler dahil her deneme sayılır; sınırın üzerinde API 429 {"message": "Too many submissions. Try again later."} döndürür. Saat, ziyaretçinin ilk denemesiyle başlar.
Borkol ziyaretçiyi, sunucunuzun ziyaretçinin IP adresiyle (IPv4 veya IPv6) doldurduğu X-Borkol-Visitor-Ip header'ı ile tanır. Yalnızca kendi proxy'nizin veya barındırma sağlayıcınızın belirlediği bir adrese güvenin: güvenilir bir proxy üzerine yazmadıkça X-Forwarded-For header'ının ilk adımı ziyaretçi tarafından taklit edilebilir. Header yoksa veya geçerli bir IP adresi değilse Borkol bağlantının adresini, yani sunucunuzu kullanır; bu durumda tüm ziyaretçileriniz tek bir sınırı paylaşır. Header yalnızca form route'larında okunur.
Ham IP adresi asla saklanmaz: başvuru yalnızca onun HMAC-SHA256 hash'ini tutar.
Yüklemelerin kendi sınırı vardır: form ve ziyaretçi başına saatte 30, aynı şekilde sayılır (bkz. Yüklemeler).
Honeypot
İnsanların hiç görmediği bir giriş alanı ekleyin (type="hidden" ile değil, CSS ile gizlenmiş; tabindex="-1" ve autocomplete="off" ile) ve değerini honeypot olarak gönderin. Botlar genellikle her alanı doldurur. honeypot boş bir string veya null dışında herhangi bir değer taşıyorsa Borkol 201 ile number: null ve formun teşekkür ayarlarını döndürür; hiçbir şey saklamaz, e-posta veya webhook göndermez, Turnstile'ı kontrol etmez ve denemeyi saatlik sınıra saymaz.
Turnstile
Satıcı Cloudflare Turnstile özelliğini form başına açabilir ve mağazanın Turnstile site key ile secret key değerlerini dashboard'da bir kez kaydeder. Formda Turnstile açıksa ve iki anahtar da ayarlanmışsa GET /v1/api/forms/{key} settings.turnstile_site_key döndürür; aksi halde bu alan yoktur.
- Turnstile widget'ını bu site key ile render edin ve ürettiği token'ı başvuruyla birlikte
turnstile_tokenolarak gönderin. - Borkol token'ı saatlik sınırdan sonra ve yanıtları kontrol etmeden önce Cloudflare'de doğrular (
X-Borkol-Visitor-Ipiçindeki ziyaretçi IP'si ile). Eksik, geçersiz, süresi dolmuş veya daha önce kullanılmış bir token, bir Cloudflare hatası ya da 5 saniyeden uzun süren bir kontrol, hatasıturnstileüzerinde olan bir422döndürür:The spam check failed. Reload the page and try again. - Bir token yalnızca bir kez çalışır. Token yanıtlardan önce kontrol edildiği için her
422(yanlış bir yanıt da) token'ı tüketmiştir. Her422sonrasında widget'ı sıfırlayın ve yeni token'ı sonraki denemeyle gönderin. - Başarısız bir kontrol de saatlik sınıra sayılır.
Formda Turnstile açık olduğu halde mağaza iki anahtarı da ayarlamamışsa hiçbir şey doğrulanmaz: turnstile_site_key yoktur, bir turnstile_token yok sayılır ve başvurular kontrol olmadan kabul edilir. Dashboard satıcıyı bu konuda formda ve Forms ayarları sayfasında uyarır.
Başvurudan sonra ne olur
Borkol görünür yanıtları (hidden alan değerleri dahil) form sürümü, dil ve gönderdiğiniz sayfa bilgileriyle birlikte saklar. Ziyaretçinin name değerini name anahtarlı alandan, email değerini yanıtlanmış ilk email alanından, phone değerini yanıtlanmış ilk phone alanından alır. Yüklenen dosyalar başvuruya eklenir ve gizli olarak saklanır: satıcı bunları gelen kutusundan açar; herkese açık bir URL yoktur. Bu e-posta adresi mağazanın tam olarak bir kişisiyle (büyük/küçük harf duyarsız) eşleşirse başvuru o kişiye bağlanır; Borkol asla kişi oluşturmaz.
Başvuru saklandıktan sonra Borkol satıcıya e-posta gönderir, form bunu içeriyorsa ve ziyaretçi bir e-posta adresi verdiyse ziyaretçiye onay e-postası gönderir, dashboard'a bir bildirim ekler ve form_submission.created webhook'unu gönderir. Bunların hiçbiri isteği başarısız kılamaz: saklandıktan sonra yanıt 201 olur.
Public API'de başvuruları geri okumak için bir endpoint yoktur. Satıcı bunları dashboard'daki gelen kutusunda ele alır.
@borkol/forms paketi
@borkol/forms, bu endpoint'lerin türlerini ve sunucuyla aynı kuralları içeren, bağımlılığı olmayan bir TypeScript paketidir (MIT); böylece siteniz göndermeden önce aynı adımları ve aynı hataları gösterebilir. @borkol/forms paketini kurun; React isteğe bağlı bir peer'dır ve yalnızca @borkol/forms/react tarafından kullanılır.
import { visible, check, prefill, type PublicForm } from "@borkol/forms";
const form: PublicForm = (await res.json()).data;
visible(form, answers); // { steps: ["what", ...], fields: ["services", ...] }
check(form, answers); // { errors: { "answers.email": ["Must be an email address."] }, clean: {...} }
check(form, answers, "what"); // check one step only
prefill(form, new URLSearchParams(location.search));visible, gösterilen adımların ve alanların anahtarlarını döndürür.check,answers.{key}anahtarlı ve sunucunun İngilizce mesajlarını içerenerrorsdeğerini (kendi çevirilerinize eşleyebilmeniz içinMESSAGESolarak dışa aktarılır) ve gönderilecek yanıtlar olancleandeğerini döndürür: kurallarıyla gizlenen alanlar, görüntüleme türleri ve bilinmeyen anahtarlar çıkarılmıştır.hiddentüründeki değerler korunur.prefill,config.prefilliçeren alanların vequerykaynaklıhiddenalanların yanıtlarını URL sorgu parametrelerinden okur.
@borkol/forms/react, adımları sizin bileşenlerinizle render eder:
import { BorkolForm } from "@borkol/forms/react";
<BorkolForm
form={form}
locale="nl"
onSubmit={(body) => submitToMyServer(body)} // resolves to { number, thank_you }
components={{
text: ({ field, value, onChange, errors }) => (
<label>{field.label}<input value={(value as string) ?? ""} onChange={(e) => onChange(e.target.value)} />{errors[0]}</label>
),
heading: ({ field }) => <h2>{field.label}</h2>,
nav: ({ isFirst, isLast, back, submitting }) => (
<>{!isFirst && <button type="button" onClick={back}>Back</button>}<button disabled={submitting}>{isLast ? "Send" : "Next"}</button></>
),
done: ({ result }) => <p>{result.thank_you.message}</p>,
}}
/>;onSubmit, kontrol edilmiş yanıtlarla birlikte {locale, answers, files?, turnstile_token?} başvuru gövdesini alır; bunu kendi sunucunuza gönderin; sunucunuz meta ve honeypot ekleyebilir ve gövdeyi forms:write anahtarı ve ziyaretçi IP header'ı ile iletir. Sunucunun 422 hatalarını göstermek için yanıt gövdesini (errors içeren nesneyi) onSubmit içinden fırlatın: gösterilen sorulardaki hatalar o sorularda görünür, diğer her anahtar (turnstile, şu anda gizli olan bir soru) formErrors içine gider; bunu nav bileşeni ve formError bileşeni alır. Fırlatılan başka her şey (bir ağ hatası) orada genel bir mesaj gösterir; submit() asla reddedilmez.
Diğer seçenekler:
upload(field, file)birfilealanı için tek bir dosya saklar: dosyayı multipart (field,file) olarak sunucunuzdaki ve onuPOST /v1/api/forms/{key}/uploadsadresine ileten bir route'a gönderin ve yanıtındatadeğeriyle ({token, name, size}) resolve edin. Mesajı sorunun altında göstermek için422gövdesini fırlatın. Bir dosya alanının yanıtı bu durumda yüklenen dosyaların listesidir;filebileşeniupload,remove,uploadingveaccept(giriş alanınınacceptözniteliği için) değerlerini alır. Paket yüklemeden öncemax_filesvemax_mbdeğerlerini kontrol eder ve token'larıfilesaltında gönderir.turnstileToken, Turnstile widget'ının güncel token'ıdır veturnstile_tokenolarak gönderilir.onServerErrors(errors)her başarısız gönderimden sonra çağrılır. Turnstile widget'ını burada sıfırlayın: token'ı tükenmiştir.persistKey, ziyaretçinin taslağını (yanıtlar ve geçerli adım)localStorage[persistKey]içinde tutar ve mount'tan hemen sonra geri yükler; böylece sayfa yenilense de ziyaretçi kaldığı yerden devam eder.initialAnswersayarladığı anahtarlarda önceliklidir, dosya yanıtları saklanmaz ve taslak başarılı bir gönderimden sonra silinir. 30 günden eski bir taslak yok sayılır ve silinir.localStorageyoksa form eskisi gibi çalışır.- Bir
addressalanı her zamankicomponents.addressprop'larını alır (field,value,onChange,errors); arama sizin bileşeninizde kalır.formatAddress,normaliseAddressvedistanceKmpaketin kökünden dışa aktarılır.
useBorkolForm({ form, initialAnswers, persistKey, locale, onSubmit, upload, turnstileToken, onServerErrors }), tamamen özel bir yerleşim için aynı durumu verir: step, stepIndex, steps, fields, answers, errors (alan anahtarına göre), formErrors, setAnswer, upload(key, files), removeFile(key, token), uploading, next() (mevcut adımı kontrol eder), back(), submit(), submitting ve result (honeypot isabetinden sonra result.number null olur). site kaynaklı hidden alanları initialAnswers içinde iletin.
Sunucu belirleyici olmaya devam eder: site ne yaparsa yapsın her başvuruyu yeniden kontrol eder.