显示数据列表标签,但提交实际值


98

当前<datalist>,大多数主流浏览器(Safari除外)都支持HTML5元素,这似乎是一种向输入添加建议的有趣方式。

但是,该value属性的实现与上的内部文本之间似乎存在一些差异<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将值传递给Submit。

如何使所有浏览器的下拉列表显示<option>s的标签(内部文本),但在value提交表单时发送属性?


1
我认为Firefox和IE11在这里是错误的;根据规范OneTwovalue="",只要有value=""声明,似乎应该优先于标记中的字符串。因此,建议将“答案”作为您的价值属性。
TylerH,2015年

1
@TylerH否-Firefox和IE11在这里是正确的:label属性为元素提供标签。选项元素的标签是标签内容属性的值(如果有的话),或者如果没有则是元素的文本IDL属性的值。 w3.org/TR/html5/forms.html#attr-option-label
easwee,2015年

1
@easwee这只是说如果有标签,标签应该是标签中的内容,如果有值,则值应该是值中的内容。它没有指定哪个优先。
TylerH 2015年

Answers:


113

请注意,datalist与并不相同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检查文本是否也存在于中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;
        }
    }
});

脚本需要idanswer以及answer-hidden常规和隐藏输入,脚本才能知道哪个输入属于哪个隐藏版本。这样input,在同一页面上可以有多个,其中一个或多个datalist可以提供建议。

任何用户输入均按原样提交。要在数据列表中不存在用户输入时提交空值,请更改hiddenInput.value = inputValuehiddenInput.value = ""


可行的jsFiddle示例:普通的javascriptjQuery


2
您将如何处理具有相同内文但数据值不同的选项?例如jsfiddle.net/7k3sovht/78
bigbearzhu

1
据我所知,没有办法区分这两种选择。因为没有用户事件要听,所以不可能知道他们实际选择了哪两个。我们所知道的是在输入字段中最终得到什么值。
Stephan Muller

@StephanMuller对于像我这样学习更多HTML5的人来说是一个很好的答案,谢谢!提交后如何清除演示的文本框?
克里斯22年

纯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'));}});});
PiotrKazuś17年

@StephanMuller感谢分享,非常有用,我正在按您的编码运行,但是仅在输入中使用退格键时才获得数据值,而不是在提交甚至选择差异项时才得到数据值,这可能是错误的吗?
digitai

46

我使用的解决方案如下:

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

1
在每个步骤中使用console.log进行故障排除。确保您使用的是相同的ID值。并检查分号。
真主党(Hezbullah Shah),

1
这个解决方案真是个好主意!-我能够在很短的时间内实施此解决方案。首先,我input用attribute更新了我的元素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
但是,如果您有两个带有不同数据值的等号标题,该怎么办
Richard Aguirre

1
谢谢真主党国王,您真的节省了很多时间
居于

5

我意识到这可能有点晚了,但我偶然发现了这一点,并且想知道如何处理具有多个相同值但键不同的情况(根据bigbearzhu的评论)。

因此,我对斯蒂芬·穆勒的答案做了些微修改:

具有非唯一值的数据列表:

<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.valuevalue所述的datalist选项而不是innerText

然后,以下代码检查option带有的value,将其推送到隐藏字段中,并将替换input.valueinnerText

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


很好的补充:)
斯蒂芬·穆勒

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提交的最后一个值,而不是选定的值。
约翰
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.