Veri listesi etiketlerini göster ancak gerçek değeri gönderin


98

Şu anda HTML5 <datalist>öğesi çoğu büyük tarayıcıda (Safari dışında) desteklenmektedir ve bir girdiye öneriler eklemenin ilginç bir yolu gibi görünmektedir.

Bununla birlikte, valueözniteliğin uygulanması ile iç metin arasında bazı tutarsızlıklar var gibi görünmektedir <option>. Örneğin:

<input list="answers" name="answer">
<datalist id="answers">
  <option value="42">The answer</option>
</datalist>

Bu, farklı tarayıcılar tarafından farklı şekilde ele alınır:

Chrome ve Opera:
Chrome / Opera'da Veri Sorumlusu

FireFox ve IE 11:
FireFox'ta Veri Sorumlusu

Birini seçtikten sonra, girdi iç metinle değil değerle doldurulur. Kullanıcının yalnızca açılır menüde ve girişte metni ("Cevap") görmesini, ancak değeri 42göndermede olduğu gibi iletmesini istiyorum select.

Tüm tarayıcıların açılır listenin e-postaların etiketlerini (iç metin) göstermesini <option>, ancak valueform gönderildiğinde özniteliği göndermesini nasıl sağlayabilirim ?


1
Firefox ve IE11'in burada yanlış olduğunu düşünüyorum; Bir ve İki özelliklerine göre value="", bir value=""bildirilen olduğunda, etiketlerin içindeki bir dizeden öncelikli olması gerektiği görülüyor . Dolayısıyla öneri, değer özelliğinizin "cevabını" yapmanız olacaktır.
TylerH

1
@TylerH Hayır - Firefox ve IE11 burada doğrudur: etiket özelliği, öğe için bir etiket sağlar. Bir seçenek öğesinin etiketi, varsa etiket içeriği özniteliğinin değeridir veya yoksa öğenin metin IDL özniteliğinin değeridir. w3.org/TR/html5/forms.html#attr-option-label
easwee

1
@easwee Bu sadece etiketin eğer bir etiket varsa etiketin içinde olması gerektiğini ve bir değer varsa değerin değerin içinde olması gerektiğini söylüyor. Hangisinin öncelikli olduğunu belirtmez.
TylerH

Yanıtlar:


114

A datalistile aynı şey olmadığını unutmayın select. Kullanıcıların listede olmayan özel bir değer girmelerine olanak tanır ve bu tür bir giriş için önce onu tanımlamadan alternatif bir değer getirmek imkansız olacaktır.

Kullanıcı girdilerini işlemenin olası yolları, girilen değeri olduğu gibi göndermek, boş bir değer göndermek veya göndermeyi önlemektir. Bu cevap yalnızca ilk iki seçeneği ele alır.

Kullanıcı girişine tamamen izin vermemek istiyorsanız, belki selectdaha iyi bir seçim olabilir.


optionAçılır listedeki yalnızca metin değerini göstermek için , bunun için iç metni kullanırız ve valueniteliği dışarıda bırakırız . Göndermek istediğimiz gerçek değer, özel bir data-valueöznitelikte saklanır :

Bunu göndermek data-valueiçin bir <input type="hidden">. Bu durumda name="answer", normal girdiyi dışarıda bırakır ve onu gizli kopyaya taşırız.

<input list="suggestionList" id="answerInput">
<datalist id="suggestionList">
    <option data-value="42">The answer</option>
</datalist>
<input type="hidden" name="answer" id="answerInput-hidden">

Bu şekilde, orijinal girdideki metin değiştiğinde, metnin de içinde bulunup bulunmadığını kontrol etmek için javascript kullanabiliriz datalistve data-value. Bu değer gizli girdiye eklenir ve gönderilir.

document.querySelector('input[list]').addEventListener('input', function(e) {
    var input = e.target,
        list = input.getAttribute('list'),
        options = document.querySelectorAll('#' + list + ' option'),
        hiddenInput = document.getElementById(input.getAttribute('id') + '-hidden'),
        inputValue = input.value;

    hiddenInput.value = inputValue;

    for(var i = 0; i < options.length; i++) {
        var option = options[i];

        if(option.innerText === inputValue) {
            hiddenInput.value = option.getAttribute('data-value');
            break;
        }
    }
});

Komut dosyasının hangi girdinin hangi gizli sürüme ait olduğunu bilmesi için id answerve answer-hiddennormal ve gizli girdiye ihtiyaç vardır. Bu şekilde input, bir veya daha fazla datalistöneriyle aynı sayfada birden çok URL'ye sahip olmak mümkündür .

Herhangi bir kullanıcı girişi olduğu gibi gönderilir. Kullanıcı girişi veri listesinde bulunmadığında boş bir değer göndermek için şu şekilde değiştirin hiddenInput.value = inputValue:hiddenInput.value = ""


Çalışma jsFiddle örnekleri: düz javascript ve jQuery


2
Aynı iç metne, ancak farklı veri değerlerine sahip seçeneklerle nasıl başa çıkardınız? eg jsfiddle.net/7k3sovht/78
bigbearzhu

1
Anladığım kadarıyla, iki seçenek arasında ayrım yapmanın bir yolu yok. Dinlenecek bir kullanıcı olayı olmadığı için gerçekte hangisini seçtiklerini bilmek imkansızdır; tüm bildiğimiz, girdi alanına hangi değerin geldiğidir.
Stephan Muller

@StephanMuller, benim gibi daha fazla HTML5 öğrenen biri için harika bir cevap, teşekkürler! Gönderdikten sonra demo için metin kutusunu nasıl temizlersiniz?
Chris22

Saf jquery document.querySelector ('input [liste]'). AddEventListener ('input', function (e) {var value = $ (this) .val (); var list = $ (this) .attr ('list' ); var id = $ (bu) .attr ('id'); $ ('#' + liste + 'seçenek'). her biri (fonksiyon () {if ($ (bu) .val () == değer) { $ ('#' + id + '- gizli'). val ($ (bu) .attr ('veri-değeri'));}});});
Piotr Kazuś

@StephanMuller, paylaştığınız için teşekkürler, çok kullanışlı, kodladığınız gibi koşuyorum, ancak veri değerini yalnızca girişte geri alma kullandığımda alıyorum, farklı bir öğe gönderirken veya hatta seçerken değil, ne yanlış olabilir?
digitai

47

Kullandığım çözüm şudur:

<input list="answers" id="answer">
<datalist id="answers">
  <option data-value="42" value="The answer">
</datalist>

Ardından, şu şekilde JavaScript kullanarak sunucuya gönderilecek değere erişin:

var shownVal = document.getElementById("answer").value;
var value2send = document.querySelector("#answers option[value='"+shownVal+"']").dataset.value;


Umarım yardımcı olur.


Herhangi bir nedenle tanımsız hale geliyorum?
Dejell

1
Her adımda console.log ile sorun giderme. Aradığınız kimlik değerini kullandığınızdan emin olun. Ve noktalı virgülleri de kontrol edin.
Hezbullah Şah

1
bu çözüm harika bir fikir! - Bu çözümü dakikalar içinde basitçe uygulayabildim. önce inputelementimi öznitelik ile güncelledim data-value="1". Ardından değerin alındığı ve kullanıldığı yerlere aşağıdaki bloğu yazdım:if (typeof $(this).attr('data-value') != 'undefined') { var id = $(this).attr('name'); val = $('#'+id).find('option[value="'+val+'"]').attr('data-value'); }
WEBjuju

1
Ama ya bazı farklı veri değerlerine sahip iki eşit başlığınız varsa
Richard Aguirre

1
Teşekkürler Hezbullah Şah gerçekten çok fazla saat
kazandınız

5

Bunun biraz geç olabileceğinin farkındayım, ama buna tökezledim ve birden çok özdeş değer, ancak farklı anahtarlar (bigbearzhu'nun yorumuna göre) olan durumları nasıl ele alacağımı merak ediyordum.

Bu yüzden Stephan Muller'in cevabını biraz değiştirdim:

Benzersiz olmayan değerlere sahip bir veri uzmanı:

<input list="answers" name="answer" id="answerInput">
<datalist id="answers">
  <option value="42">The answer</option>
  <option value="43">The answer</option>
  <option value="44">Another Answer</option>
</datalist>
<input type="hidden" name="answer" id="answerInput-hidden">

Kullanıcı bir seçenek, tarayıcı cümledeki seçtiğinde input.valueile valuearasında datalistyerine seçeneği innerText.

Aşağıdaki kod daha sonra optionbununla bir olup olmadığını denetler value, bunu gizli alana iter input.valueve innerText.

document.querySelector('#answerInput').addEventListener('input', function(e) {
    var input = e.target,   
        list = input.getAttribute('list'),
        options = document.querySelectorAll('#' + list + ' option[value="'+input.value+'"]'),
        hiddenInput = document.getElementById(input.getAttribute('id') + '-hidden');

    if (options.length > 0) {
      hiddenInput.value = input.value;
      input.value = options[0].innerText;
      }

});

Sonuç olarak, kullanıcı seçeneğin innerTextsöylediği şeyi görür , ancak option.valueformun gönderilmesiyle birlikte gelen benzersiz kimliği kullanılabilir. Demo jsFiddle


Güzel bir ek :)
Stephan Muller

1

Arama için butona tıkladığınızda, onu döngü olmadan bulabilirsiniz.
Sadece seçeneğe ihtiyacınız olan değere sahip bir özellik ekleyin (beğenmek id) ve özel olarak arayın.

$('#search_wrapper button').on('click', function(){
console.log($('option[value="'+ 
$('#autocomplete_input').val() +'"]').data('value'));
})

-11

PHP'yi kullanarak bunu yapmanın oldukça basit bir yolunu buldum. Beyler, sadece böyle bir şey kullanın

<input list="customers" name="customer_id" required class="form-control" placeholder="Customer Name">
            <datalist id="customers">
                <?php 
    $querySnamex = "SELECT * FROM `customer` WHERE fname!='' AND lname!='' order by customer_id ASC";
    $resultSnamex = mysqli_query($con,$querySnamex) or die(mysql_error());

                while ($row_this = mysqli_fetch_array($resultSnamex)) {
                    echo '<option data-value="'.$row_this['customer_id'].'">'.$row_this['fname'].' '.$row_this['lname'].'</option>
                    <input type="hidden" name="customer_id_real" value="'.$row_this['customer_id'].'" id="answerInput-hidden">';
                }

                 ?>
            </datalist>

Yukarıdaki Kod, formun ayrıca seçilen seçeneğin kimliğini taşımasına izin verir.


Bu bir karmaşa gibi görünüyor ve SQL enjeksiyonu gibi kokuyor. Bunu yapma.
Fusseldieb

@ 23r0, bunun neden reddedilmiş olabileceğine dair bazı geri bildirimler; bu soru özellikle ön uç koduyla ilgilidir. Arka uç kodunu eklemek (PHP gibi) gereksiz ve kafa karıştırıcı olabilir. HTML ile ilgili olarak customer_id_real, seçilen değeri değil, yalnızca gönderilen son değeri alacağınızı umuyorum.
John
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.