Hacer clic en un botón dentro de un formulario provoca la actualización de la página


Tengo un formulario en Angular que tiene dos etiquetas de botones. Un botón envía el formulario en ng-click. El otro botón es puramente para la navegación usando ng-click. Sin embargo, cuando se hace clic en este segundo botón, AngularJS está causando una actualización de página que desencadena un 404. He caído un punto de interrupción en la función y está activando mi función. Si hago cualquiera de las siguientes cosas, se detiene:

  1. Si elimino el ng-click, el botón no causa una actualización de página.
  2. Si comento el código en la función, no causa una actualización de página.
  3. Si cambio la etiqueta de botón a una etiqueta de anclaje (<a>) con href="", entonces no causa una actualización.

Esta última parece la solución más simple, pero ¿por qué AngularJS incluso ejecuta cualquier código después de mi función que hace que la página se vuelva a cargar? Parece un bicho.

Aquí está la forma:

<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>

Aquí está el método del controlador:

$scope.showChangePassword = function() {
  $scope.selectedLink = "changePassword";
};
Author: Xufox, 2012-09-07

9 answers

Si echas un vistazo a la especificación del W3C, parece que lo más obvio es marcar los elementos del botón con type='button' cuando no quieres que se envíen.

Lo que hay que tener en cuenta en particular es donde dice

Un elemento button sin atributo type especificado representa lo mismo que un elemento button con su atributo type establecido en"submit"

 421
Author: LOAS,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-12 23:58:20

Puede intentar evitar el controlador predeterminado:

Html:

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

Js:

$scope.saveUser = function (event) {
  event.preventDefault();
  // your code
}
 69
Author: antage,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-09-10 16:02:51

Debe declarar el atributo ng-submit={expression} en su etiqueta <form>.

De los documentos ngSubmit http://docs.angularjs.org/api/ng.directive:ngSubmit

Habilita el enlace de expresiones angulares a eventos desububmit.

Además, evita la acción predeterminada (que para form significa enviar la solicitud al servidor y recargar la página actual).

 18
Author: Shane Stillwell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-09-07 20:08:14

Uso la directiva para evitar el comportamiento predeterminado:

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

Y luego, en html:

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

Esta directiva también se puede utilizar con <a> y todas las demás etiquetas

 17
Author: pleerock,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-02-05 12:56:01

Puede mantener <button type="submit">, pero debe eliminar el atributo action="" de <form>.

 5
Author: Anderson Ferreira,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-07 06:25:49

Me pregunto por qué nadie propuso la solución posiblemente más simple:

No utilice un <form>

Un <whatever ng-form> hace un mejor trabajo en mi humilde opinión y sin un formulario HTML, no hay nada que enviar por el propio navegador. Que es exactamente el comportamiento correcto cuando se utiliza angular.

 2
Author: maaartinus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-23 00:03:53

Esta respuesta puede no estar directamente relacionada con la pregunta. Es solo para el caso cuando envías el formulario usando scripts.

De acuerdo con ng-submit code

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

  event.preventDefault();
};

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

Agrega el receptor de eventos submit en el formulario. Pero submit event handler no se llamaría cuando submit se inicia llamando a form.presentar(). En este caso, ng-submit no impedirá la acción predeterminada, debe llamar a preventDefault usted mismo en el controlador ng-submit;

Para proporcionar una respuesta razonablemente definitiva, el Algoritmo de Envío de Formularios HTML elemento 5 establece que un formulario solo envía un evento de envío si no fue enviado llamando al método de envío (lo que significa que solo envía un evento de envío si es enviado por un botón u otro método implícito, por ejemplo, presionando intro mientras el foco está en un elemento de texto de tipo de entrada).

Ver El formulario enviado usando submit() desde un enlace no puede ser capturado por handubmit handler

 1
Author: user1577263,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-09 12:10:45

El primer botón envía el formulario y el segundo no

<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
Author: Amay Kulkarni,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-07-02 09:13:24

Añade acción a tu formulario.

<form action="#">

 0
Author: Swapnil Patwa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-24 19:15:04