如何在具有多个表单的页面上使用自动保存部分视图?

时间:2014-01-21 21:56:00

标签: javascript jquery asp.net asp.net-mvc forms

扩展在Autosave in MVC (ASP.NET)找到的示例,我想在我的应用程序中创建一个部分重用。我有一个带有选项卡式布局的视图,每个选项卡都有自己的表单,这会导致问题,即每个表单都会尝试每次都提交,并且只有文档中的第一个时间戳更新。我理解为什么会这样,但我不知道如何解决它。

Partial的cshtml:

<div class="form-group">
<label class="control-label col-lg-2" for=""> </label>
<div class="col-lg-10">
    <span class="help-block" id="autosaveTime">Not Autosaved</span>
</div>
</div>

@{
    var autosaveString = "'" + @ViewData["autosaveController"] + "'";
    if (ViewData["autosaveAction"] != null && ViewData["autosaveAction"] != "")
        autosaveString += ", '" + ViewData["autosaveAction"] + "'";
} 

<script type="text/javascript">
    $(document).ready(function () {
        autosave(@Html.Raw(autosaveString));
    });
</script>

使用Javascript:

//methodName is optional-- will default to 'autosave'
function autosave(controllerName, methodName)
{
    methodName = typeof methodName !== 'undefined' ? methodName : 'autosave'
    var dirty = false;
    $('input, textarea, select').keypress(function () {
        dirty = true;
    });
    $('input, textarea, select').change(function () {
        dirty = true;
    });
    window.setInterval(function () {
        if (dirty == true) {
            var form = $('form');
            var data = form.serialize();
            $.post('/' + controllerName + '/' + methodName, data, function () {
                $('#autosaveTime').text("Autosaved at " + new Date);
            })
            .fail(function () {
                $('#autosaveTime').text("There was a problem autosaving, check your internet connection and login status.");
            });
            dirty = false;
        }
    }, 30000); // 30 seconds
}

我有2个关于如何修复它的想法,但不确定哪个更易于维护/可行:

  1. 为每个表单指定一个id,并将其传递给partial / autosave函数。将名称添加到autosavetime文本块以获取更新,并确定要序列化/提交的表单。
  2. 以某种方式使用jquery的closest函数来查找放置自动保存块的表单,并使用它来执行我使用#1明确执行的操作。

1 个答案:

答案 0 :(得分:1)

首先,使用Razor帮助程序的Html扩展名创建URL(在JavaScript中动态拼接这样的URL是不必要的风险)。把它拿到选项卡控件的数据属性中,如下所示:

<div class="tab autosave" data-action-url='@Html.Action("Action", "Controller")'>
    <form>
        <!-- Insert content here -->
    </form>
</div>

然后,你会想要这样的东西 - 不要在任何地方都包含它,并完全从你的部分中删除javascript:

$(function() {
    // Execute this only once, or you'll end up with multiple handlers... not good
    $('.autosave').each(function() {
        var $this = $(this),
            $form = $this.find('form'),
            dirty = false;

        // Attach event handler to the tab, NOT the elements--more efficient, and it's always properly scoped
        $this.on('change', 'input select textarea', function() {
            dirty = true;
        });

        setInterval(function() {
            if(dirty) {
                // If your form is unobtrusive, you might be able to do something like: $form.trigger('submit'); instead of this ajax
                $.ajax({
                    url : $this.data('action-url'),
                    data : $form.serialize()
                }).success(function() {
                    alert("I'm awesome");
                    dirty = false;
                });
            }
        }, 30 * 1000);
    });
});