javascript - 制作 Spring 形式:select searchable by two parameters

标签 javascript java spring-mvc drop-down-menu

我有一个下拉菜单(产品类型):

enter image description here

由 Spring MVC 代码生成(Google MDL 已删除)

<form:select path="productType" required="required">
    <form:option value="" label="" />
    <form:options items="${availableProductTypesForAdd}" />
</form:select>
<label for="productType">Product Type</label>

${availableProductTypesForAdd} 由 Controller 加载到模型中,如下所示:

HashMap<String, String> availableProductTypesForAdd = new HashMap<>();

availableProductTypesForAdd.put("191", "191 - Table");
availableProductTypesForAdd.put("201", "201 - Chair");
availableProductTypesForAdd.put("230", "230 - Desk");
availableProductTypesForAdd.put("232", "232 - Monitor");

model.put("availableProductTypesForAdd", availableProductTypesForAdd);

如果您将 ${availableProductTypesForAdd} 打印到屏幕上,它将如下所示:

{191=191 - table ,201=201 - 椅子,230=230 - table ,232=232 - 显示器}

填写表单的用户知道以下两件事之一:(1) 产品 key (191、201 等)或 (2) 产品名称( table 、椅子等)。

  • 有些用户不熟悉按键,因此需要按产品名称进行搜索。
  • 一些用户熟悉这些按键,并且更喜欢更快捷的按键方式。

我想让这两个选项都可以通过键盘选择下拉菜单。即,当用户点击此字段时,他们可以在键盘上键入“201”或“椅子”,它将选择列表中的正确项目。

目前,该列表只能通过类型代码(191、201 等)进行搜索,因为显示的字符串以代码开头。

如何实现这一目标?

最佳答案

最简单也可能是最可取的方法是使用标准选择的某种替代品,因为它不太可定制。

您可以尝试'Chosen' jQuery plugin 。这将需要外部 js 和 css。然而,似乎完全满足您的要求,没有痛苦和解决方法。

只需在 jsp 中添加 4 行:

<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>

<form:form id="form" method="post" modelAttribute="form" action="/submit2">
    <form:select path="productType" required="required" >
        <form:option value="" label="" />
        <form:options items="${availableProductTypesForAdd}" />
    </form:select>
    <label for="productType">Product Type</label>
    <input type="submit" name="action" value="Submit" />
</form:form>

<script src="https://harvesthq.github.io/chosen/docsupport/jquery-3.2.1.min.js"></script>
<script src="https://harvesthq.github.io/chosen/chosen.jquery.js"></script>
<link rel="stylesheet" href="https://harvesthq.github.io/chosen/chosen.css">
<script>$(function(){ $('select').chosen(); })</script>

你在这里: (它在 OSX 上的或多或少新鲜的 chrome、safari 和 FF 中就像一个魅力)

'Choosen' in action

$(function(){
    $('select').chosen();
});
<link href="https://harvesthq.github.io/chosen/chosen.css" rel="stylesheet"/>
<script src="https://harvesthq.github.io/chosen/docsupport/jquery-3.2.1.min.js"></script>
<script src="https://harvesthq.github.io/chosen/chosen.jquery.js"></script>

<form id="form" action="/submit2" method="post">
    <select id="productType" name="productType" required="required">
        <option value=""></option>
        <option value="232">232 - Monitor</option><option value="310">310 - Bad</option><option value="201">201 - Chair</option><option value="555">555 - Sofa</option><option value="191">191 - Table</option><option value="999">999 - Bookcase</option><option value="618">618 - Armchair</option><option value="230">230 - Desk</option>
    </select>
    <label for="productType">Product Type</label>
    <input type="submit" name="action" value="Submit">
</form>


您也可以看看HTML Data List element

<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<%@ taglib uri = "http://java.sun.com/jsp/jstl/core" prefix = "c" %>

<form:form id="form" method="post" modelAttribute="form" action="/submit">
    <form:input path="productType" list="productTypes" required="required" autocomplete="off" />
        <datalist id="productTypes">
            <c:forEach items="${availableProductTypesForAdd}" var="productType">
                <option value="${productType.key}">${productType.value}</option>
            </c:forEach>
        </datalist>
    <label for="productType">Product Type</label>
    <button type="submit">Ok</button>
</form:form>

search anywhere

您甚至可以从选项中删除键,因为它显示并在值和文本中进行搜索

HashMap<String, String> availableProductTypesForAdd = new HashMap<>();
availableProductTypesForAdd.put("191", "Table");
availableProductTypesForAdd.put("201", "Chair");
availableProductTypesForAdd.put("230", "Desk");
availableProductTypesForAdd.put("232", "Monitor");

search anywhere search anywhere

但是,它不像select那么严格,并且允许输入不受选项限制的任何内容(本质上是建议,这就是为什么自动完成关闭)

但是,如果您对一些微小的 js 感到满意,您可以添加一些额外的逻辑来弥补这一差距,这是选项之一(如果输入与选项之一不匹配,则清除输入):

<script>
(function() {
    function verify() {
        var input = document.getElementById("productType");
        var o = [].map.call(input.list.options, opt => opt.value);
        var opts = o.reduce((result, v) => (result[v.toUpperCase()] = v, result), {});
        var value = input.value.toUpperCase();
        if (!opts[value]) {
            input.value = '';
            return false;
        }
    }
    document.getElementById("productType").addEventListener("focusout", verify);
    document.getElementById("form").addEventListener("focusout", verify);
})();
</script>

基本上,您可以稍微改进默认值。但前提是你同意这个搜索在菜单打开时不能完全工作(因为该菜单无法从 js 访问,因为它是特定于操作系统的,而且似乎不是 html 的一部分)。

<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>

<form:form id="form" method="post" modelAttribute="form" action="/submit2">
    <form:select path="productType" required="required" >
        <form:option value="" label="" />
        <form:options items="${availableProductTypesForAdd}" />
    </form:select>
    <label for="productType">Product Type</label>
    <input type="submit" name="action" value="Submit" />
</form:form>

<script>
(function() {
    var lastKeysForSearchNumber = 7; // tune # of keys entered to keep
    var lastKeys = [];
    var select = document.querySelector('[name=productType]');
    function search(e) {
        if (e.key.match(/^\w$/i)) {
            lastKeys.push(e.key);
            if (lastKeys.length > lastKeysForSearchNumber) {
                lastKeys.shift();
            }
            select.value = bestMatch(select.options, lastKeys.join(''));
            e.preventDefault();
        }
    }
    function bestMatch(options, input) {
        for (var i = 0; i < input.length; i++) {
            for (var j = 0; j < options.length; j++) {
                if (options[j].text.match(new RegExp(input.substring(i), 'i'))) { // contains ignore case
                    return options[j].value;
                }
            }
        }
        return '';
    }
    select.addEventListener("keydown", search);
})();
</script>

这里的想法是存储最后 7 个(或其他)键并检查每个选项是否包含尽可能多的内容。

enter image description here

这可能需要针对特定​​浏览器(IE?)进行一些调整和/或一些调整 以下是该内容的片段,请尝试一下:

(function() {
    var lastKeysSorSearchNumber = 7;
    var lastKeys = [];
    var select = document.querySelector('[name=productType]');
    function search(e) {
        if (e.key.match(/^\w$/i)) {
            lastKeys.push(e.key);
            if (lastKeys.length > lastKeysSorSearchNumber) {
                lastKeys.shift();
            }
            select.value = bestMatch(select.options, lastKeys.join(''));
            e.preventDefault();
        }
    }
    function bestMatch(options, input) {
        for (var i = 0; i < input.length; i++) {
            for (var j = 0; j < options.length; j++) {
                if (options[j].text.match(new RegExp(input.substring(i), 'i'))) {
                    return options[j].value;
                }
            }
        }
        return '';
    }
    select.addEventListener("keydown", search);
})();
<form id="form" action="/submit2" method="post">
    <select id="productType" name="productType" required="required">
        <option value=""></option>
        <option value="310">310 - Bad</option><option value="201">201 - Chair</option><option value="2324">2324 - Monitor</option><option value="555">555 - Sofa</option><option value="191">191 - Table</option><option value="999">999 - Bookcase</option><option value="618">618 - Armchair</option><option value="230">230 - Desk</option>
    </select>
    <label for="productType">Product Type</label>
    <input type="submit" name="action" value="Submit">
</form>

关于javascript - 制作 Spring 形式:select searchable by two parameters,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58607869/

相关文章:

java - 使用 Apache POI 将工作簿的日期系统设置为 1904

java - 使用 Spring MVC 和自行实现的拦截器强制下载文件会产生一个奇怪的问题

javascript - 使用 array.map 返回响应三元运算符

java - 用面板填充内容 Pane

java - 归并排序去除重复项

java - Spring @Validated 和 @InitBinder

java - 用于登录的WebSecurityConfigurerAdapter的配置

javascript - 如何使用 ES6 编写 ReactJS 高阶组件?

javascript - 正负挑战

javascript - Chrome 扩展,在选项卡之间发送数据