Нажатие кнопки внутри формы вызывает обновление страницы


217

У меня есть форма в Angular, в которой есть две кнопки-теги. Одна кнопка отправляет форму на ng-click. Другая кнопка предназначена исключительно для навигации ng-click. Однако, когда нажимается эта вторая кнопка, AngularJS вызывает обновление страницы, которое вызывает 404. Я сбросил точку останова в функции, и она вызывает мою функцию. Если я сделаю любое из следующего, он остановится:

  1. Если я удаляю ng-click, кнопка не вызывает обновления страницы.
  2. Если я закомментирую код в функции, это не приведет к обновлению страницы.
  3. Если я поменяю тег кнопки на тег привязки ( <a>) с помощью href="", то это не вызовет обновления.

Последнее кажется самым простым решением, но почему AngularJS даже выполняет какой-либо код после моей функции, который вызывает перезагрузку страницы? Похоже, ошибка.

Вот форма:

<form class="form-horizontal" name="myProfile" ng-switch-when="profile">
  <fieldset>
    <div class="control-group">
      <label class="control-label" for="passwordButton">Password</label>
      <div class="controls">
        <button id="passwordButton" class="secondaryButton" ng-click="showChangePassword()">Change</button>
      </div>
    </div>

    <div class="buttonBar">
      <button id="saveProfileButton" class="primaryButton" ng-click="saveUser()">Save</button>
    </div>
  </fieldset>
</form>

Вот метод контроллера:

$scope.showChangePassword = function() {
  $scope.selectedLink = "changePassword";
};

Посмотрите, является ли это вашей проблемой github.com/angular/angular.js/issues/1238 (К сожалению, я не достаточно разбираюсь в github, чтобы определить, есть ли это исправление в версии 1.0.1 или нет) ,
Марк Райкок

Я видел это, но я не меняю местоположение, поэтому я не думаю, что это применимо. Если эта другая кнопка каким-то образом не вызывает отправку, но она не определена как тип отправки, и когда я нажимаю ng, кнопка не отправляет форму.
chubbsondubs

Было бы здорово, если бы вы могли предоставить рабочую демонстрацию этой проблемы. Возможно, начиная с: Angular Plnkr
Пит BD


Похоже, дубликат. stackoverflow.com/questions/16703215/…
Вайбс

Ответы:


471

Если вы посмотрите на спецификацию W3C , вам может показаться очевидной попытка пометить элементы кнопок, type='button'когда вы не хотите, чтобы они отправлялись.

Особо следует отметить, где говорится

Элемент кнопки без указанного атрибута типа представляет собой то же самое, что и элемент кнопки с атрибутом типа, установленным как «submit»


4
У меня та же проблема, что и у OP, но у моих кнопок указан тип - и все равно щелчок вызывает обновление. Какие-нибудь другие места, где я мог бы посмотреть?
Матео Веленик

Это наводит меня на мысль, что ваша проблема в JavaScript. Проблема, которую решает мой ответ, больше связана с dom и браузером. Некоторый JavaScript, обрабатывающий ваше нажатие кнопки, вероятно, вызывает перезагрузку, которую вы видите.
Удачной

Это именно то, что я искал. Это было очень неприятно на моей странице, потому что он должен был только показать ошибки, а не представить.
reaper_unique

У меня есть кнопки, помеченные как type = "button", и проблема тоже есть. В моем обработчике ng-click у меня есть $ event.stopPropagation (). Когда я удаляю его, он не перезагружается. Мне это нужно, хотя. Есть идеи, почему это вызывает перезагрузку страницы ?!
felixfbecker

@freshfelicio: попробуйте также добавить $event.preventDefault(), что помогло в моем случае. Но у меня нет объяснения, почему: - \
Тим Бют

72

Вы можете попытаться предотвратить обработчик по умолчанию:

HTML:

<button ng-click="saveUser($event)">

ЯШ:

$scope.saveUser = function (event) {
  event.preventDefault();
  // your code
}

Ницца! Это действительно соответствует моему сценарию!
Ричард

2
Это сработало для нас, когда мы использовали AngularJS внутри формы SharePoint. Я должен был добавить "event.stopPropagation ();" хотя хорошо.
Ник Демайо

19

Вы должны объявить атрибут ng-submit={expression}в вашем<form> теге.

Из документов ngSubmit http://docs.angularjs.org/api/ng.directive:ngSubmit

Включает привязку угловых выражений к событиям отправки.

Кроме того, он предотвращает действие по умолчанию (что для формы означает отправку запроса на сервер и перезагрузку текущей страницы).


3
Кроме того, убедитесь, что у вас не установлено свойство 'action' в форме: form (action = "/ login", lng-submit = "login ()"), поскольку это заставит страницу обновиться, даже если у вас установлен ng-submit ,
Дженсо

Отправка формы и предотвращение действий по умолчанию Так как роль форм в клиентских приложениях Angular отличается от роли в классических приложениях туда и обратно, желательно, чтобы браузер не переводил отправку формы в полную перезагрузку страницы, которая отправляет данные на сервер , Вместо этого должна быть запущена некоторая логика JavaScript для обработки отправки формы специфичным для приложения способом. По этой причине Angular запрещает действие по умолчанию (отправка формы на сервер), если в элементе <form> не указан атрибут действия. - docs.angularjs.org/api/ng.directive:form
Джинеш Гоэль

У меня есть форма с ng-submit = {expression} и кнопка с type = "submit". Работает как просто отлично, кроме как на BB10. Если я использую ВВЕРХ на клавиатуре ВВ10, страница обновится. Если я использую кнопку, которую я объявил в моей форме, она будет работать нормально.
Майкл

Это не работает для меня. Я точно следовал инструкциям. Страница все еще
отправляет

18

Я использую директиву для предотвращения поведения по умолчанию:

module.directive('preventDefault', function() {
    return function(scope, element, attrs) {
        angular.element(element).bind('click', function(event) {
            event.preventDefault();
            event.stopPropagation();
        });
    }
});

И тогда, в HTML:

<button class="secondaryButton" prevent-default>Secondary action</button>

Эта директива также может использоваться со <a>всеми другими тегами


+1 Спасибо! Это полезно, когда у вас нет доступа к <form>тегу и, следовательно, вы не можете использовать ng-submitдирективу.
jackvsworld

спасибо за это, но мне нужно также отменить ng-click в директиве
boi_echos

Это также предотвращает запуск формой обратного вызова ng-submit, верно?
Jhourlad Estrella


2

Интересно, почему никто не предложил самое простое решение:

не используйте <form>

A <whatever ng-form>делает ИМХО лучшую работу, и без HTML-формы сам браузер ничего не отправит. Что является правильным поведением при использовании угловых.


Как применить форму валидным на клик, а затем без тега формы?
Ризван Патель

1
@RizwanPatel Я думаю, я не понимаю, но с ng-form=someForm, вы получаете, $scope.someFormи у него есть $validполе. Так что я получаю все, что мне нужно <button ng-disabled="!someForm.$valid">.
Maaartinus


1

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

Согласно коду ng-submit

 var handleFormSubmission = function(event) {
  scope.$apply(function() {
    controller.$commitViewValue();
    controller.$setSubmitted();
  });

  event.preventDefault();
};

formElement[0].addEventListener('submit', handleFormSubmission);

Добавляет слушатель события отправки в форму. Но обработчик события submit не будет вызываться, когда submit инициируется вызовом form.submit (). В этом случае ng-submit не будет препятствовать действию по умолчанию, вы должны сами вызвать protectDefault в обработчике ng-submit;

Чтобы предоставить достаточно точный ответ, элемент 5 алгоритма отправки HTML-формы гласит, что форма отправляет событие submit, только если оно не было отправлено, путем вызова метода submit (что означает, что оно отправляет событие submit только в том случае, если оно отправлено кнопкой или другим неявным образом). метод, например, нажав клавишу ввода, когда фокус находится на текстовом элементе типа ввода).

См. Форма, отправленная с использованием submit () по ссылке, не может быть перехвачена обработчиком onsubmit


0

Первая кнопка отправляет форму, а вторая нет

<body>
<form  ng-app="myApp" ng-controller="myCtrl" ng-submit="Sub()">
<div>
S:<input type="text" ng-model="v"><br>
<br>
<button>Submit</button>
//Dont Submit
<button type='button' ng-click="Dont()">Dont Submit</button>
</div>
</form>

<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.Sub=function()
{
alert('Inside Submit');
}

$scope.Dont=function()
{
$scope.v=0;
}
});
</script>

</body>

0

Просто добавьте FormsModuleв importsмассив app.module.tsфайл и добавьте import { FormsModule } from '@angular/forms';в начало этого файла ... это будет работать.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.