Какой самый простой способ определить, было ли изменено хотя бы одно поле в форме HTML? - PullRequest
38 голосов
/ 01 марта 2009

У меня есть HTML-форма с более чем 20 полями. У меня также есть пара ссылок на странице, которые уведут пользователя от формы ... потенциально без сохранения каких-либо изменений.

Я хочу предупредить (подтверждение JS) пользователя onClick этих ссылок, если какие-либо поля формы изменились, но я не хочу создавать огромный оператор switch, который мне нужно будет поддерживать при добавлении новых полей форма. Я знаю, как создать длинный список операторов if в Javascript, назвав каждое из полей и проверив каждое значение, но я не хочу этого делать, если мне это удастся.

Какой самый простой способ проверить, изменил ли пользователь хотя бы одно из значений поля?

Ответы [ 6 ]

69 голосов
/ 01 марта 2009

подход

  1. сериализует форму (и все ее значения) перед ее отображением ( jQuery way , Prototype way )
  2. снова сериализовать его в обработчик событий "onbeforeunload"

Если они не совпадают, значит, они изменили форму, поэтому верните строку (например, «У вас есть несохраненные данные») из вашего обработчика onbeforeunload.

Этот метод позволяет развиваться полям формы, в то время как логика «Подтвердить, если изменилось» остается прежней.

Пример (смешанный JavaScript и jquery)

var form_clean;

// serialize clean form
$(function() { 
    form_clean = $("form").serialize();  
});

// compare clean and dirty form before leaving
window.onbeforeunload = function (e) {
    var form_dirty = $("form").serialize();
    if(form_clean != form_dirty) {
        return 'There is unsaved form data.';
    }
};
11 голосов
/ 03 апреля 2009

Я почти уверен, что это плохая идея, но я хотел выбросить ее туда.

Поля формы имеют способ получить «значение по умолчанию» (то есть значение, которое поле имело при загрузке), и вы можете сравнить его с текущим значением. Простой цикл над всеми полями устраняет необходимость в обслуживании, если вы добавляете поля в форму.

Могут быть или не быть различные ошибки браузера, связанные со свойствами «значения по умолчанию», поэтому я бы не стал доверять этому методу без тщательного тестирования. Приведенный ниже код является подтверждением концепции и не используется (мной) ни в одном реальном приложении.

function IsDirty(form) {
    for (var i=0; i<form.elements.length; i++) {
        var field = form.elements[i];
        switch (field.type) {
            case "select-multiple":
            case "select-one":
                var options = field.options;
                for (var j=0; j<options.length; j++) {
                    if(options[j].selected != options[j].defaultSelected) return true;
                }
                break;
            case "text":
            case "file":
            case "password":
                if (field.value != field.defaultValue) return true;
                break;
            case "checkbox":
            case "radio":
                if (field.checked != field.defaultChecked) return true;
                break;
        }
    }
    return false;
}
9 голосов
/ 01 марта 2009

Используя jQuery, это очень просто. Вы должны быть в состоянии использовать ту же предпосылку для достижения того же результата и в ванильном javascript.

var $inps = $('#myForm').find('input,select,textarea')
  , formAltered = false
;
$inps.change(function() {
    formAltered = true;
    $inps.unbind('change'); // saves this function running every time.
});

Единственная проблема, связанная с этим, заключается в том, что если вы измените значение, а затем вернете его к исходному, оно все равно сообщит форму как измененную.

5 голосов
/ 01 марта 2009

Вот один вкладыш, который вы можете добавить к своим формам:

$(':input',document.myForm).bind("change", function() { 
  enablePrompt(true); }); // Prevent accidental navigation away

И тогда вы можете сделать функцию enableUnloadPrompt () для всего сайта:

function enablePrompt(enabled) {
  window.onbeforeunload = enabled ? "Your changes are not saved!" : null;
}

И, наконец, перед тем, как правильно отправить форму, убедитесь, что:

enablePrompt(false);

Это не будет проверять, отличаются ли формы значениями, только если форма когда-либо изменялась пользователем. Но он прост и удобен в использовании.

3 голосов
/ 01 марта 2009

Это может быть обработано только одной логической переменной, мы называем это грязной обработкой битов. Если вы наблюдали, как правило, на веб-страницах, когда пользователь выполняет какое-либо действие по редактированию любого из полей, форма считается грязной (отредактированной) (даже если данные остаются неизменными после редактирования). Когда пользователь пытается отойти от страницы, пользователю предлагается сохранить изменения.

Согласно стандартной практике, после редактирования какого-либо поля нет проверки, изменилось ли значение на самом деле или нет. Например: если пользователь редактирует и добавляет «xyz» к текстовому полю, а затем удаляет «xyz», по существу данные формы остаются такими же, как и раньше, но форма все еще считается «грязной», и пользователю предлагается предупреждающее сообщение, когда он пытается уйти.

Итак, если вы хотите реализовать это, все станет довольно просто. Вам просто нужно добавить обработчики событий onchange () к элементам управления и установить глобальную логическую переменную, похожую на isDirty, на true внутри этих обработчиков.

Когда пользователь захочет уйти, вы можете прошить сообщение «Возможно, на текущей странице есть несохраненные изменения. Вы хотите сохранить их?». Пользователь не будет разочарован, даже если он заметит, что его редактирование не изменило исходные данные.

Ответы, приведенные выше, реализуют именно это поведение. И я написал это, потому что у вас, похоже, была идея проверить каждое поле по его начальному значению, чтобы увидеть, действительно ли оно было изменено после редактирования. Просто хотел сказать вам, что проверка каждого поля вообще не нужна.

0 голосов
/ 12 июня 2019

В моем случае я объединил ответы @Crescent Fresh и @nickf и получил следующий:

var formBefore;

var $inps = $('form').find('input,select,textarea');

$(function() {
    formBefore = $("form").serialize();
});

$inps.change(function () {
    var changedForm = $("form").serialize();
    if (formBefore != changedForm) {
        $("#btnSave").css('background-color', 'green');
    } else {
        $("#btnSave").css('background-color', '');
    }
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...