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";
};
chubbsondubs
źródło
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
Wydaje się jak duplikat. stackoverflow.com/questions/16703215/…
Vaibs

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”

LOAS
źródło
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
}
antage
źródło
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).

Shane Stillwell
źródło
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

pleerock
źródło
+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,
5

Można zachować <button type="submit">, ale musi usunąć atrybut action=""z <form>.

Anderson Ferreira
źródło
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.

maaartinus
źródło
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

Dodaj akcję do formularza.

<form action="#">

Swapnil Patwa
źródło
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

użytkownik1577263
źródło
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>
Amay Kulkarni
źródło
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ć.

Sahil Sharma
źródło