Alpine.js’de İlgili Seçimler Oluşturma

Raymond Camden

Web tasarımında yaygın bir UX/UI metaforu, “ilgili” seçimler veya açılır menüler fikridir. Bununla kastettiğim, tek bir seçenek alanına sahip olma fikridir ve oradan bir şey seçtiğinizde, içeriğin içeriğini yönlendirir. bir diğer (veya ilgili) alanı seçin. Buna bir örnek, araba markalarının bir açılır listesi olabilir. Belirli bir marka seçildiğinde, araba modellerinin bir açılır listesini alırsınız. Bunun bir örneğini oluşturmanın eğlenceli olacağını düşündüm. Alpine.js.

Başlamak için, seçimlerim için sahte veriler oluşturacak iki yardımcı işlev oluşturdum. İlki, bir durum listesi döndürür (hepsi değil ve sorun değil):

const getStates = () => {
    return [
        {id:1, label:"Alabama"},
        {id:2, label:"California"},
        {id:3, label:"Louisiana"},
        {id:4, label:"Texas"},
        {id:5, label:"Washington"}
        ]
}

Dikkat edin, her eyalette bir id ve label değer. Her eyaletin bir dizi ilgili şehri vardır. Bunun için istendiğinde onları oluşturmak için bir yöntem geliştirdim. Her eyalet için farklı veri kümelerinin döndürüldüğünü göstermek için hem şehirlerin adları hem de şehirlerin sayısı dinamiktir:

const getCities = (id) => {
    if(!id) return [];
    let state = (getStates()).find(i => i.id === parseInt(id,10));
    let result = [];
    for(let i=0; i<(id*2); i++) {
        result.push({id:i, label:`${state.label} City ${i+1}`});
    }
    return result;
}

Pekala, bunun için kullanacağım HTML’ye bakalım:

<div x-data="app" x-cloak>
    <label>State:
    <select x-model="state">
        <option value="">-- Select a State --</option>
        <template x-for="state in states">
            <option :value="state.id"><span x-text="state.label"></span></option>
        </template>
    </select>
    </label>
    
    <label x-show="state">City:
        <select x-model="city">
            <template x-for="city in cities">
                <option :value="city.id"><span x-text="city.label"></span></option>
            </template>
        </select>
    </label>
</div>

Bunun iki ana bölümü var – biri eyaletler için, diğeri şehirler için. Eyaletler için seçimi a’ya bağladım. state değişken ve seçenekler geliyor states.

Şehirler için oldukça benzer, ancak kullanımına dikkat edin. x-show. Buradaki fikir, yalnızca bir eyalet seçildiğinde şehir açılır menüsünü göstermektir.

Şimdi JavaScript’i kontrol edelim:

document.addEventListener('alpine:init', () => {
  Alpine.data('app', () => ({
        states:getStates(),
        state:null,
        city:null,
        cities() {
            return getCities(this.state);
        }
  }))
});

Bu çok basit bir demo olduğu için kod uzun değil. Görebilirsin states daha önce tanımladığım işlevi kullanarak. aynen citiesancak nasıl kullanıldığına dikkat edin this.state. Bu, değeri her zaman yeniden çalışır state değişir. Başka bir şey yapmak zorunda değilim. Bununla kendin burada oynayabilirsin:

Kalemi Gör İlgili GG tarafından Raymond Camden (@cfjedimaster) üzerinde kod kalemi.

Bir halt için, başka bir sürüm oluşturmaya karar verdim, bu, bir eyalet için şehir alma çağrısının eşzamansız olduğu bir sürüm. Bunun örneğin bir API çağırmanın sonucu olduğunu düşünebilirsiniz. Bunu taklit etmenin tuhaf bir yolu olarak, sadece kullandım setTimeout. İşte yeni sürüm:

const getCities = async (id) => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            if(!id) resolve([]);
            let state = (getStates()).find(i => i.id === parseInt(id,10));
            let result = [];
            for(let i=0; i<(id*2); i++) {
                result.push({id:i, label:`${state.label} City ${i+1}`});
            }
            resolve(result);
        }, 1000);
    });
}

Kontrol ettiğimde küçük bir fark daha var. id değer boştur, yükte olacaktır ve öyleyse boş bir dizi döndürür.

Şimdi – ilk başta – bunu kullanmak kolay bir değişiklikti. Bunu kelimenin tam anlamıyla sadece cities Alp uygulamamdaki tanım:

async cities() {
    return  await getCities(this.state);
}

Ve acayip işe yaradı. Ancak, bir durum seçildiğinde kullanıcıya bir şeyler olduğuna dair herhangi bir geri bildirim olmadı. Bir yükleme mesajı eklemeye ve bu süreçte seçilen şehirlerin gizlendiğinden emin olmaya karar verdim. Bu biraz daha karmaşık hale geldi.

İlk önce, HTML’imin ikinci yarısını değiştirdim:

<span x-show="loadingCities"><i>Loading cities...</i></span>
<label x-show="state && !loadingCities">
    <span x-show="!loadingCities">City:</span>
    <select x-model="city" x-show="!loadingCities">
        <template x-for="city in cities">
            <option :value="city.id"><span x-text="city.label"></span></option>
        </template>
    </select>
</label>

İlk olarak, yeni bir değer olduğunda ortaya çıkan bir yayılma alanım var, loadingCities, doğru. Bunu bir saniye içinde göreceksiniz. sonra modifiye ettim label her ikisini de kontrol etmek için state ve loadingCities yanlış olmak. Çok uzak çok iyi. Ama burada işler tuhaflaştı. Bana göre bu yeterli olmalıydı. Ama tek başına “Şehir” olduğunda, bir aralığa sarılmamış, ilk kez bir eyalet seçildiğinde onu görecektim. loadingCities doğruydu. İkinci ve benzerlerinde, seçim beklendiği gibi çalıştı. Ayrıca seçimin boş görünmesiyle ilgili bir sorunum vardı.

Neden olduğundan emin değilim, ama kullanılan aralığı ekledim x-show hem içeride hem de beklediğimden daha fazla iş yapmak zorundaymışım gibi gelse de, iyi çalışıyor gibiydi.

İşte güncellenmiş JavaScript:

document.addEventListener('alpine:init', () => {
  Alpine.data('app', () => ({
        states:getStates(),
        state:null,
        loadingCities:false,
        async cities() {
            if(this.state) this.loadingCities = true;
            let result = await getCities(this.state);
            this.loadingCities = false;
            return result;
        }
  }))
});

Görebilirsin cities biraz daha karmaşıktır. Sonucu almam ve ardından yükleme değerimi tekrar false olarak ayarlamam ve sonra döndürmem gerekiyor. Sonuç olarak işe yaradı ama dediğim gibi, her şeyin zamanlamasını doğru yapmak zordu. İşte oynayabileceğiniz bu uygulama:

Kalemi Gör İlgili DD (Async) tarafından Raymond Camden (@cfjedimaster) üzerinde kod kalemi.

fotoğrafı çeken Adrian Schwarz üzerinde Sıçramayı kaldır

Bir cevap yazın

E-posta hesabınız yayımlanmayacak.