Desde la primera captura de pantalla a continuación, tengo una aplicación Flask que tiene un campo de búsqueda que usa la solicitud Ajax para consultar una lista de estados de EE. UU. para devolver como valores desplegables. Cuando dejo el campo Name
vacío y presiono Enviar, esto está eliminando inadvertidamente el valor desplegable que había seleccionado anteriormente. También quiero conservar el campo desplegable durante la validación del formulario.
app.py
import sys from flask import Flask, render_template, request from forms import InputForm app = Flask(__name__) app.config['SECRET_KEY'] = "Development" US_STATES = ["Alaska", "Alabama", "Arkansas", "American Samoa", "Arizona", "California", "Colorado", "Connecticut", "District ", "of Columbia", "Delaware", "Florida", "Georgia", "Guam", "Hawaii", "Iowa", "Idaho", "Illinois", "Indiana", "Kansas", "Kentucky", "Louisiana", "Massachusetts", "Maryland", "Maine", "Michigan", "Minnesota", "Missouri", "Mississippi", "Montana", "North Carolina", "North Dakota", "Nebraska", "New Hampshire", "New Jersey", "New Mexico", "Nevada", "New York", "Ohio", "Oklahoma", "Oregon", "Pennsylvania", "Puerto Rico", "Rhode Island", "South Carolina", "South Dakota", "Tennessee", "Texas", "Utah", "Virginia", "Virgin Islands", "Vermont", "Washington", "Wisconsin", "West Virginia", "Wyoming"] @app.route("/", methods=["GET","POST"]) def index(): form = InputForm() if request.method == "POST": print(form.name.data, file=sys.stderr) print(form.states.data, file=sys.stderr) print(form.territory.data, file=sys.stderr) print("Hello from outside Validate.", file=sys.stderr) if form.validate_on_submit(): print(form.name.data, file=sys.stderr) print(form.states.data, file=sys.stderr) print(form.territory.data, file=sys.stderr) print("Hello from inside Validate.", file=sys.stderr) else: print(form.errors) return render_template("states.html", form=form) @app.route("/search") def search(): text = request.args["searchText"] result = [c for c in US_STATES if text.lower() in c.lower()] return {"results": result} if __name__ == '__main__': app.run(host="localhost", port=5001, debug=True)
formularios.py
from flask_wtf import FlaskForm from wtforms import StringField, SelectField, SubmitField from wtforms import validators from wtforms.validators import Optional, InputRequired, DataRequired class InputForm(FlaskForm): name = StringField("Name", validators=[DataRequired()]) states = SelectField("US States", validate_choice=False) territory = SelectField("Is Territory?", choices=["Unknown", "Yes", "No"], default="Unknown", validators=[InputRequired()]) submit = SubmitField("Add State", validators=[Optional()])
plantillas\index.html
<!DOCTYPE html> <html> <head> <title>Live Search Ajax Demo</title> <meta charset="utf-8" /> <!-- CSS Stylesheets --> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-eOJMYsd53ii+scO/bJGFsiCZc+5NDVN2yr8+0RDqr0Ql0h+rP48ckxlpbzKgwra6" crossorigin="anonymous"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-select/1.12.1/css/bootstrap-select.css"/> <script src="https://code.jquery.com/jquery-3.2.1.min.js"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-select/1.12.1/js/bootstrap-select.js"></script> <script type="text/javascript"> function liveSearch(value) { value = value.trim(); if (value != "") { $.ajax({ url: "search", data: { searchText: value }, dataType: "json", success: function (data) { var res = ""; for (i in data.results) { res += "<option value=" + data.results[i] + ">" + data.results[i] + "</option>"; } $("#states").html(res); }, }); } else { $("#states").html(""); } } </script> </head> <body> <!-- Main --> <main role="main" class="container"> <div> {% block content %} {% endblock %} </div> </main> </body> </html>
plantillas\estados.html
{% extends "index.html" %} {% block content %} <div class="content-section"> <div class="col-6"> <div class="row mt-4 mb-4"> <h2>Live Search in Flask with Ajax</h2> <hr> <div class="row mt-4 mb-4"> <form method="POST" action="" novalidate="novalidate"> {{ form.hidden_tag() }} <fieldset class="form-group"> <div class="row"> <div class="col"> {{ form.name.label(class="form-control-label") }} {% if form.name.errors %} {{ form.name(class="form-control form-control-md is-invalid") }} <div class="invalid-feedback"> {% for error in form.name.errors %} <span>{{ error }}</span> {% endfor %} </div> {% else %} {{ form.name(class="form-control form-control-md") }} {% endif %} </div> <div class="col"> {{ form.territory.label(class="form-control-label") }} {% if form.territory.errors %} {{ form.territory(class="form-control form-control-md is-invalid") }} <div class="invalid-feedback"> {% for error in form.territory.errors %} <span>{{ error }}</span> {% endfor %} </div> {% else %} {{ form.territory(class="form-control form-select") }} {% endif %} </div> </div> <div class="row"> <div class="input-group mt-4 mb-4"> <input type="text" class="form-control" placeholder="Search USA States" onkeyup="liveSearch(this.value)"> {{ form.states(class="form-control form-select") }} </input> </div> </div> <div class="input-group mb-3 justify-content-md-end"> <div class="form-group"> {{ form.submit(class="btn btn-primary btn-sm") }} </div> </div> </fieldset> </form> </div> </div> </div> {% endblock content %}
La documentación oficial de JQuery es muy amigable para principiantes si necesita algo, le sugiero que comience desde allí.
De lo contrario, explique claramente qué está tratando de hacer.
Aquí hay una forma más limpia de hacer lo que ya has hecho.
Asegúrese de que el contenido de su formulario tenga reglas bastante estrictas (creo que puede personalizar esto en su "creador de formularios" en el backend) como por ejemplo:
<input name="Name" type="text" maxlength="10" required />
$(document).ready(function () { $('#inputSearchStates').keyup(function () { // when a keyboard key is hitted (even CTRL is included and all keyboard keys...) var value = $(this).val().trim(); // remove first and last blank spaces from your string (note that blank spaces in the middle will still remain) if (this.form.reportValidity()) { // return true if the form is valid (required inputs already filled ...etc) $.ajax({ url: "search", data: { searchText: value }, dataType: "json", success: function (data) { // data is the returned result from your backend // it can be a string/filled array/empty array/number/float ...etc $("#states").empty(); // always make your dropdown empty (with definitely no options to select) data.results.each(function () { // automatically fetch the response result (a JS array) if exists , else it will do nothing. $("#states").append(` <option value="${this}"> ${this} </option> `); // for each available data in your response result and append <options> respectively }); // remember that your dropdown will still empty if no data there is no data in your response array. }, }); } }); });