データリストラベルを表示しますが、実際の値を送信します


98

現在、HTML5<datalist>要素はほとんどの主要なブラウザー(Safariを除く)でサポートされており、入力に提案を追加するための興味深い方法のようです。

ただし、value属性の実装との内部テキストの間にはいくつかの矛盾があるようです<option>。例えば:

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

これは、ブラウザによって処理が異なります。

ChromeとOpera:
Chrome / Operaのデータリスト

FireFoxとIE11:
FireFoxのデータリスト

いずれかを選択すると、入力には内部テキストではなく値が入力されます。ドロップダウンと入力にテキスト(「回答」)のみを表示したいのですが、42送信時に値を渡します。selectます。

ドロップダウンリストに<option>sのラベル(内部テキスト)を表示させvalue、フォームの送信時に属性を送信させるにはどうすればよいですか?


1
ここではFirefoxとIE11が間違っていると思います。仕様12によるとvalue=""value=""宣言されている場合は常に、タグ内の文字列よりも優先されるべきであるようです。したがって、提案は「答え」をあなたの価値属性にすることです。
TylerH 2015

1
@TylerHいいえ-FirefoxとIE11はここで正しいです:label属性は要素のラベルを提供します。オプション要素のラベルは、ラベルコンテンツ属性がある場合はその値、存在しない場合は要素のテキストIDL属性の値です。 w3.org/TR/html5/forms.html#attr-option-label
easwee

1
@easweeこれは、ラベルがある場合はラベルがラベルに含まれている必要があり、値がある場合は値が値に含まれている必要があることを示しています。どちらが優先されるかは指定されていません。
TylerH 2015年

回答:


113

datalistと同じではないことに注意してくださいselect。これにより、ユーザーはリストにないカスタム値を入力でき、最初に定義せずにそのような入力の代替値をフェッチすることは不可能です。

ユーザー入力を処理するための可能な方法は、入力された値をそのまま送信するか、空白の値を送信するか、送信しないようにすることです。この回答は、最初の2つのオプションのみを処理します。

ユーザー入力を完全に禁止したい場合は、おそらくselectより良い選択でしょう。


optionドロップダウンにのテキスト値のみを表示するには、その内部テキストを使用し、value属性を省略します。送信する実際の値は、カスタムdata-value属性に格納されます。

これを送信するdata-valueには、を使用する必要があり<input type="hidden">ます。この場合name="answer"、通常の入力を省略して、非表示のコピーに移動します。

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

このように、元の入力のテキストが変更されたときに、javascriptを使用して、テキストがに存在するかどうかを確認し、そのdatalistをフェッチできdata-valueます。その値は非表示の入力に挿入されて送信されます。

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;
        }
    }
});

スクリプトがどの入力がどの非表示バージョンに属しているかを知るには、IDansweranswer-hidden通常の非表示入力が必要です。このようにinputして、同じページに複数のを配置し、1つまたは複数datalistのを提案することができます。

ユーザー入力はすべてそのまま送信されます。ユーザー入力がデータリストに存在しないときに空の値を送信するには、次のように変更hiddenInput.value = inputValueします。hiddenInput.value = ""


実用的なjsFiddleの例:プレーンなjavascriptjQuery


2
内部テキストは同じでデータ値が異なるオプションをどのように処理しますか?例:jsfiddle.net/7k3sovht/78
bigbearzhu

1
私の知る限り、2つのオプションを区別する方法はありません。聞くユーザーイベントがないため、2つのうちどちらを実際に選択したかを知ることは不可能です。私たちが知っているのは、入力フィールドにどのような値が入力されたかだけです。
Stephan Muller

@StephanMuller私のようなHTML5をもっと学んでいる人にとっては素晴らしい答えです、ありがとう!送信後、デモのテキストボックスをどのようにクリアしますか?
Chris22 2017年

純粋なjquerydocument.querySelector( 'input [list]')。addEventListener( 'input'、function(e){var value = $(this).val(); var list = $(this).attr( 'list' ); var id = $(this).attr( 'id'); $( '#' + list + 'option')。each(function(){if($(this).val()== value){ $( '#' + id + '-hidden')。val($(this).attr( 'data-value'));}});});
ピョートルKazuś

@StephanMuller共有してくれてありがとう、とても便利です、私はあなたがコーディングしたように実行していますが、入力でバックスペースを使用するときだけでデータ値を取得します。
Digitai 2018

47

私が使用する解決策は次のとおりです。

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

次に、次のようにJavaScriptを使用して、サーバーに送信する値にアクセスします。

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


それが役に立てば幸い。


なんらかの理由で未定義になっていますか?
dejell 2016年

1
各ステップでconsole.logを使用してトラブルシューティングを行います。呼び出しているのと同じID値を使用していることを確認してください。そしてセミコロンもチェックしてください。
ヒズボラシャー2016

1
このソリューションはとても素晴らしいアイデアです!-私は、このソリューションを数分で実装することができました。まず、input要素を属性で更新しましたdata-value="1"。それから私は、値をつかんで、使用されていた場所で、次のブロックを書いた:if (typeof $(this).attr('data-value') != 'undefined') { var id = $(this).attr('name'); val = $('#'+id).find('option[value="'+val+'"]').attr('data-value'); }
WEBjuju

1
しかし、いくつかの異なるデータ値を持つ2つの等しいキャプションがある場合はどうなりますか
Richard Aguirre

1
おかげHezbullahシャーあなたは本当にそんなに時間保存
ABODE

5

これは少し遅いかもしれませんが、私はこれに遭遇し、複数の同一の値であるが異なるキーを持つ状況をどのように処理するのか疑問に思いました(bigbearzhuのコメントによる)。

そこで、StephanMullerの答えを少し変更しました。

一意でない値を持つデータリスト:

<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">

ユーザーは、ブラウザの置き換えオプションを選択した場合input.valuevaluedatalist代わりにオプションをinnerText

次のコードは、チェックしoptionているとvalue、隠しフィールドに置き換えることをプッシュinput.valueして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;
      }

});

結果として、ユーザーにはオプションの内容が表示されますが、フォームの送信時にinnerTextからの一意のIDoption.valueが利用可能になります。 デモjsFiddle


素敵な追加:)
Stephan Muller

1

検索ボタンをクリックすると、ループなしで見つけることができます。
必要な値(などid)を持つ属性をオプションに追加して、特定の属性を検索するだけです。

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

-11

PHPを使用して、これを行う非常に簡単な方法を見つけました。みんな、このようなものを使ってください

<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>

上記のコードにより、フォームには、選択されたオプションのIDを含めることができます。


それは混乱のようで、SQLインジェクションのようなにおいがします。そうしないでください。
Fusseldieb

@ 23r0、なぜこれが投票されなかったのかについてのフィードバック。この質問は、特にフロントエンドコードに関するものです。バックエンドコード(PHPなど)を含める必要はなく、混乱を招く可能性があります。HTMLに関してはcustomer_id_real、選択した値ではなく、送信された最後の値のみを取得することを期待しています。
ジョン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.