在点击事件触发之前,我必须单击取消按钮两次

时间:2014-08-15 14:04:04

标签: jquery

我有一个模态弹出窗体,用户可以单击取消退出表单。如果用户已开始在表单中输入数据,系统会询问用户是否要确认是否要退出而不保存更改。

发生的事情是我输入一些数据,当我点击取消按钮时,设置了_isModalDirty标志,但按钮点击事件(即$(' .modal-cancel')。点击( function(){...});)未被触发。当我再次单击取消按钮时,它会被触发。 我需要更改什么,以便第一次触发按钮单击事件?

$('.controls :input').change(function (){
    _isModalDirty = true;
});

$('.modal-cancel').click(function (){
    if (_isModalDirty) {
        if (confirm('Are you sure you want to cancel? You will lose your unsaved changes.')) {
            closeModalPopup();
        }
    } else {
        closeModalPopup();
    }
});

var closeModalPopup = function () {
    resetModalPopup();
    _isModalDirty = false;
    $('.modal').modal('hide');
}

var resetModalPopup = function() {
    $('.controls :input').each(function () {
        var $this = $(this);
        $this.val('');
    });    
}

EDIT 这是html;

<div class="modal fade" id="edit-quote-form">
    @using (Html.BeginForm("Edit", "Quote", FormMethod.Post, new { id = "editQuoteForm", @class = "modalPopup" }))
    {
        <input type="hidden" id="EditQuoteQuoteId" name="QuoteId" />
        <fieldset>
            <legend>Edit Quote for Tender</legend>
            <p style="color: white;font-weight: bold;"><span id="EditCompany"></span></p>
            <div class="modal-body">
                <div class="row">
                    <div class="controls col-md-2">
                        <label class="control-label label-default" for="Status">Status</label>
                    </div>
                    <div class="controls col-md-2">
                        <select id="QuoteStatus">
                        </select>
                    </div>
                </div>
                <div class="row">
                    <div class="controls col-md-2">
                        <label class="control-label label-default" for="Value">Value</label>
                    </div>
                    <div class="controls col-md-2">
                        <input type="text" id="EditQuoteValue" name="maskValue" class="maskValue"
                            style="text-align: right; width: 160px;"
                            data-inputmask="'alias': 'numeric', 'groupSeparator': ',', 'autoGroup': true, 'digits': 2, 'digitsOptional': false, 'prefix': '£ ', 'placeholder': '0'" />
                        <input type="hidden" name="editValue" class="editValue" />
                    </div>
                </div>
                <div class="row">
                    <div class="controls col-md-2">
                        <label class="control-label label-default" for="Comments">Comments</label>
                    </div>
                    <div class="controls col-md-2" style="white-space: nowrap;">
                        <textarea id="EditComments" name="Comments" class="commentsTextarea"></textarea>
                    </div>
                </div>
                <div class="modal-footer" style="padding-bottom: 10px;">
                    <input type="button" class="btn btn-warning modal-cancel" value="Cancel" />
                    <input type="submit" class="btn btn-success" value="Save" />
                </div>
            </div>
        </fieldset>
    }
</div>

EDIT2

上面的表单是从主窗体中的以下超链接触发的;

<fieldset>
        <legend>Tender Quotes</legend>
        <div style="padding-bottom: 10px;" class="bootstrapLink">
            <a href="#edit-quote-form" class="btn btn-info btn-xs" data-toggle="modal">Add New Quote</a>
        </div>
        @grid.GetHtml()
    </fieldset>

EDIT3 这是它不起作用的小提琴; http://jsfiddle.net/arame3333/mto9mt9v/7/

3 个答案:

答案 0 :(得分:0)

听起来旗帜没有按预期运作。

 $('.controls :input').change(function (){
    _isModalDirty = true;
});

我会在提交时对原始与当前进行比较,而不是更改事件。 因此,首先在模态创建,存储原始值:

var origdata=[];
 $('.controls :input').each(function () {
    origdata.push($(this).val());
}); 

取消后,将它们与当前数据字段进行比较。

var _isModalDirty=0;
$('.controls :input').each(function (i, item) {
    if(origdata[i]!=item.val())
       _isModalDirty++;
}); 

您的真/假测试仍然有效,因为0将返回false,并且任何不匹配的实例将递增并将其置为布尔正值。

答案 1 :(得分:0)

您收到错误,因为_isModalDirty最初未定义。如果我添加

var _isModalDirty = false;

到你的javascript顶部然后它适用于我

Working fiddle

编辑:您可能需要考虑将表单的状态设置为表单上的数据而不是变量:

$('.controls :input').change(function (){
    console.log('change run');
    $(this).closest('.modal').data('isModalDirty', true);
});

$('.modal-cancel').click(function (){
    console.log('click run');
    if ( $(this).closest('.modal').data('isModalDirty') ) {
        if (confirm('Are you sure you want to cancel? You will lose your unsaved changes.')) {
            closeModalPopup();
        }
    } else {
        closeModalPopup();
    }
});

var closeModalPopup = function () {
    resetModalPopup();
    $('.modal').data('isModalDirty', false).modal('hide');
}

var resetModalPopup = function() {
    $('.controls :input').each(function () {
        var $this = $(this);
        $this.val('');
    });    
}

这样可以更轻松地在页面上支持多个这样的模态,因为它不使用全局变量。 Fiddle using data

编辑2 OP在评论中说他们仍然需要点击两次。我认为问题实际上是您用于调试的警报。如果在一个字段中输入文本,则立即单击取消按钮,更改事件的警报将运行。警报是一个阻塞过程,在该块中,click事件似乎丢失了。尝试将alert更改为console.log(这在用户和功能上都不那么烦人且不那么干扰 - 在我看来调试数据的方式)并且我认为它有效(直到上面讨论的未定义变量问题。)

答案 2 :(得分:0)

我找到了答案。说实话,我不明白为什么这是答案,我不明白为什么JsFiddle没有重现它。 但是我只是交换了函数的顺序,然后它起作用了;

var _isModalDirty = false;

$('.modal-cancel').click(function () {
    if (_isModalDirty) {
        if (confirm('Are you sure you want to cancel? You will lose your unsaved changes.')) {
            closeModalPopup();
        }
    } else {
        closeModalPopup();
    }
});

$('.controls :input').change(function () {
    _isModalDirty = true;
});