我正在尝试使用 Flask 并尝试创建一个页面,我可以在其中开始在文本框中输入内容并缩小下拉菜单中显示的内容。我已经记下了,但是我在实际选择下拉列表中的第一项并填充文本框时遇到了麻烦,到目前为止我只能使用其他选项来填充它。下面的示例 python 和模板代码。非常感谢任何帮助。
app.py
from flask import Flask, render_template, request, jsonify
app = Flask(__name__)
# Sample list of cities
cities = [
'New York',
'Los Angeles',
'Chicago',
'Houston',
'Phoenix',
'Philadelphia',
'San Antonio',
'San Diego',
'Dallas',
'San Jose'
]
@app.route('/')
def index():
return render_template('index.html')
@app.route('/suggest_cities', methods=['POST'])
def suggest_cities():
search_term = request.form['searchTerm']
suggestions = [city for city in cities if search_term.lower() in city.lower()]
return jsonify({'suggestions': suggestions})
if __name__ == '__main__':
app.run(debug=True)
index.html 模板
<!DOCTYPE html>
<html>
<head>
<title>Suggest Cities</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
$(document).ready(function() {
$('#cityInput').on('input', function() {
var searchTerm = $(this).val();
if (searchTerm.length >= 2) {
$.ajax({
url: '/suggest_cities',
type: 'POST',
data: {searchTerm: searchTerm},
success: function(response) {
var suggestions = response.suggestions;
var options = suggestions.map(function(city) {
return '<option value="' + city + '">' + city + '</option>';
}).join('');
$('#citySelect').html(options);
$('#citySelect').show();
},
error: function(xhr) {
console.log(xhr.responseText);
}
});
} else {
$('#citySelect').empty();
$('#citySelect').hide();
}
});
$('#citySelect').change(function() {
var selectedCity = $(this).val();
$('#cityInput').val(selectedCity);
$('#citySelect').hide();
});
$('#cityForm').submit(function(e) {
e.preventDefault();
var cityInput = $('#cityInput').val();
var cityOptions = $('#citySelect option').map(function() { return $(this).val(); }).get();
if (cityOptions.includes(cityInput)) {
alert('You selected ' + cityInput + '!');
} else {
alert('Please select a city from the drop-down menu.');
}
});
});
</script>
</head>
<body>
<form id="cityForm">
<label for="cityInput">Enter a city:</label>
<input type="text" id="cityInput" name="cityInput">
<select id="citySelect" style="display: none;"></select>
<input type="submit" value="Submit">
</form>
</body>
</html>
这里的用户体验有点尴尬。而不是您当前正在尝试的流程:
我建议更简单且不那么令人惊讶:
这对用户来说更好,因为不可能做出“错误”的选择,并且他们的过滤器永远不会从另一个字段的意外副本中消失。涉及更少的点击/输入/选择——他们可以使用过滤器输入缩小所有内容,只需按 Enter 键接受下拉列表顶部的任何内容。从我们的角度来看,代码更简单。
例如:
<!DOCTYPE html>
<html>
<head>
<title>Suggest Cities</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
function getSuggestions() {
var searchTerm = $('#cityInput').val();
$.ajax({
url: '/suggest_cities',
type: 'POST',
data: {searchTerm: searchTerm},
success: function(response) {
var suggestions = response.suggestions;
var options = suggestions.map(function(city, i) {
return '<option value="' + city + '">' + city + '</option>';
}).join('');
$('#citySelect').html(options);
},
error: function(xhr) {
console.log(xhr.responseText);
}
});
}
$(document).ready(function() {
getSuggestions();
$('#cityInput').on('input', getSuggestions);
$('#cityForm').submit(function(e) {
e.preventDefault();
var selected = $('#citySelect').val();
if (selected) {
alert('You selected ' + selected + '!');
}
else {
alert('No cities match your query.');
}
});
});
</script>
</head>
<body>
<form id="cityForm">
<label for="cityInput">Enter a city:</label>
<input type="text" id="cityInput" name="cityInput" autocomplete="off">
<select id="citySelect"></select>
<input type="submit" value="Submit">
</form>
</body>
</html>
其他一些注意事项:
如果你有很多城市并且不想在用户只输入 1 或 2 个字符时访问服务器,那很好,但我会添加一些消息,例如“请再输入 2 个字符进行搜索”,所以当用户按下一个键并且没有任何反应时,用户不会感到困惑。
更好的方法可能是将响应限制在前 10 个左右,去抖动输入和/或限制请求的数量。我避免了这些,因为它们可能是过早的优化。
如果列表和你的例子一样小,或者即使它只有几百个项目,你也可以在模板中预先提供它,然后在前端进行所有过滤。对用户来说更快,对您的服务器来说工作更少。但我不确定你的实际用例是什么,所以我或多或少地玩过你的设计。
下拉菜单出现和消失有点奇怪。我宁愿一直看到它。如果你需要隐藏/显示它很容易实现,所以我把它留了下来。
CSS 名称通常是
kebab-case
,但我保留了它们 camelCase
以免过多地偏离您的原始代码。