Kliknięcie przycisku w formularzu powoduje odświeżenie strony


217

Mam formularz w Angular, który zawiera dwa znaczniki przycisków. Jeden przycisk przesyła formularz na ng-click. Drugi przycisk służy wyłącznie do nawigacji ng-click. Jednak po kliknięciu tego drugiego przycisku AngularJS powoduje odświeżenie strony, które powoduje 404. Upuściłem punkt przerwania w funkcji i uruchamia moją funkcję. Jeśli wykonam jedną z poniższych czynności, przestanie to działać:

  1. Jeśli usunę przycisk ng-click, przycisk nie spowoduje odświeżenia strony.
  2. Jeśli skomentuję kod w funkcji, nie spowoduje to odświeżenia strony.
  3. Jeśli zmienię tag przycisku na tag anchor ( <a>) za pomocą href="", nie spowoduje to odświeżenia.

To ostatnie wydaje się być najprostszym obejściem, ale dlaczego AngularJS uruchamia nawet dowolny kod po mojej funkcji, który powoduje przeładowanie strony? Wygląda na błąd.

Oto formularz:

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

Oto metoda kontrolera:

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

Sprawdź, czy to jest twój problem github.com/angular/angular.js/issues/1238 (Niestety, nie znam wystarczająco dużo sposobów na obejście github, aby móc stwierdzić, czy ta poprawka jest w wersji 1.0.1, czy nie) .
Mark Rajcok

Widziałem to, ale nie zmieniam lokalizacji, więc nie sądzę, żeby miało to zastosowanie. Chyba że ten inny przycisk w jakiś sposób powoduje przesłanie go, ale nie jest zdefiniowany jako typ przesyłania, a kiedy zdejmuję kliknięcie ng, przycisk nie przesyła formularza.
chubbsondubs

Byłoby świetnie, gdybyś mógł przedstawić działającą wersję demonstracyjną tego problemu. Być może zaczynając od: Angular Plnkr
Pete BD


Odpowiedzi:


471

Jeśli spojrzysz na specyfikację W3C , wydaje się, że oczywistą rzeczą jest, aby spróbować oznaczyć elementy przycisków, type='button'gdy nie chcesz, aby były przesyłane.

W szczególności należy zwrócić uwagę na to, co mówi

Element przycisku bez określonego atrybutu typu reprezentuje to samo, co element przycisku z atrybutem typu ustawionym na „prześlij”


4
Mam taki sam problem jak OP, ale moje przyciski mają określony typ - i nadal kliknięcie powoduje odświeżenie. Jakieś inne miejsca, gdzie mógłbym szukać?
Mateo Velenik

To sugeruje mi, że twój problem jest w javascript. Problem, na który mam odpowiedź, jest bardziej kwestią między domem a przeglądarką. Niektóre javascript obsługujący kliknięcie przycisku prawdopodobnie powoduje przeładowanie, które widzisz.
Udanych

Właśnie tego szukałem. To było bardzo denerwujące na mojej stronie, ponieważ miało tylko pokazywać błędy, a nie przesyłać.
reaper_unique

Mam moje przyciski z oznaczeniem type = "button" i mam problem. W moim module obsługi ng-click mam $ event.stopPropagation (). Kiedy go usunę, nie zostanie ponownie załadowany. Potrzebuję tego jednak. Wszelkie pomysły, dlaczego powoduje to przeładowanie strony ?!
felixfbecker,

@freshfelicio: spróbuj również dodać $event.preventDefault(), co pomogło w moim przypadku. Ale nie mam wyjaśnienia, dlaczego: - \
Tim Büthe,

72

Możesz spróbować zapobiec domyślnemu programowi obsługi:

HTML:

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

js:

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

Miły! To naprawdę pasuje do mojego scenariusza!
Richard

2
To działało dla nas, gdy korzystamy z AngularJS w formularzu SharePoint. Musiałem dodać „event.stopPropagation ();” jak również.
Nick DeMayo

19

Powinieneś zadeklarować atrybut ng-submit={expression}w swoim <form>tagu.

Z dokumentacji ngSubmit http://docs.angularjs.org/api/ng.directive:ngSubmit

Umożliwia wiązanie wyrażeń kątowych z zdarzeniami onsubmit.

Dodatkowo zapobiega domyślnej akcji (co dla formularza oznacza wysłanie żądania do serwera i ponowne załadowanie bieżącej strony).


3
Upewnij się również, że nie masz ustawionej właściwości „action” w formularzu: form (action = "/ login", lng-subm = "login ()") Ponieważ spowoduje to odświeżenie strony, nawet jeśli masz zestaw ng-upload .
Jenso

Przesyłanie formularza i zapobieganie domyślnemu działaniu Ponieważ rola formularzy w aplikacjach Angular po stronie klienta jest inna niż w klasycznych aplikacjach typu roundtrip, pożądane jest, aby przeglądarka nie tłumaczyła przesłania formularza na pełne ładowanie strony, które wysyła dane do serwera . Zamiast tego należy uruchomić pewną logikę javascript, aby obsłużyć przesłanie formularza w sposób specyficzny dla aplikacji. Z tego powodu Angular uniemożliwia domyślną akcję (przesłanie formularza na serwer), chyba że element <form> ma określony atrybut akcji. - docs.quarejs.org/api/ng.directive:form
Jignesh Gohel

Mam formularz z ng-submenu = {wyrażenie} i przycisk z typem = "wyślij". Działa jak w porządku, z wyjątkiem BB10. Jeśli użyję polecenia Prześlij klawiatury BB10, strona zostanie odświeżona. Jeśli użyję przycisku, który zadeklarowałem w formularzu, działa dobrze.
Michael

To mi nie działa. Dokładnie zastosowałem się do wskazówek. Strona wciąż się wyświetla z powrotem
skuteczny

18

Używam dyrektywy, aby zapobiec domyślnemu zachowaniu:

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

A następnie w html:

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

Tej dyrektywy można także używać ze <a>wszystkimi innymi tagami


+1 dzięki! Jest to pomocne, gdy nie masz dostępu do <form>tagu, a zatem nie możesz użyć ng-submitdyrektywy.
jackvsworld 16.0415

dziękuję za to, ale muszę też anulować ng-click w dyrektywie
boi_echos

Zapobiega to również wyzwalaniu przez formularz wywołania zwrotnego ng-upload, prawda?
Jhourlad Estrella,


2

Zastanawiam się, dlaczego nikt nie zaproponował możliwie najprostszego rozwiązania:

nie używaj <form>

A <whatever ng-form>robi IMHO lepszą pracę i bez formularza HTML, sama przeglądarka nie ma nic do przesłania. To jest dokładnie właściwe zachowanie przy użyciu kątownika.


jak wymusić formvalid na kliknięcie, a następnie bez tagu formularza?
Rizwan Patel

1
@RizwanPatel Chyba nie rozumiem, ale z ng-form=someForm, dostajesz $scope.someFormi ma $validpole. Mam więc wszystko, czego potrzebuję <button ng-disabled="!someForm.$valid">.
maaartinus


1

Ta odpowiedź może nie być bezpośrednio związana z pytaniem. Dotyczy to tylko przypadku przesłania formularza za pomocą skryptów.

Zgodnie z kodem ng-upload

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

  event.preventDefault();
};

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

Dodaje on nasłuchiwanie zdarzenia przesłania w formularzu. Ale moduł obsługi zdarzeń wysyłania nie byłby wywoływany, gdy wysyłanie jest inicjowane przez wywołanie form.submit (). W takim przypadku ng-subm nie zapobiegnie domyślnej akcji, musisz sam wywołać preventDefault w module obsługi ng-subm;

Aby udzielić rozsądnie ostatecznej odpowiedzi, pozycja 5 formularza algorytmu HTML stwierdza, że ​​formularz wywołuje zdarzenie wysyłania tylko wtedy, gdy nie zostało przesłane przez wywołanie metody wysyłania (co oznacza, że ​​wywołuje zdarzenie przesłania tylko, jeśli zostanie przesłane przyciskiem lub innym niejawnym metoda, np. naciśnięcie Enter, gdy fokus znajduje się na elemencie tekstowym typu wejściowego).

Zobacz Formularz przesłany za pomocą subm () z linku nie może zostać przechwycony przez moduł obsługi onsubmit


0

Pierwszy przycisk przesyła formularz, a drugi nie

<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

Wystarczy dodać FormsModuledo importstablicy app.module.tspliku i dodaćimport { FormsModule } from '@angular/forms'; w górnej części tego pliku ... to będzie działać.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.