如果形式数据中存在错误,请使用AJAX停止加载后续模式

发布于 2025-01-23 13:51:40 字数 3196 浏览 0 评论 0原文

我的网站上有一个由一系列模式组成的多步格式。当我单击下一步时,我触发下一个模式并提交表单数据。我试图在这些模式上设置验证,在该模态上,我要么停止序列中的下一个模态的激活,要么在缺少数据时重新加载当前模式。在我的ajax调用中,我可以显示存在错误,但是当我使用$('#modal_2_toggle')时。modal('show');尝试重新加载发生错误发生的模式,我的代码仍将用户传递到序列中的下一个模式。我正在寻找阻止下一个模式的加载,直到data.error为false。这是我的html的html:

<div class="modal fade" id="Modal_2_Toggle" aria-hidden="true" aria-labelledby="Modal_2_ToggleLabel" tabindex="-1">
                  <div class="modal-dialog modal-dialog-centered">
                    <div class="modal-content">
                      <div class="modal-header">
                        <h5 class="modal-title" id="Modal_2_ToggleLabel">Frage 2</h5>
                        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
                      </div>
                      <div class="modal-body">
                        <div class="progress">
                          <div class="progress-bar" role="progressbar" style="width: 18%;" aria-valuenow="25" aria-valuemin="0" aria-valuemax="100">18%</div>
                        </div>                        
                        <form method="POST" enctype="multipart/form-data", id="form_2">
                            {{ form_2.csrf_token }}
                            <p>
                              <br>
                                {{ form_2.consumption.label(class="form-label") }}
                                {{ form_2.consumption(class="form-control form-control-sm", id="consumptionInput") }}
                            </p>
                            {{ form_2.submit(class="btn btn-primary", id="form_2_submit", hidden="true") }}
                            <br>
                        </form>
                        <div id="errorAlert" class="alert alert-danger" role="alert" style="display:none;"></div>
                      </div>
                      <div class="modal-footer">
                        <button class="btn btn-primary modal_btn" data-bs-target="#Modal_1_Toggle" data-bs-toggle="modal" data-bs-dismiss="modal">Vorherig</button>
                        <button class="btn btn-primary modal_btn" data-bs-target="#Modal_3_Toggle" data-bs-toggle="modal" data-bs-dismiss="modal" form="form_2" id="modal_2_confirm">Weiter</button>
                      </div>
                    </div>
                  </div>
                </div>

这是我的JS:

$(document).ready(function() {

    $('#form_2').on('submit', function(event) {

        $.ajax({
            data : {
                consumption : $('#consumptionInput').val(),
            },
            type : 'POST',
            url : '/test'
        })
        .done(function(data){
            if (data.error) {
                $('#errorAlert').text(data.error).show();
                $('#Modal_2_Toggle').modal('show'); <- I ASSUMED THIS WOULD RELOAD THE MODAL
            }
        });
        
        event.preventDefault();
        
    });

});

I have a multi-step form on my website which is made up of a series of modals. When I click next, I trigger the next modal and submit form data. I am trying to set up validation on these modals, where I either stop the activation of the next modal in the sequence, or reload the current modal if there is missing data. In my ajax call I can show that an error is present, but when I use $('#Modal_2_Toggle').modal('show'); to try to reload the modal where the error took place, my code still passes the user to the next modal in the sequence. I am looking for help with blocking the loading of the next modal until data.error is false. Here is my HTML for the modal in question:

<div class="modal fade" id="Modal_2_Toggle" aria-hidden="true" aria-labelledby="Modal_2_ToggleLabel" tabindex="-1">
                  <div class="modal-dialog modal-dialog-centered">
                    <div class="modal-content">
                      <div class="modal-header">
                        <h5 class="modal-title" id="Modal_2_ToggleLabel">Frage 2</h5>
                        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
                      </div>
                      <div class="modal-body">
                        <div class="progress">
                          <div class="progress-bar" role="progressbar" style="width: 18%;" aria-valuenow="25" aria-valuemin="0" aria-valuemax="100">18%</div>
                        </div>                        
                        <form method="POST" enctype="multipart/form-data", id="form_2">
                            {{ form_2.csrf_token }}
                            <p>
                              <br>
                                {{ form_2.consumption.label(class="form-label") }}
                                {{ form_2.consumption(class="form-control form-control-sm", id="consumptionInput") }}
                            </p>
                            {{ form_2.submit(class="btn btn-primary", id="form_2_submit", hidden="true") }}
                            <br>
                        </form>
                        <div id="errorAlert" class="alert alert-danger" role="alert" style="display:none;"></div>
                      </div>
                      <div class="modal-footer">
                        <button class="btn btn-primary modal_btn" data-bs-target="#Modal_1_Toggle" data-bs-toggle="modal" data-bs-dismiss="modal">Vorherig</button>
                        <button class="btn btn-primary modal_btn" data-bs-target="#Modal_3_Toggle" data-bs-toggle="modal" data-bs-dismiss="modal" form="form_2" id="modal_2_confirm">Weiter</button>
                      </div>
                    </div>
                  </div>
                </div>

Here is my JS:

$(document).ready(function() {

    $('#form_2').on('submit', function(event) {

        $.ajax({
            data : {
                consumption : $('#consumptionInput').val(),
            },
            type : 'POST',
            url : '/test'
        })
        .done(function(data){
            if (data.error) {
                $('#errorAlert').text(data.error).show();
                $('#Modal_2_Toggle').modal('show'); <- I ASSUMED THIS WOULD RELOAD THE MODAL
            }
        });
        
        event.preventDefault();
        
    });

});

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

小巷里的女流氓 2025-01-30 13:51:40

我不确定您的多步骤形式的方法是否可符合您的需求。
也许您将使用当前的JavaScript框架之一,例如Angular,React,Vue或Svelte,更容易地实现目标。

然而,以下示例使用了带有集成幻灯片的单个模态对话框,该对话可以被激活并互相停用。它解决了您的问题,即下一步直到上一个步骤正确完成。服务器返回的错误代码确定提到的行为。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-zCbKRCUGaJDkqS1kPbPd7TveP5iyJE0EjAuZQTgFLD2ylzuqKfdKlfG/eSrtxUkn" crossorigin="anonymous">
    <title></title>
    <style>
      form[name^=form-] {
        display: none;
      }
      form[name^=form-].active {
        display: block;
      }
    </style>
  </head>
  <body>

    <!-- Button trigger modal -->
    <button type="button" class="btn btn-primary" data-toggle="modal" data-target="#exampleModal">
      Launch demo modal
    </button>

    <!-- Modal -->
    <div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
      <div class="modal-dialog">
        <div class="modal-content">
          <div class="modal-header">
            <h5 class="modal-title" id="exampleModalLabel">Modal title</h5>
            <button type="button" class="close" data-dismiss="modal" aria-label="Close">
              <span aria-hidden="true">×</span>
            </button>
          </div>

            <form
              action="/ep1"
              method="post"
              enctype="multipart/form-data"
              name="form-1"
              class="active"
            >
              {{ form1.csrf_token }}
              <div class="modal-body">
                <div class="mb-3">
                  {{ form1.some.label(class="form-label") }}
                  {{ form1.some(class="form-control form-control-sm") }}
                </div>
              </div>
              <div class="modal-footer">
                <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
                {{ form1.submit(class="btn btn-primary") }}
              </div>
            </form>

            <form
              action="/ep2"
              method="post"
              enctype="multipart/form-data"
              name="form-2"
            >
              {{ form2.csrf_token }}
              <div class="modal-body">
                <div class="mb-3">
                  {{ form2.thing.label(class="form-label") }}
                  {{ form2.thing(class="form-control form-control-sm") }}
                </div>
              </div>
              <div class="modal-footer">
                <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
                <button type="button" class="btn btn-secondary btn-prev">Previous</button>
                {{ form2.submit(class="btn btn-primary") }}
              </div>
            </form>

            <form
              action="/ep3"
              method="post"
              enctype="multipart/form-data"
              name="form-2"
            >
              {{ form3.csrf_token }}
              <div class="modal-body">
                <div class="mb-3">
                  {{ form3.more.label(class="form-label") }}
                  {{ form3.more(class="form-control form-control-sm") }}
                </div>
              </div>
              <div class="modal-footer">
                <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
                <button type="button" class="btn btn-secondary btn-prev">Previous</button>
                {{ form3.submit(class="btn btn-primary") }}
              </div>
            </form>
        </div>
      </div>
    </div>

    <script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-fQybjgWLrvvRgtW6bFlB7jaZrFsaBXjsOMm/tB9LTS58ONXgqbR9W8oWht/amnpF" crossorigin="anonymous"></script>
    <script type="text/javascript">
      $(document).ready(() => {
        let currentSlide = 0;
        const slides = $('form[name^="form-"]').toArray();
        $(slides).each(function(i) {
          $(this).submit(function(evt) {
            evt.preventDefault();
            const form = $(this);
            const formData = new FormData(form[0]);
            $.ajax({
              url: form.attr('action'),
              data: formData,
              processData: false,
              contentType: false,
              type: 'POST',
            }).done(function(data) {
              form[0].reset();
              form.removeClass('active');
              currentSlide = (i + 1)%slides.length;
              $(slides[currentSlide]).addClass('active');
              if (currentSlide === 0) {
                $('#exampleModal').modal('hide');
              }
            });
          });
        });

        $('#exampleModal').on('hidden.bs.modal', () => {
          $(slides[currentSlide]).removeClass('active');
          $(slides[currentSlide = 0]).addClass('active');
        });

        $('.btn-prev').each(function() {
          $(this).click(() => {
            $(slides[currentSlide]).removeClass('active');
            for (currentSlide -= 1; currentSlide < 0; currentSlide + slides.length);
            $(slides[currentSlide]).addClass('active');
          });

        });
      });
    </script>
  </body>
</html>
from flask import (
    Flask,
    render_template,
    request
)
from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField
from wtforms.validators import DataRequired

app = Flask(__name__)
app.secret_key = b'your-secret-here'

class Form1(FlaskForm):
    some = StringField(
        validators = [
            DataRequired()
        ]
    )
    submit = SubmitField()

class Form2(FlaskForm):
    thing = StringField(
        validators = [
            DataRequired()
        ]
    )
    submit = SubmitField()

class Form3(FlaskForm):
    more = StringField(
        validators = [
            DataRequired()
        ]
    )
    submit = SubmitField()

@app.route('/')
def index():
    form1 = Form1()
    form2 = Form2()
    form3 = Form3()
    return render_template('index.html', **locals())

@app.post('/ep1')
def ep1():
    form = Form1(request.form)
    if form.validate():
        # Handle form data here!
        print(form.some.data)
        return '', 200
    return '', 400

@app.post('/ep2')
def ep2():
    form = Form2(request.form)
    if form.validate():
        # Handle form data here!
        print(form.thing.data)
        return '', 200
    return '', 400

@app.post('/ep3')
def ep3():
    form = Form3(request.form)
    if form.validate():
        # Handle form data here!
        print(form.more.data)
        return '', 200
    return '', 400

I'm not sure if your multi-step form approach is viable with your needs.
Perhaps you would reach your goal more easily and directly with one of the current JavaScript frameworks such as Angular, React, Vue or Svelte.

Nevertheless, the following example uses a single modal dialog with integrated slides, which can be activated and deactivated one after the other. It solves your problem that the next step cannot be called until the previous one has been completed correctly. The error code returned by the server determines the behavior mentioned.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-zCbKRCUGaJDkqS1kPbPd7TveP5iyJE0EjAuZQTgFLD2ylzuqKfdKlfG/eSrtxUkn" crossorigin="anonymous">
    <title></title>
    <style>
      form[name^=form-] {
        display: none;
      }
      form[name^=form-].active {
        display: block;
      }
    </style>
  </head>
  <body>

    <!-- Button trigger modal -->
    <button type="button" class="btn btn-primary" data-toggle="modal" data-target="#exampleModal">
      Launch demo modal
    </button>

    <!-- Modal -->
    <div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
      <div class="modal-dialog">
        <div class="modal-content">
          <div class="modal-header">
            <h5 class="modal-title" id="exampleModalLabel">Modal title</h5>
            <button type="button" class="close" data-dismiss="modal" aria-label="Close">
              <span aria-hidden="true">×</span>
            </button>
          </div>

            <form
              action="/ep1"
              method="post"
              enctype="multipart/form-data"
              name="form-1"
              class="active"
            >
              {{ form1.csrf_token }}
              <div class="modal-body">
                <div class="mb-3">
                  {{ form1.some.label(class="form-label") }}
                  {{ form1.some(class="form-control form-control-sm") }}
                </div>
              </div>
              <div class="modal-footer">
                <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
                {{ form1.submit(class="btn btn-primary") }}
              </div>
            </form>

            <form
              action="/ep2"
              method="post"
              enctype="multipart/form-data"
              name="form-2"
            >
              {{ form2.csrf_token }}
              <div class="modal-body">
                <div class="mb-3">
                  {{ form2.thing.label(class="form-label") }}
                  {{ form2.thing(class="form-control form-control-sm") }}
                </div>
              </div>
              <div class="modal-footer">
                <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
                <button type="button" class="btn btn-secondary btn-prev">Previous</button>
                {{ form2.submit(class="btn btn-primary") }}
              </div>
            </form>

            <form
              action="/ep3"
              method="post"
              enctype="multipart/form-data"
              name="form-2"
            >
              {{ form3.csrf_token }}
              <div class="modal-body">
                <div class="mb-3">
                  {{ form3.more.label(class="form-label") }}
                  {{ form3.more(class="form-control form-control-sm") }}
                </div>
              </div>
              <div class="modal-footer">
                <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
                <button type="button" class="btn btn-secondary btn-prev">Previous</button>
                {{ form3.submit(class="btn btn-primary") }}
              </div>
            </form>
        </div>
      </div>
    </div>

    <script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-fQybjgWLrvvRgtW6bFlB7jaZrFsaBXjsOMm/tB9LTS58ONXgqbR9W8oWht/amnpF" crossorigin="anonymous"></script>
    <script type="text/javascript">
      $(document).ready(() => {
        let currentSlide = 0;
        const slides = $('form[name^="form-"]').toArray();
        $(slides).each(function(i) {
          $(this).submit(function(evt) {
            evt.preventDefault();
            const form = $(this);
            const formData = new FormData(form[0]);
            $.ajax({
              url: form.attr('action'),
              data: formData,
              processData: false,
              contentType: false,
              type: 'POST',
            }).done(function(data) {
              form[0].reset();
              form.removeClass('active');
              currentSlide = (i + 1)%slides.length;
              $(slides[currentSlide]).addClass('active');
              if (currentSlide === 0) {
                $('#exampleModal').modal('hide');
              }
            });
          });
        });

        $('#exampleModal').on('hidden.bs.modal', () => {
          $(slides[currentSlide]).removeClass('active');
          $(slides[currentSlide = 0]).addClass('active');
        });

        $('.btn-prev').each(function() {
          $(this).click(() => {
            $(slides[currentSlide]).removeClass('active');
            for (currentSlide -= 1; currentSlide < 0; currentSlide + slides.length);
            $(slides[currentSlide]).addClass('active');
          });

        });
      });
    </script>
  </body>
</html>
from flask import (
    Flask,
    render_template,
    request
)
from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField
from wtforms.validators import DataRequired

app = Flask(__name__)
app.secret_key = b'your-secret-here'

class Form1(FlaskForm):
    some = StringField(
        validators = [
            DataRequired()
        ]
    )
    submit = SubmitField()

class Form2(FlaskForm):
    thing = StringField(
        validators = [
            DataRequired()
        ]
    )
    submit = SubmitField()

class Form3(FlaskForm):
    more = StringField(
        validators = [
            DataRequired()
        ]
    )
    submit = SubmitField()

@app.route('/')
def index():
    form1 = Form1()
    form2 = Form2()
    form3 = Form3()
    return render_template('index.html', **locals())

@app.post('/ep1')
def ep1():
    form = Form1(request.form)
    if form.validate():
        # Handle form data here!
        print(form.some.data)
        return '', 200
    return '', 400

@app.post('/ep2')
def ep2():
    form = Form2(request.form)
    if form.validate():
        # Handle form data here!
        print(form.thing.data)
        return '', 200
    return '', 400

@app.post('/ep3')
def ep3():
    form = Form3(request.form)
    if form.validate():
        # Handle form data here!
        print(form.more.data)
        return '', 200
    return '', 400
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文