javascript - 使用 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(如下所示)似乎正在向服务器发送请求。
- 服务器正在接收这些并响应 - 似乎带有正确的 JSONP 响应。
- JavaScript 似乎并没有处理它并更新它的源标签/值列表,所以它可以使用它(就像它成功的那样,当“源:”是具有相同对象列表的变量时)。
- 还是 JSONP 响应有问题?(注意:我尝试在“label”和“value”键周围添加引号,但没有成功。将这个确切的文本作为变量的值粘贴到 JavaScipt 中时效果很好,该变量被用作 AutoComplete “source:” AJAX 函数。)
我对这个技术领域相当陌生,想不出其他可以尝试的方法。谁能看到我错过了什么?这是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>
解决方案
我终于破解了这个问题——在一位在前端开发方面有丰富经验的朋友(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”},{“标签”:
无论如何,我希望这对某人有帮助。
推荐阅读
- flutter - 如何使用 MediaQuery 响应我的颤振应用程序?
- microk8s - MicroK8s Metallb 调用服务时出现随机错误
- autohotkey - 如何使用 AutoHotKey 最小化和恢复活动窗口?
- bash - bash 脚本在 grep -w -c 之后不会继续
- hyperledger-fabric - Fabric sdk go 应用程序无法连接到 SaveChannel 上的 orderer
- html - 将超链接更改为 CSS 按钮
- android - 真的有办法在不使用电缆的情况下将 ADB 命令发送到非 root 的 android 设备吗?
- tensorflow - 为什么将彩色图像通过我的去噪模型后以 RGB 格式输出黑白?
- javascript - 获取在 iFrame 中加载我的网站的父网站的完整路径
- python - 我怎样才能把对某个反应做出反应的每个人都列在一个列表中?