Yayınlanma tarihi: 8 Ağustos 2019
Birçok geliştirici, tarayıcıda yerleşik olmayan kontroller sağlamak veya görünümü ve tarzı yerleşik form kontrolleriyle mümkün olanın ötesinde özelleştirmek için özel form kontrolleri oluşturur.
Ancak yerleşik HTML form kontrollerinin özelliklerini kopyalamak zor olabilir. Bir <input> öğesini bir forma eklediğinizde otomatik olarak edindiği özelliklerden bazılarını göz önünde bulundurun:
- Giriş, formun kontrol listesine otomatik olarak eklenir.
- Girişin değeri, formla birlikte otomatik olarak gönderilir.
- Giriş form doğrulamasında yer alır. Girişi
:validve:invalidsözde sınıflarını kullanarak biçimlendirebilirsiniz. - Form sıfırlandığında, form yeniden yüklendiğinde veya tarayıcı form girdilerini otomatik doldurmaya çalıştığında girdiye bildirim gönderilir.
Özel form denetimleri genellikle bu özelliklerin birkaçına sahiptir. Geliştiriciler, form gönderimine katılmak için forma gizli bir <input> eklemek gibi JavaScript'teki bazı sınırlamaları aşabilirler. Ancak diğer özellikler yalnızca JavaScript'te kopyalanamaz.
İki web özelliği, özel form kontrolleri oluşturmayı kolaylaştırır ve özel kontrollerin sınırlamalarını ortadan kaldırır:
formdataolayı, rastgele bir JavaScript nesnesinin form gönderimine 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 denetimleri gibi davranmasını 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önderme işlemine katılmasına olanak tanıyan düşük düzeyli bir API'dir.
- Etkileşimde bulunmak istediğiniz forma bir
formdataolay dinleyicisi ekleyin. - Bir kullanıcı gönder'i tıkladığında, form gönderilen tüm verileri tutan bir
FormDatanesnesi içeren birformdataolayını tetikler. - Her
formdatadinleyicisi, form gönderilmeden önce verilere ekleme veya verileri değiştirme şansına sahip olur.
formdata olay dinleyicisinde tek bir değer göndermenin bir örneği şöyledir:
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);
});
Formla ilişkili özel öğeler
Olay tabanlı API'yi her türlü bileşenle kullanabilirsiniz, ancak bu API yalnızca gönderim süreciyle etkileşime girmenize olanak tanır.
Standartlaştırılmış form kontrolleri, form yaşam döngüsünün birçok bölümünde yer alır. Formla ilişkili özel öğeler, özel bileşenler ile yerleşik denetimler arasındaki boşluğu kapatmayı amaçlar. Formla ilişkili özel öğeler, standartlaştırılmış form öğelerinin birçok özelliğiyle eşleşir:
- Formla ilişkili özel bir öğeyi
<form>içine yerleştirdiğinizde, tarayıcı tarafından sağlanan bir 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şi olup olmadığını belirten bir işaret ayarlayabilir. Form kontrollerinden birinde geçersiz giriş varsa form gönderilemez.
- Öğ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 aramalar sağlayabilir.
- Öğe,
:disabledve:invalidgibi form denetimleri için standart CSS sözde sınıflarını destekler.
Bu belge her şeyi kapsamıyor ancak özel öğenizi bir formla entegre etmek için gereken temel bilgileri açıklıyor.
Formla ilişkili özel bir öğe tanımlayın
Özel bir öğeyi formla ilişkili özel bir öğeye dönüştürmek için birkaç ek 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 ele almasını söyler. - Form denetimleri için
setFormValue()vesetValidity()gibi ek yöntemlere ve özelliklere erişmek için öğedeattachInternals()yöntemini çağırın. name,valuevevaliditygibi form denetimleri tarafından desteklenen ortak özellikleri ve yöntemleri ekleyin.
Bu öğelerin temel özel öğe tanımına nasıl uyduğunu aşağıda görebilirsiniz:
// Form-associated custom elements must be autonomous custom elements.
// 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);
Kaydolduktan 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>
Bir değer ayarlayın
attachInternals() yöntemi, form kontrol API'lerine erişim sağlayan bir ElementInternals nesnesi döndürür. Bunların en temel olanı, kontrolün geçerli değerini ayarlayan setFormValue() yöntemidir.
setFormValue() yöntemi üç tür değerden birini alabilir:
- Bir dize değeri.
- Bir
Filenesnesi. - Bir
FormDatanesnesi. Birden fazla değeri geçirmek içinFormDatanesnesini kullanabilirsiniz. Örneğin, bir kredi kartı giriş kontrolü bir kart numarası, son kullanma tarihi ve doğrulama kodunu geçebilir.
Bir değer ayarlamak için:
this.internals_.setFormValue(this.value_);
Birden fazla değer ayarlamak için şunu 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, dahili nesnede setValidity() yöntemini çağırarak form doğrulama işlemine de 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_);
}
:valid ve :invalid sözde sınıflarını kullanarak, yerleşik bir form denetimi gibi, formla ilişkili özel bir öğeyi biçimlendirebilirsiniz.
Yaşam döngüsü geri aramaları
Formla ilişkili özel öğe API'si, form yaşam döngüsüne bağlanmak için bir dizi ek yaşam döngüsü geri araması içerir. Geri aramalar isteğe bağlıdır: yalnızca öğenizin yaşam döngüsünün o noktasında bir şey yapması gerekiyorsa geri aramayı uygulayın.
void formAssociatedCallback(form)
Tarayıcı öğeyi bir form öğesiyle ilişkilendirdiğinde veya öğeyi form öğesinden ayırdığında çağrılır.
void formDisabledCallback(disabled)
Öğenin disabled durumu değiştiğinde çağrılır; bu, öğenin disabled özniteliğinin eklenmesi veya kaldırılması veya bu öğenin atası olan <fieldset> öğesinde disabled durumunun değişmesi nedeniyle gerçekleşir.
Örneğin, devre dışı bırakıldığında öğe gölge DOM'undaki öğeleri devre dışı bırakabilir.
void formResetCallback()
Form sıfırlandıktan sonra çağrılır. Öğenin kendisini bir tür varsayılan duruma sıfırlaması gerekir. <input> öğeleri için bu işlem genellikle value özelliğinin, işaretlemede ayarlanan value özelliğiyle eşleşecek şekilde ayarlanmasını içerir. Onay kutusuyla bu, checked özelliğini checked özelliğiyle eşleşecek şekilde ayarlamakla ilgilidir.
void formStateRestoreCallback(state, mode)
Aşağıdaki iki durumdan birinde çağrılır:
- Tarayıcı, gezinme işleminden sonra veya yeniden başlatıldığında öğenin durumunu geri yüklediğinde.
modebağımsız değişkeni"restore". - Tarayıcının formları otomatik doldurma gibi giriş yardımcısı özellikleri bir değer ayarladığında.
modebağımsız değişkeni"autocomplete".
İlk bağımsız değişkenin türü, setFormValue() yönteminin nasıl çağrıldığına bağlıdır.
Form durumunu geri yükleme
Sayfaya geri dönme veya tarayıcıyı yeniden başlatma gibi bazı durumlarda tarayıcı, 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. Bu yöntemi, önceki örneklerde gösterildiği gibi tek bir değer parametresiyle veya iki parametreyle çağırabilirsiniz:
this.internals_.setFormValue(value, state);
value, kontrolün gönderilebilir değerini temsil eder. İsteğe bağlı state parametresi, sunucuya gönderilmeyen verileri içerebilen denetimin durumunun dahili bir gösterimidir. state parametresi, value parametresiyle aynı türleri alır: bir dize, File veya FormData nesnesi.
state parametresi, bir denetimin durumunu yalnızca değerine dayanarak geri yükleyemediğinizde yararlıdır. Örneğin, birden fazla moda sahip bir renk seçici oluşturduğunuzu varsayalım: bir palet veya bir RGB renk tekerleği. Gönderilen değeri, "#7fff00" gibi kanonik bir biçimde seçilen renktir. 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, depolanan durum değerine göre durumunu 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 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 (örneğin, sayı girişi) söz konusu olduğunda, kontrolü önceki durumuna geri yüklemek için değer muhtemelen yeterlidir. setFormValue() işlevini çağırırken state parametresini atlarsanız değer formStateRestoreCallback() parametresine iletilir.
formStateRestoreCallback(state, mode) {
// Simple case, restore the saved value
this.value_ = state;
}
Özellik algılama
formdata etkinliğinin ve formla ilişkili özel öğelerin kullanılabilir olup olmadığını belirlemek için özellik algılamayı kullanabilirsiniz. Her iki özellik için de polyfill yayınlanmamıştır. Her iki durumda da, kontrolün değerini forma yaymak için gizli bir form öğesi eklemeye geri dönebilirsiniz.
Formla ilişkili özel öğelerin daha gelişmiş özelliklerinin çoğu, polyfill ile doldurmak için muhtemelen zor veya imkansızdır.
if ('FormDataEvent' in window) {
// formdata event is supported
}
if ('ElementInternals' in window &&
'setFormValue' in window.ElementInternals.prototype) {
// Form-associated custom elements are supported
}
formdata etkinliği, gizli bir <input> öğesi oluşturmanıza gerek kalmadan form verilerinizi gönderme işlemine ekleyebileceğiniz bir arayüz sağlar. Formla ilişkili özel öğeler API'siyle, yerleşik form kontrolleri gibi çalışan özel form kontrolleri için yeni bir dizi özellik sağlayabilirsiniz.