Yeni bir etkinlik ve özel öğe API'leri sayesinde formlara katılım çok daha kolay hale geldi.
Birçok geliştirici, tarayıcıya yerleşik olmayan denetimler sağlamak veya yerleşik form denetimleriyle mümkün olanın ötesinde görünüm ve izlenimi özelleştirmek için özel form denetimleri oluşturur.
Ancak yerleşik HTML form kontrollerinin özelliklerini kopyalamak zor olabilir. Bir <input>
öğesini forma eklediğinizde otomatik olarak sahip olduğu özelliklerden bazıları şunlardır:
- Giriş, formun denetimler listesine otomatik olarak eklenir.
- Girişin değeri, formla birlikte otomatik olarak gönderilir.
- Giriş, form doğrulamasına dahildir.
:valid
ve:invalid
sözde sınıflarını kullanarak girişe stil uygulayabilirsiniz. - Form sıfırlandığında, yeniden yüklendiğinde veya tarayıcı form girişlerini otomatik olarak doldurmaya çalıştığında girişe bildirim gönderilir.
Özel form denetimlerinde genellikle bu özelliklerden birkaçı bulunur. Geliştiriciler, JavaScript'teki bazı sınırlamaların üstesinden gelebilir. Örneğin, form gönderme işlemine katılmak için bir forma gizli <input>
ekleyebilirler. Ancak diğer özellikler yalnızca JavaScript'te kopyalanamaz.
Özel form denetimleri oluşturmayı kolaylaştıran ve mevcut özel denetimlerin sınırlamalarını ortadan kaldıran iki yeni web özelliği:
formdata
etkinliği, rastgele bir JavaScript nesnesinin form gönderme işlemine katılmasına izin verir. Böylece gizli bir<input>
kullanmadan form verileri ekleyebilirsiniz.- Formla ilişkili özel öğeler API'si, özel öğelerin yerleşik form denetimlerine benzer şekilde hareket etmesini sağlar.
Bu iki özellik, daha iyi çalışan yeni kontrol türleri oluşturmak için kullanılabilir.
Etkinliğe dayalı API
formdata
etkinliği, herhangi bir JavaScript kodunun form gönderimine katılmasına olanak tanıyan düşük düzey bir API'dir. Bu mekanizma şu şekilde işler:
- Etkileşimde bulunmak istediğiniz forma bir
formdata
etkinlik dinleyicisi eklersiniz. - Bir kullanıcı gönder düğmesini tıkladığında form, gönderilen tüm verileri barındıran bir
FormData
nesnesi içeren birformdata
etkinliği tetikler. - Her
formdata
dinleyici, form gönderilmeden önce verilere ekleme veya verileri değiştirme şansı elde eder.
Aşağıda, formdata
etkinlik dinleyicisine tek bir değer gönderme örneği verilmiştir:
const form = document.querySelector('form');
// FormData event is sent on <form> submission, before transmission.
// The event has a formData property
form.addEventListener('formdata', ({formData}) => {
// https://developer.mozilla.org/docs/Web/API/FormData
formData.append('my-input', myInputValue);
});
Glitch'teki örneğimizi kullanarak bunu deneyin. API'nin nasıl çalıştığını görmek için Chrome 77 veya sonraki bir sürümde çalıştırdığınızdan emin olun.
Tarayıcı uyumluluğu
Formla ilişkilendirilmiş özel öğeler
Etkinlik tabanlı API'yi her tür bileşenle kullanabilirsiniz ancak yalnızca gönderim süreciyle etkileşim kurmanıza olanak tanır.
Standartlaştırılmış form kontrolleri, göndermenin yanı sıra form yaşam döngüsünün birçok bölümünde yer alır. Formla ilişkilendirilmiş özel öğeler, özel widget'lar ile yerleşik kontroller arasındaki boşluğu doldurmayı amaçlar. Formla ilişkilendirilmiş özel öğeler, standartlaştırılmış form öğelerinin birçok özelliğiyle eşleşir:
- Formla ilişkilendirilmiş bir özel öğeyi
<form>
öğesinin içine yerleştirdiğinizde, tarayıcı tarafından sağlanan kontrol gibi otomatik olarak formla ilişkilendirilir. - Öğe,
<label>
öğesi kullanılarak etiketlenebilir. - Öğe, formla birlikte otomatik olarak gönderilen bir değer ayarlayabilir.
- Öğe, geçerli girişe sahip olup olmadığını belirten bir işaret ayarlayabilir. Form kontrollerinden birinde geçersiz giriş varsa form gönderilemez.
- Bu öğe, formun devre dışı bırakılması veya varsayılan durumuna sıfırlanması gibi, form yaşam döngüsünün çeşitli bölümleri için geri çağırmalar sağlayabilir.
- Öğe, form kontrolleri için standart CSS sözde sınıflarını (ör.
:disabled
ve:invalid
) destekler.
Çok fazla özellik var! Bu makalede bunların hepsi ele alınmasa da özel öğenizi bir formla entegre etmek için gereken temel bilgiler açıklanmaktadır.
Formla ilişkili özel öğe tanımlama
Özel bir öğeyi formla ilişkili bir özel öğeye dönüştürmek için fazladan birkaç adım gerekir:
- Özel öğe sınıfınıza statik bir
formAssociated
özelliği ekleyin. Bu, tarayıcıya öğeyi bir form kontrolü gibi işlemesini söyler. setFormValue()
vesetValidity()
gibi form denetimlerinde ekstra yöntemler ve özelliklere erişmek için öğedeattachInternals()
yöntemini çağırın.- Form denetimleri tarafından desteklenen ortak özellikleri ve yöntemleri (ör.
name
,value
vevalidity
) ekleyin.
Bu öğeler, temel bir özel öğe tanımına nasıl uyar?
// Form-associated custom elements must be autonomous custom elements--
// meaning they must extend HTMLElement, not one of its subclasses.
class MyCounter extends HTMLElement {
// Identify the element as a form-associated custom element
static formAssociated = true;
constructor() {
super();
// Get access to the internal form control APIs
this.internals_ = this.attachInternals();
// internal value for this control
this.value_ = 0;
}
// Form controls usually expose a "value" property
get value() { return this.value_; }
set value(v) { this.value_ = v; }
// The following properties and methods aren't strictly required,
// but browser-level form controls provide them. Providing them helps
// ensure consistency with browser-provided controls.
get form() { return this.internals_.form; }
get name() { return this.getAttribute('name'); }
get type() { return this.localName; }
get validity() {return this.internals_.validity; }
get validationMessage() {return this.internals_.validationMessage; }
get willValidate() {return this.internals_.willValidate; }
checkValidity() { return this.internals_.checkValidity(); }
reportValidity() {return this.internals_.reportValidity(); }
…
}
customElements.define('my-counter', MyCounter);
Kaydettikten sonra bu öğeyi, tarayıcı tarafından sağlanan bir form denetimini kullanacağınız her yerde kullanabilirsiniz:
<form>
<label>Number of bunnies: <my-counter></my-counter></label>
<button type="submit">Submit</button>
</form>
Değer ayarlama
attachInternals()
yöntemi, form denetimi API'lerine erişim sağlayan bir ElementInternals
nesnesi döndürür. Bunlardan en temel olanı, kontrolün mevcut değerini belirleyen setFormValue()
yöntemidir.
setFormValue()
yöntemi üç değer türünden birini alabilir:
- Dize değeri.
File
nesnesi.FormData
nesnesi. Birden fazla değer iletmek için birFormData
nesnesi kullanabilirsiniz (örneğin, bir kredi kartı giriş denetimi kart numarası, son kullanma tarihi ve doğrulama kodu iletebilir).
Basit bir değer ayarlamak için:
this.internals_.setFormValue(this.value_);
Birden fazla değer ayarlamak için aşağıdaki gibi bir işlem yapabilirsiniz:
// Use the control's name as the base name for submitted data
const n = this.getAttribute('name');
const entries = new FormData();
entries.append(n + '-first-name', this.firstName_);
entries.append(n + '-last-name', this.lastName_);
this.internals_.setFormValue(entries);
Giriş doğrulaması
Kontrolünüz, internals nesnesinde setValidity()
yöntemini çağırarak da form doğrulamasına katılabilir.
// Assume this is called whenever the internal value is updated
onUpdateValue() {
if (!this.matches(':disabled') && this.hasAttribute('required') &&
this.value_ < 0) {
this.internals_.setValidity({customError: true}, 'Value cannot be negative.');
}
else {
this.internals_.setValidity({});
}
this.internals.setFormValue(this.value_);
}
Formla ilişkilendirilmiş özel bir öğeye, yerleşik bir form denetimi gibi :valid
ve :invalid
sözde sınıflarıyla stil uygulayabilirsiniz.
Yaşam döngüsü geri çağırmaları
Formla ilişkilendirilmiş özel öğe API'si, form yaşam döngüsü ile ilişkilendirilecek ek yaşam döngüsü geri çağırma yöntemi grubu içerir. Geri çağırmalar isteğe bağlıdır: Yalnızca öğenizin yaşam döngüsünün o noktasında bir şey yapması gerekiyorsa geri çağırma uygulayın.
void formAssociatedCallback(form)
Tarayıcı, öğeyi bir form öğesiyle ilişkilendirdiğinde veya öğenin form öğesiyle ilişkisini kaldırdığında çağrılır.
void formDisabledCallback(disabled)
Öğenin disabled
durumu, bu öğenin disabled
özelliği eklendiği veya kaldırıldığı ya da bu öğenin atası olan bir <fieldset>
öğesinde disabled
durumu değiştiği için değiştikten sonra çağrılır. disabled
parametresi, öğenin yeni devre dışı durumunu temsil eder. Örneğin, öğe devre dışı bırakıldığında gölge DOM'undaki öğeleri devre dışı bırakabilir.
void formResetCallback()
Form sıfırlandıktan sonra çağrılır. Öğe, kendisini bir tür varsayılan duruma sıfırlamalıdır. <input>
öğeleri için bu işlem genellikle value
özelliğinin, işaretlemede ayarlanan value
özelliğiyle eşleşmesini (veya onay kutusu söz konusu olduğunda checked
özelliğinin checked
özelliğiyle eşleşmesini) içerir.
void formStateRestoreCallback(state, mode)
Aşağıdaki durumlardan birinde çağrılır:
- Tarayıcı, öğenin durumunu geri yüklediğinde (ör. gezinme işleminden sonra veya tarayıcı yeniden başlatıldığında). Bu durumda
mode
bağımsız değişkeni"restore"
olur. - Tarayıcıdaki giriş yardımı özellikleri (ör. form otomatik doldurma) bir değer ayarladığında. Bu durumda
mode
bağımsız değişkeni"autocomplete"
olur.
İlk bağımsız değişkenin türü, setFormValue()
yönteminin nasıl çağrıldığına bağlıdır. Daha fazla bilgi için Form durumunu geri yükleme bölümüne bakın.
Form durumunu geri yükleme
Tarayıcı, bazı durumlarda (ör. bir sayfaya geri gittiğinizde veya tarayıcıyı yeniden başlattığınızda) formu kullanıcının bıraktığı duruma geri yüklemeye çalışabilir.
Formla ilişkili bir özel öğe için geri yüklenen durum, setFormValue()
yöntemine ilettiğiniz değerlerden gelir. Yöntemi, önceki örneklerde gösterildiği gibi tek bir değer parametresiyle veya iki parametreyle çağırabilirsiniz:
this.internals_.setFormValue(value, state);
value
, denetimin gönderilebilir değerini temsil eder. İsteğe bağlı state
parametresi, denetimin durumunun dahili bir temsilidir ve sunucuya gönderilmeyen veriler içerebilir. state
parametresi, value
parametresiyle aynı türleri alır. Bu parametre bir dize, File
veya FormData
nesnesi olabilir.
state
parametresi, bir kontrolün durumunu yalnızca değere göre geri yükleyemediğiniz durumlarda kullanışlıdır. Örneğin, birden çok modu olan bir renk seçici oluşturduğunuzu varsayalım: bir palet veya RGB renk çemberi. Gönderilebilir value, seçilen rengi "#7fff00"
gibi standart bir biçimde belirtir. Ancak kontrolü belirli bir duruma geri yüklemek için hangi modda olduğunu da bilmeniz gerekir. Bu nedenle durum "palette/#7fff00"
gibi görünebilir.
this.internals_.setFormValue(this.value_,
this.mode_ + '/' + this.value_);
Kodunuzun, durumunu depolanan durum değerine göre geri yüklemesi gerekir.
formStateRestoreCallback(state, mode) {
if (mode == 'restore') {
// expects a state parameter in the form 'controlMode/value'
[controlMode, value] = state.split('/');
this.mode_ = controlMode;
this.value_ = value;
}
// Chrome currently doesn't handle autofill for form-associated
// custom elements. In the autofill case, you might need to handle
// a raw value.
}
Daha basit bir kontrol söz konusu olduğunda (ör. sayı girişi), değeri kontrol panelini önceki durumuna geri yüklemek için yeterli olabilir. setFormValue()
işlevini çağırırken state
öğesini atlarsanız değer formStateRestoreCallback()
işlevine iletilir.
formStateRestoreCallback(state, mode) {
// Simple case, restore the saved value
this.value_ = state;
}
Çalışan bir örnek
Aşağıdaki örnekte, formla ilişkili özel öğelerin birçok özelliği bir araya getirilmiştir. API'nin işleyişini görmek için Chrome 77 veya sonraki bir sürümde çalıştırdığınızdan emin olun.
Özellik algılama
formdata
etkinliği ve formla ilişkili özel öğelerin kullanılabilir olup olmadığını belirlemek için özellik algılamayı kullanabilirsiniz. Şu anda her iki özellik için de yayınlanmış çoklu dolgu yok. Her iki durumda da, denetimin değerini forma iletmek için gizli bir form öğesi ekleyebilirsiniz. Formla ilişkili özel öğelerin daha gelişmiş özelliklerinin çoğunun polyfill olarak doldurulması muhtemelen zor veya imkansız olacaktır.
if ('FormDataEvent' in window) {
// formdata event is supported
}
if ('ElementInternals' in window &&
'setFormValue' in window.ElementInternals.prototype) {
// Form-associated custom elements are supported
}
Sonuç
formdata
etkinliği ve formla ilişkilendirilmiş özel öğeler, özel form kontrolleri oluşturmak için yeni araçlar sağlar.
formdata
etkinliği size yeni özellikler sunmaz ancak gizli bir <input>
öğesi oluşturmak zorunda kalmadan form verilerinizi gönderme sürecine eklemek için bir arayüz sağlar.
Formla ilişkilendirilmiş özel öğeler API'si, yerleşik form denetimleri gibi çalışan özel form denetimleri oluşturmak için yeni bir özellik grubu sağlar.
Unsplash'taki Oudom Pravat tarafından oluşturulan hero resim.