데이터 목록 레이블을 표시하지만 실제 값을 제출합니다.


99

현재 HTML5 <datalist>요소는 대부분의 주요 브라우저 (Safari 제외)에서 지원되며 입력에 제안을 추가하는 흥미로운 방법으로 보입니다.

그러나 value속성 의 구현과 .NET Framework 의 내부 텍스트 간에 약간의 불일치가있는 것 같습니다 <option>. 예를 들면 :

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

이것은 다른 브라우저에서 다르게 처리됩니다.

Chrome 및 Opera :
Chrome / Opera의 데이터 목록

FireFox 및 IE 11 :
FireFox의 데이터 목록

하나를 선택한 후 입력은 내부 텍스트가 아닌 값으로 채워집니다. 사용자가 드롭 다운과 입력에서 텍스트 ( "답변") 만 볼 수 있기를 원하지만 42, 제출할 때 값 을 전달합니다 select.

모든 브라우저가 <option>s 의 레이블 (내부 텍스트)을 표시하는 드롭 다운 목록을 가지 value면서 양식이 제출 될 때 속성을 보내도록하려면 어떻게해야합니까?


1
나는 Firefox와 IE11이 여기서 잘못되었다고 생각합니다. 사양 OneTwo 에 따르면 선언 된 항목 value=""이있을 때마다 태그 내의 문자열보다 우선해야하는 것 같습니다 value="". 따라서 제안은 "답변"을 귀하의 가치 속성으로 만드는 것입니다.
TylerH 2015

1
@TylerH 아니요-Firefox 및 IE11은 여기에서 정확합니다. label 속성은 요소에 대한 레이블을 제공합니다. 옵션 요소의 레이블은 레이블 내용 속성의 값 (있는 경우) 또는없는 경우 요소의 텍스트 IDL 속성의 값입니다. w3.org/TR/html5/forms.html#attr-option-label
easwee

1
@easwee 레이블이 있으면 레이블이 레이블에 있어야하고 값이 있으면 값이 값에 있어야한다고 말합니다. 어느 것이 우선할지 지정하지 않습니다.
TylerH

답변:


115

참고 datalistA와 동일하지 않습니다 select. 사용자가 목록에없는 사용자 지정 값을 입력 할 수 있으며, 먼저 정의하지 않고는 이러한 입력에 대한 대체 값을 가져올 수 없습니다.

사용자 입력을 처리하는 가능한 방법은 입력 된 값을있는 그대로 제출하거나 빈 값을 제출하거나 제출을 방지하는 것입니다. 이 답변은 처음 두 가지 옵션 만 처리합니다.

사용자 입력을 완전히 허용하지 않으려면 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를 사용하여 텍스트 datalistdata-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;
        }
    }
});

스크립트가 어떤 입력이 어떤 숨겨진 버전에 속하는지 알기 위해서는 id answeranswer-hidden일반 및 숨겨진 입력이 필요합니다. 이렇게하면 제안을 제공하는 input하나 이상의를 사용하여 동일한 페이지에 여러를 가질 수 datalist있습니다.

모든 사용자 입력은있는 그대로 제출됩니다. 사용자 입력이 데이터 목록에 없을 때 빈 값을 제출하려면 다음 hiddenInput.value = inputValue으로 변경하십시오 .hiddenInput.value = ""


작업 jsFiddle 예제 : 일반 자바 스크립트jQuery


2
내부 텍스트는 같지만 데이터 값이 다른 옵션을 어떻게 다룰까요? 예를 들어 jsfiddle.net/7k3sovht/78
bigbearzhu

1
내가 말할 수있는 한, 두 옵션을 구별 할 방법이 없습니다. 들을 수있는 사용자 이벤트가 없기 때문에 그들이 실제로 선택한 두 가지 이벤트를 알 수 없습니다. 우리가 아는 것은 입력 필드의 값이 무엇인지입니다.
Stephan Muller

@StephanMuller 저처럼 HTML5를 더 많이 배우는 사람에게 좋은 대답입니다. 감사합니다! 제출 후 데모의 텍스트 상자를 어떻게 지우시겠습니까?
Chris22

순수 jquery document.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'));}});});
Piotr Kazuś

@StephanMuller 공유해 주셔서 감사합니다. 매우 유용합니다. 코딩 한대로 실행 중입니다. 그러나 입력에 백 스페이스를 사용할 때만 데이터 값을 얻습니다. 제출하거나 다른 항목을 선택할 때도 마찬가지입니다. 무엇이 잘못 될 수 있습니까?
digitai

48

내가 사용하는 솔루션은 다음과 같습니다.

<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

1
각 단계에서 console.log로 문제를 해결하세요. 호출하는 것과 동일한 ID 값을 사용하고 있는지 확인하십시오. 세미콜론도 확인하십시오.
Hezbullah Shah

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
하지만 데이터 값이 다른 두 개의 등가 캡션이 있다면
어떨까요

1
감사합니다 Hezbullah Shah 당신은 정말 많은 시간을 절약했습니다
ABODE

5

나는 이것이 조금 늦을 수도 있음을 알고 있지만 이것을 우연히 발견하고 여러 개의 동일한 값을 사용하지만 다른 키로 상황을 처리하는 방법을 궁금해했습니다 (bigbearzhu의 의견에 따라).

그래서 Stephan Muller의 대답을 약간 수정했습니다.

고유하지 않은 값이있는 데이터 목록 :

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

다음 코드는 optionwith that 을 확인 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내용을 볼 수 있지만 option.value양식 제출시 고유 ID를 사용할 수 있습니다. 데모 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.