Есть html форма в которой пользователь может менять свои данные:
<form action='/user/editProfile' id="edit-profile_form" method="post">
<ul class='profile-data'>
<li class='profile-data_item persona-icon'>Никнейм: <input id='profile_nickname' name='nickname' type="text" placeholder="Никнейм:" value="{{myNickname}}" :readonly="inputStatus == 1 ? true : false"></li>
<li class='profile-data_item'>Имя: <input name='name' id='profile_name' type="text" placeholder="Имя:" value="{{myName}}" :readonly="inputStatus == 1 ? true : false"></li>
<li class='profile-data_item'>Фамилия: <input name='surname' id='profile_surname' type="text" placeholder="Фамилия:" value="{{mySurname}}" :readonly="inputStatus == 1 ? true : false"></li>
<li class='profile-data_item b-day-icon'>Возраст: <input name='age' id='profile_age' type="text" placeholder="Возраст:" value="{{myAge}}" :readonly="inputStatus == 1 ? true : false"></li>
<li class='profile-data_item place-icon'><input type="text" name='city' id='profile_city' placeholder="Город" value="{{myCity}}" :readonly="inputStatus == 1 ? true : false">, <input name='country' id='profile_country' type="text" placeholder="Страна" value="{{myCountry}}" :readonly="inputStatus == 1 ? true : false"></li>
<li class='profile-data_item phone-icon'>Телефон: <input name='phoneNumber' id='profile_phoneNumber' type="text" placeholder="Телефон:" value="{{myPhoneNumber}}" :readonly="inputStatus == 1 ? true : false"></li>
<input type="hidden" name="_csrf" value='{{csrfToken}}' />
<input type="submit" value="Submit" id="edit-profile_submit">
</ul>
</form>
$("form").submit(function(e) {
e.preventDefault();
var csrf_token = {{csrfToken}};
$("body").bind("ajaxSend", function(elm, xhr, s){
if (s.type == "POST") {
xhr.setRequestHeader('X-CSRF-Token', csrf_token);
}
});
var pathname = window.location.href;
$.ajax({
type: "POST",
url: '/user/editProfile',
data: {
name: $("#profile_name").val(),
nickname: $("#profile_nickname").val(),
surname: $("#profile_surname").val(),
country: $("#profile_country").val(),
city: $("#profile_city").val(),
phoneNumber: $("#profile_phoneNumber").val(),
age: $("#profile_age").val()
},
dataType: "html",
contentType: "application/html, charset: UTF-*",
success: function(data){
console.log(data);
},
});
});
Но по неизвестным причинам, при нажатии на submit, сайт переходит по ссылке, которая указана в action=''. Почему-то preventDefault не делает то, что должен. В чём проблема? Версия jquery 3.1.0, на сервере форму обрабатывает код...
router.post('/editProfile', isLoggedIn, function (req, res, next){
var id = req.user._id;
console.log(req.body);
var nickname = req.body.nickname;
var name = req.body.name;
var surname = req.body.surname;
var age = req.body.age;
var city = req.body.city;
var country = req.body.country;
var phoneNumber = req.body.phoneNumber;
User.findByIdAndUpdate(id, { $set: { nickname: nickname, name: name, surname: surname, age: age, city: city, country: country, phoneNumber: phoneNumber }}, function (err, user) {
if (err) return handleError(err);
console.log("ADDED!!!!!!!!!!!!!");
});
});
В итоге форма отправляется и в базу заносятся новые данные, но страница перезагружается, хотя мне это не нужно.
Все действия происходят на странице /user/:userid
Если так вышло, что preventDefault не прервал отправки данных на сервер через submit, то можно добавить дополнительную проверку:
e.preventDefault();
if(!e.isDefaultPrevented()){
e.returnValue = false;
}
Также, чтобы отправки формы не произошло - достаточно внутри обработчика, точнее внутри функции, в конце, написать return false;. Если функция возвращает false, то отправки не будет, а если true - выполниться отправка формы.
preventDefault может не срабатывать по причине того, что имеются другие обработчики, которые отправляют данные с формы, к примеру. Для такого случая можно попробовать вызвать stopImmediatePropagation, а не preventDefault. То есть так:
e.stopImmediatePropagation(); // вместо e.preventDefault();
Ну а вообще, вот этот код:
$("body").bind("ajaxSend", function(elm, xhr, s){
if (s.type == "POST") {
xhr.setRequestHeader('X-CSRF-Token', csrf_token);
}
});
Вы в bind к "body" устанавливаете обработчик события на ajaxSend, который срабатывает каждый раз перед отправкой Ajax-запроса, причем setRequestHeader - устанавливает значение заголовка запроса HTTP. Проблема кроется скорее всего тут и preventDefault срабатывает, но срабатывает уже другой обработчик, после preventDefault. Ну и проблемная строка кода вот эта:
var csrf_token = {{csrfToken}};
Что приходит в браузер вместо вот этой строки?
var csrf_token = {{csrfToken}};
Вероятно, Вам нужно:
var csrf_token = "{{csrfToken}}";
csrf лучше хранить в подобном виде:
<meta name="csrf" content="{{csrfToken}}">
и брать его как-нибудь так:
var _token = $('meta[name="csrf-token"]').attr('content');
Смените:
data: {
name: $("#profile_name").val(),
nickname: $("#profile_nickname").val(),
surname: $("#profile_surname").val(),
country: $("#profile_country").val(),
city: $("#profile_city").val(),
phoneNumber: $("#profile_phoneNumber").val(),
age: $("#profile_age").val()
},
На:
var toSend = $(this).serializeArray(); // перед вызовом ajax, здесь будут все ваши данные с формы, с абсолютно такими же значениями
$.ajax({
// ...
data: toSend,
// ...
});
У меня данный код сработал, но, я так понмаю, что вы используете blade и скорее всего проблема в этой строчке:
var csrf_token = {{csrfToken}};
Попробуйте сменить на:
var csrf_token = '{{csrfToken}}';
Так должны были поступать советские пионеры: сначала создать себе трудность, потом преодолевать её.
Событие submit - это событие браузера "отправить форму". Но аффтар отправляет данные AJAX-запросом - зачем же тогда кнопка type='submit', зачем самому назначать событие, от которого потом нужно будет избавиться? Ну напишите type='button', прикрутите к ней .onclick - и вообще не нужны будут в обработчике ни .preventDefault(), ни return false.
Мало того, и тег <form> тут совсем не нужен, вместе с бессмысленными атрибутами action и method - это, тоже, всё потом указано в AJAX-запросе, ну и зачем он, тег <form>, для красоты?
Можно было бы подумать - что для того, чтобы удобнее было обращаться к полям формы по атрибутам name, но у тега <form> и нет такого атрибута, а в запросе аффтар собирает данные из полей по их id.
Резюме: в данном коде упаковывать поля в форму незачем (можно и в div), тип кнопки назначить button, прикрутить к ней обработчик на событие onclick - и совсем не потребуется отменять "событие браузера submit", ибо его и не будет существовать в природе.
Доклад окончен.
Современные инструменты для криптотрейдинга: как технологии помогают принимать решения
Апостиль в Лос-Анджелесе без лишних нервов и бумажной волокиты
Основные этапы разработки сайта для стоматологической клиники
Продвижение своими сайтами как стратегия роста и независимости