ChatGPT解决这个技术问题 Extra ChatGPT

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

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

但是,value 属性的实现与 <option> 上的内部文本之间似乎存在一些差异。例如:

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

这由不同的浏览器以不同的方式处理:

https://i.stack.imgur.com/3kdQd.png

https://i.stack.imgur.com/qtir4.png

选择一个后,输入将填充值而不是内部文本。我只希望用户在下拉列表和输入中看到文本(“答案”),但在提交时传递值 42,就像 select 一样。

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

我认为 Firefox 和 IE11 在这里是错误的;根据规范 OneTwo,似乎 value="" 应该优先于标签中的字符串,只要声明了 value=""。所以建议是让“答案”成为你的价值属性。
@TylerH 否 - Firefox 和 IE11 在这里是正确的: label 属性为元素提供标签。 选项元素的标签是标签内容属性的值,如果有,或者如果没有,则为元素的文本 IDL 属性的值。 w3.org/TR/html5/forms.html#attr-option-label
@easwee这只是说如果有标签,标签应该是标签中的内容,如果有值,则值应该是值中的内容。它没有指定哪个优先。

A
Adam M.

请注意,datalistselect 不同。它允许用户输入不在列表中的自定义值,并且如果不先定义它就不可能为此类输入获取替代值。

处理用户输入的可能方法是按原样提交输入的值、提交空白值或阻止提交。这个答案只处理前两个选项。

如果您想完全禁止用户输入,也许 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;
        }
    }
});

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

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

工作 jsFiddle 示例:plain javascriptjQuery


您将如何处理具有相同内部文本但数据值不同的选项?例如jsfiddle.net/7k3sovht/78
据我所知,没有办法区分这两个选项。因为没有可听的用户事件,所以不可能知道他们实际选择了两个中的哪一个;我们所知道的是输入字段中最终的值。
@StephanMuller 对于像我这样正在学习更多 HTML5 的人来说,这是一个很好的答案,谢谢!提交后如何清除演示的文本框?
纯 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')); } }); });
@StephanMuller 感谢分享,非常有用,我正在按照您的编码运行,但是我只是在输入中使用退格键时才获得数据值,而不是在提交甚至选择不同的项目时,有什么问题?
i
informatik01

我使用的解决方案如下:

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

希望能帮助到你。


我得到不确定的任何原因?
在每个步骤中使用 console.log 进行故障排除。确保您使用的 id 值与您调用的相同。并检查分号。
这个解决方案真是个好主意! - 我能够很简单地在几分钟内实施这个解决方案。首先,我使用属性 data-value="1" 更新了我的 input 元素。然后我在值被抓取和使用的地方写了以下块:if (typeof $(this).attr('data-value') != 'undefined') { var id = $(this).attr('name'); val = $('#'+id).find('option[value="'+val+'"]').attr('data-value'); }
但是,如果您有两个具有不同数据值的相等标题怎么办
谢谢真主党沙阿,你真的节省了这么多时间
c
cobbystreet

我意识到这可能有点晚了,但我偶然发现了这一点,想知道如何处理具有多个相同值但不同键的情况(根据 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.value 替换为 datalist 选项的 value 而不是 innerText

然后,以下代码检查具有该 valueoption,将其推入隐藏字段并用 innerText 替换 input.value

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 在表单提交时可用。 Demo jsFiddle


不错的补充:)
M
Mangaldeep Pannu

单击搜索按钮时,您可以在没有循环的情况下找到它。
只需在选项中添加一个具有您需要的值的属性(例如 id)并搜索它。

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

S
Saghachi

获取 text() 而不是 val() 尝试:

$("#datalistid option[value='" + $('#inputid').val() + "']").text();

为什么它会被否决呢?
2
23r0

使用 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 注入。不要那样做。
@23r0,关于为什么这可能被否决的一些反馈;这个问题是关于前端代码的。包括后端代码(如 PHP)可能是不必要且令人困惑的。关于 HTML,我希望您只会获得 customer_id_real 提交的最后一个值,而不是选定的值。
@Fussellieb 因为它不需要任何用户输入,所以它是非常安全的。恕我直言,这是一个非常严厉的声明。
@RuneKaagaard 我也没有在他/她的答案中看到任何 sqlinjection 可能性。但其他人应该注意:仅仅因为输入是隐藏的、只读的或停用的,它仍然会被发送到服务器。即使普通用户无法输入内容,也可以使用浏览器 devtools => sqlinjections。后端应该始终不信任前端。