You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

jQuery表单提交触发模态框执行不同操作遇无限循环求优雅方案

问题描述

我有一个待提交的表单,提交时需要阻止默认行为,通过AJAX请求检查是否存在已有记录,逻辑如下:

  • 若不存在记录,则正常提交表单;
  • 若存在记录,则弹出模态框询问用户是否关闭该已有记录:
    • 用户确认时,为id字段设置对应值;
    • 用户拒绝时,继续正常提交表单。

当前实现陷入了无限循环,虽然可以用全局布尔变量判断是否直接提交,但肯定有更优雅的方式,特此求助。


现有代码

JavaScript(含Laravel模板代码)

<script type="text/javascript">
    $(document).ready(function() {
        $(document).on('click', '#button-close-previous-status', function() {
            $('#form-create-status').submit();
        });
        $(document).on('click', '#button-ignore-previous-status', function() {
            $('#open_status_id').val('');
            $('#form-create-status').submit();
        });

        $('#modal-title-close-previous-status').on('hidden.bs.modal', function () {
            $('#close-status-end-date').empty();
            $('#close-status-status').empty();
            $('#close-status-start-date').empty();
            $('#open_status_id').val('');
        });

        $('#form-create-status').submit(function(e) {
            // this code prevents form from actually being submitted
            e.preventDefault();
            e.returnValue = false;

            if (!$('#status_start').val()) {
                swtAlert('error', '{{__('Missing Information')}}', '{{__('Please enter the status start date')}}');
            }
            else {
                var $form = $(this);

                $.ajax({
                    url: "{{route('baadmin.students.bursaries.statuses.get_open_student_bursary_statuses',['student'=>$student->id,'bursary'=>$student_bursary->id])}}",
                    type: "post",
                    dataType: 'json',
                    context: $form,
                    data: {
                        status_start: $('#status_start').val()
                    },
                    headers: {
                        'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
                    },
                    success: function (data) {
                        if (data.id>0) {
                            var parts =$('#status_start').val().split('-');
                            var end_date = new Date(parts[0], parts[1] - 1, parts[2]);
                            end_date.setDate(end_date.getDate() - 1);
                            end_date = end_date.toLocaleDateString('en-CA', {year: 'numeric', month: '2-digit', day: '2-digit'});

                            $('#close-status-end-date').text(end_date);
                            $('#close-status-status').text(data.text);
                            $('#close-status-start-date').text(data.status_start);
                            $('#open_status_id').val(data.id);

                            $('#modal-close-previous-status').modal('show');
                        }
                        else {
                            swtAlert('error','Communications Error',"Couldn't fetch existing statuses. Cant request auto-close.");
                            // make sure that you are no longer handling the submit event; clear handler
                            this.off('submit');
                            // actually submit the form
                            this.submit();
                        }
                    },
                });
            }
        });

    });
</script>

模态框HTML(含Laravel模板代码)

<div class="modal fade" id="modal-close-previous-status" tabindex="-1" role="dialog" aria-labelledby="modal-title-close-previous-status" aria-hidden="true" style="display: none;">
    <div class="modal-dialog modal-dialog-centered" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title" id="modal-title-close-previous-status">{{__('Close Previous Status')}}</h5>
                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                    <span aria-hidden="true">×</span>
                </button>
            </div>
            <div class="modal-body">
                <p>We found a previously open status. Would you like to close that status with a status end date of <span id="close-status-end-date"></span>.</p>
                <p>
                    <strong>Found  Status:</strong><br>
                    Status: <span id="close-status-status"></span><br/>
                    Status Start: <span id="close-status-start-date"></span>
                </p>
            </div>
            <div class="modal-footer">
                {{ Form::button(__('Dont Change Anything'), ['type' => 'button', 'class' => 'btn btn-secondary', 'data-dismiss'=>'modal','id'=>'button-ignore-previous-status']) }}
                {{ Form::button(__('Close Previous Status'), ['type' => 'button', 'class' => 'btn btn-success','id'=>'button-close-previous-status']) }}
            </div>
        </div>
    </div>
</div>

解决方案

问题根源在于:模态框按钮触发的submit()会再次执行绑定的事件处理函数,导致重复AJAX检查,陷入循环。以下是两种优雅的解决方式:

方式一:调用原生表单提交方法

直接调用表单的原生submit()方法,而非jQuery封装的submit(),这样不会触发绑定的jQuery事件处理函数,直接提交表单:

修改模态框按钮的点击事件:

$(document).on('click', '#button-close-previous-status', function() {
    // 调用原生submit,跳过jQuery事件监听
    document.getElementById('form-create-status').submit();
});
$(document).on('click', '#button-ignore-previous-status', function() {
    $('#open_status_id').val('');
    // 调用原生submit,跳过jQuery事件监听
    document.getElementById('form-create-status').submit();
});

同时,把原有AJAX成功后无记录的提交逻辑也改为原生submit:

success: function (data) {
    if (data.id>0) {
        // 原有模态框渲染逻辑保持不变
    }
    else {
        swtAlert('error','Communications Error',"Couldn't fetch existing statuses. Cant request auto-close.");
        // 调用原生submit提交表单
        this[0].submit();
    }
}

方式二:用自定义标记区分提交类型

给表单加一个自定义属性,标记是否需要跳过AJAX检查:

修改JavaScript部分:

$(document).ready(function() {
    $(document).on('click', '#button-close-previous-status', function() {
        $('#form-create-status').attr('data-skip-check', 'true');
        $('#form-create-status').submit();
    });
    $(document).on('click', '#button-ignore-previous-status', function() {
        $('#open_status_id').val('');
        $('#form-create-status').attr('data-skip-check', 'true');
        $('#form-create-status').submit();
    });

    // 模态框隐藏时移除标记,恢复正常检查逻辑
    $('#modal-title-close-previous-status').on('hidden.bs.modal', function () {
        $('#close-status-end-date').empty();
        $('#close-status-status').empty();
        $('#close-status-start-date').empty();
        $('#open_status_id').val('');
        $('#form-create-status').removeAttr('data-skip-check');
    });

    $('#form-create-status').submit(function(e) {
        // 检查标记,若存在则跳过检查直接提交
        if ($(this).attr('data-skip-check') === 'true') {
            $(this).removeAttr('data-skip-check');
            return;
        }

        // 原有阻止默认行为、AJAX检查逻辑保持不变
        e.preventDefault();
        e.returnValue = false;

        if (!$('#status_start').val()) {
            swtAlert('error', '{{__('Missing Information')}}', '{{__('Please enter the status start date')}}');
        }
        else {
            var $form = $(this);

            $.ajax({
                url: "{{route('baadmin.students.bursaries.statuses.get_open_student_bursary_statuses',['student'=>$student->id,'bursary'=>$student_bursary->id])}}",
                type: "post",
                dataType: 'json',
                context: $form,
                data: {
                    status_start: $('#status_start').val()
                },
                headers: {
                    'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
                },
                success: function (data) {
                    if (data.id>0) {
                        var parts =$('#status_start').val().split('-');
                        var end_date = new Date(parts[0], parts[1] - 1, parts[2]);
                        end_date.setDate(end_date.getDate() - 1);
                        end_date = end_date.toLocaleDateString('en-CA', {year: 'numeric', month: '2-digit', day: '2-digit'});

                        $('#close-status-end-date').text(end_date);
                        $('#close-status-status').text(data.text);
                        $('#close-status-start-date').text(data.status_start);
                        $('#open_status_id').val(data.id);

                        $('#modal-close-previous-status').modal('show');
                    }
                    else {
                        swtAlert('error','Communications Error',"Couldn't fetch existing statuses. Cant request auto-close.");
                        this[0].submit();
                    }
                },
            });
        }
    });
});

内容的提问来源于stack exchange,提问作者SupaMonkey

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 04:55:33