Я экспериментирую с 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.info(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>



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


UX здесь немного неуклюж. Вместо потока, который вы сейчас пытаетесь:
Я бы предложил более простое и менее удивительное:
Это лучше для пользователя, потому что невозможно сделать «плохой» выбор, и его фильтр никогда не сработает от неожиданной копии из другого поля. Требуется меньше кликов/ввода/выбора — они могут сузить все, используя ввод фильтра, и просто нажать 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.info(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, чтобы не слишком отклоняться от исходного кода.
Спасибо, это очень помогло! Я новичок, когда дело доходит до фляги и работы с jquery. У меня была простая форма, в которой у меня не было проблем с получением данных POST и сохранением их в CSV, похоже, у меня возникли проблемы с отправкой данных этой формы. Можете ли вы помочь мне начать? Кажется, я не могу захватить данные и что-то с ними сделать на стороне python.
Без проблем. Если этот ответ решил первоначальную проблему, подумайте о том, чтобы принять его . Если у вас есть новый вопрос, даже если он связан, создайте новый пост со всем соответствующим контекстом, и я могу взглянуть.
спасибо, я так и сделал: stackoverflow.com/questions/76176746/…
Вопрос должен быть помечен для JS/jquery и т. д., а не для python/flask