Клацання кнопки у формі викликає оновлення сторінки


217

У мене є форма у кутовій, у якій є два теги кнопок. Одна кнопка подає форму на 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/isissue/1238 (На жаль, я не знаю, як обходитися github достатньо, щоб можна було сказати, чи є це виправлення у версії 1.0.1 чи ні) .
Марк Райкок

Я бачив це, але я не змінюю місцезнаходження, тому не думаю, що це стосується. Якщо ця інша кнопка якось не спричинить її надсилання, але вона не визначена як тип подання, і коли я знімаю натискання кнопки, кнопка не надсилає форму.
кругляки

Було б чудово, що ви можете надати діючу демонстрацію цієї проблеми. Можливо, починаючи з: Angular Plnkr
Pete BD


Здається, як дублікат. stackoverflow.com/questions/16703215 / ...
Vaibs

Відповіді:


471

Якщо ви подивитесь на специфікацію W3C , вам здається, очевидно, що слід спробувати - позначити елементи кнопки, type='button'коли ви не хочете, щоб вони надсилалися.

Особливо слід зазначити, де це сказано

Елемент кнопки з не вказаним атрибутом типу являє собою те саме, що й елемент кнопки, а його атрибут типу встановлено на "подати"


4
У мене така ж проблема, як у ОП, але в моїх кнопках вказаний тип - і все одно натискання викликає оновлення. Будь-які інші місця, де я міг би подивитися?
Матео Веленик

Це говорить про те, що ваша проблема в JavaScript. Проблема, на яку я відповів, - це більше питання між домом та браузером. Якесь оброблення javascript натисканням кнопки, ймовірно, спричинить перезавантаження, яке ви бачите. Щасливе полювання;)
ЛОЗ

Це саме те, що я шукав. На моїй сторінці це було дуже дратує, оскільки воно повинно було лише показувати помилки, а не подавати.
reaper_unique

У мене є кнопки, позначені типу = "кнопка", і у мене є проблема. У своєму обробнику ng click у мене є $ event.stopPropagation (). Коли я його видаляю, він не завантажується. Мені це потрібно, хоча. Будь-які ідеї, чому це викликає перезавантаження сторінки ?!
felixfbecker

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

72

Ви можете спробувати запобігти обробці за замовчуванням:

html:

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

js:

$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 .
jenso

Подання форми та запобігання дії за замовчуванням Оскільки роль форм у кутових додатках на стороні клієнта відрізняється, ніж у класичних додатках для прямого переходу, браузер бажано не переводити подання форми на повне перезавантаження сторінки, яке надсилає дані на сервер . Натомість слід запускати певну логіку JavaScript, щоб обробляти подання форми у конкретному додатку. З цієї причини Angular запобігає дії за замовчуванням (подання форми на сервер), якщо для елемента <form> не вказаний атрибут дії. - docs.angularjs.org/api/ng.directive:form
Jignesh Gohel

У мене є форма з ng-submit = {izraz} і кнопкою з type = "submit". Працює як просто, за винятком BB10. Якщо я використовую клавіатуру BB10 надіслати, сторінка буде оновлена. Якщо я використовую кнопку, яку я оголосив у своїй формі, вона добре працює.
Майкл

Це не працює для мене. Я точно слідував вказівкам. Сторінка все ще публікується назад
meffect

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>

<whatever ng-form>Робить ІМХО краще і без HTML форми, немає нічого , щоб бути представлені самим браузером. Яка саме правильна поведінка при використанні кутових.


як примусити формулеру натиснути потім без тегу форми?
Rizwan Patel

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

Він додає надіслати слухача події на форму. Але обробник події відправлення не буде викликаний, коли ініціюється подання, зателефонувавши form.submit (). У цьому випадку ng-submit не перешкоджає дії за замовчуванням, вам доведеться викликати prevenDefault самостійно в обробнику ng-submit;

Для надання достатньо остаточної відповіді, пункт 5 алгоритму подання форми HTML зазначає, що форма розсилає лише подію подання, якщо вона не була подана, викликаючи метод подання (це означає, що вона розсилає подія подання лише у випадку, якщо вона подана кнопкою або іншим неявним метод, наприклад натискання клавіші Enter, коли фокус знаходиться на текстовому елементі типу введення).

Див. Форму, подану за допомогою submit () із посилання, не може бути зафіксовано надісланим обробником


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.