首页 > 解决方案 > 使用 AJAX 的 jQuery AutoComplete - 我错过了什么?

问题描述

我正在尝试将 jQuery AutoComplete 用于客户端/客户选择输入字段 - 在一个简单的测试 HTML 页面上(一旦 AJAX 部分工作,我计划对其进行增强)。

我已从https://jqueryui.com/autocomplete/#remote-jsonp复制(逐字)JQuery 示例 JavaScript, 我对此所做的唯一更改是“#...”ID 名称和 URL 值“源”定义。

后端服务器(运行 Django)很好地接收来自 JavaScript 的请求,并且似乎正确地生成了 JSON 回调字符串。这是它的输出:

curl http://localhost:52974/AjaxClientAutocomplete/?term=Adm

[ {label: "ADMAC", value: "109"}, {label: "Administration Software L", value: "110"}, {label: "Adminsoft - Office Rental", value: "111"}, {label : "Adminsoft - Reimburse Int", value: "112"}, {label: "Adminsoft - Royalties", value: "113"}, {label: "adminsoftware.biz", value: "114"}, {label: "Admiral Word Publishing B", value: "115"} ]

使用浏览器上的开发人员工具,我已将 DOM 看到的 HTML 复制到硬盘上的测试 HTML 文件中。我已将其缩减为最基本的要素,并制作了几种变体来测试哪些有效,哪些无效。

使用局部变量作为自动完成“源:”工作正常 - 包括按照上面显示的完整字符串(复制并粘贴到 JavaScript 中)作为对象数组。

总而言之:

我对这个技术领域相当陌生,想不出其他可以尝试的方法。谁能看到我错过了什么?这是JavaScript:

// AjaxClientAutocomplete.js        Created by GE on 16 May 2020
// Expects Django to handle the AJAX request being made using an HTTP GET to an URL of "/AjaxClientAutocomplete/"
//      The search string will be passed in a parameter named "term"
// The Django HTML template must give the input field an ID of "idClientName":  e.g. <input type="text" name="ClientName" id="idClientName">
// It also should have a an HTML element with id="log" which will accept the output from the "log()" function - which will be disabled once working.

$(function () {
    function log(message) {
        $("<div>").text(message).prependTo("#log");
        $("#log").scrollTop(0);
    }

    $("#idClientName").autocomplete({
        source: function (request, response) {
            $.ajax({
                url: "/AjaxClientAutocomplete/",
                dataType: "jsonp",
                data: {
                    term: request.term
                },
                success: function (data) {
                    response(data);
                }
            });
        },
        minLength: 2,
        select: function (event, ui) {
            log("Selected: " + ui.item.value + " aka " + ui.item.id);
        }
    });
});

这是 HTML 模板的相关部分:

<form action="" method="get">
    {% csrf_token %}
    <div class="ui-widget">
        <label for="ClientName">Client Name Search: </label>
        <input type="text" name="ClientName" id="idClientName">
    </div>
    <input type="submit" value="Go">
</form>

<div class="ui-widget" style="margin-top:2em; font-family:Arial">
    Result:
    <div id="log" style="height: 200px; width: 300px; overflow: auto;" class="ui-widget-content"></div>
</div>

标签: javascriptjqueryajaxautocompletedjango-templates

解决方案


我终于破解了这个问题——在一位在前端开发方面有丰富经验的朋友(Paul Hutcheon)的帮助下。

根据https://jqueryui.com/autocomplete/#remote-上的示例源代码,我们尝试了很多方法,但完全无法使用“.ajax()”和“jsonp”方法使其工作。jsonp

但是,它使用 jQuery ".getJSON()" 速记方法(无论如何要简单一些)完美地工作。

这是新的“.getJSON()”JavaScript,希望对其他人有用:

// AjaxClientAutocomplete.js        Created by GE on 16 May 2020
// 20 May 20:  Modified (with help from Paul Hutcheon) to use JQuery's ".getJSON()" function, which is a wrapper for ".ajax()"
// Expects Django to handle the AJAX request being made using an HTTP GET to an URL of "/AjaxClientAutocomplete/"
//      The search string will be passed in a parameter named "term", which has the search string
// The Django HTML template must give the input field an ID of "idClientName":  e.g. <input type="text" name="ClientName" id="idClientName">
// It also should have a an HTML element with id="log", which will accept the output from the "log()" function - This will be disabled once working.

$(function () {
    $("#idClientName").autocomplete({
        source: function (request, response) {
            $.getJSON("/AjaxClientAutocomplete/", {
                NameStartsWith: request.term
            }, response);
        },
        minLength: 2,
        select: function (event, ui) {
            event.preventDefault();
            $(this).val(ui.item.label);
            log(ui.item ?
                "Selected: " + ui.item.label :
                "Nothing selected, input was " + this.value);
        },
        focus: function (event, ui) {
            event.preventDefault();
            $(this).val(ui.item.label);
        }
    });
});

您可能会注意到我们已将原来的“term:”替换为“NameStartsWith:”。希望这有助于人们更好地理解“.getJSON()”的简写。但它也在发送到服务器的请求中给出了一个更有意义的键名。这让我们可以在搜索表单中添加其他搜索选项(例如“姓名包含”、“地址包含”和“电话包含”),并在单个 JavaScript 和服务器请求中处理它们。

如果服务器响应只是一个值列表,则不需要“select:”和“focus:”事件中的额外代码。然而,在我们的例子中它是必需的,因为来自服务器的响应是一个标签/值对的列表,给出了匹配的客户端的名称和主键值(整数)。额外的代码确保始终为当前/选定的输入项显示名称(而不是主键 - 当最终提交表单时,主键仍作为该字段的值正确返回)。

我们还在服务器端进行了更改,以便它返回真正的 JSON 响应(对象名称周围也有引号),而不是“jsonp”格式(在我最初的问题中,它在我遵循的另一个示例中有效,其中“来源:”是一个变量)。对于搜索字符串“adm”,服务器的 JSON 响应现在是: [ {"label": "ADMAC", "value": "109"}, {"label": "Administration Software L", "value" : "110"}, {"label": "Adminsoft - Office Rental", "value": "111"}, {"label": "Adminsoft - Reimburse Int", "value": "112"}, {"标签”:“Adminsoft - 版税”,“价值”:“113”},{“标签”:

无论如何,我希望这对某人有帮助。


推荐阅读