2012-09-07 10 views
187

Mam formularz w Angular, który ma dwa znaczniki przycisków w nim. Jeden przycisk przesyła formularz na ng-click. Drugi przycisk służy wyłącznie do nawigacji przy użyciu ng-click. Jednak po kliknięciu tego drugiego przycisku AngularJS powoduje odświeżenie strony, które wyzwala 404. Zrzuciłem punkt przerwania w funkcji i uruchamia on moją funkcję. Gdybym wykonaj dowolną z następujących czynności, zatrzymuje:Kliknięcie przycisku w formularzu powoduje odświeżenie strony.

  1. Jeśli usunąć ng-click, przycisk nie powoduje odświeżania strony.
  2. Jeśli skomentuję kod w funkcji, nie spowoduje to odświeżenia strony.
  3. Jeśli zmienię znacznik przycisku na znacznik zakotwiczenia (<a>) z href="", to nie spowoduje to odświeżenia.

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

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

Oto metoda kontroler:

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

Zobacz, czy jest to Twój problem https://github.com/angular/angular.js/issues/1238 (Niestety, nie wiem, mój sposób wokół github wystarczy być może stwierdzić, czy ta poprawka jest w wersji 1.0.1 czy nie). –

+0

Widziałem to, ale nie zmieniam lokalizacji, więc nie sądzę, by miało to zastosowanie. O ile ten inny przycisk nie jest w jakiś sposób przyczyną jego przesłania, ale nie jest zdefiniowany jako typ przesyłania, a po zdjęciu przycisku ng, przycisk nie przesyła formularza. – chubbsondubs

+0

Byłoby wspaniale, gdybyś mógł przedstawić działające demo tego problemu. Być może zaczynając od: [Angular Plnkr] (http://plnkr.co/edit/gist:3662656) –

Odpowiedz

399

Jeśli spojrzeć na W3C specification, wydaje się, jakby oczywistą rzeczą, którą należy wypróbować, jest oznaczenie elementów przycisków za pomocą type='button', gdy nie chcesz m do przesłania.

Rzecz zauważyć w szczególności, gdzie jest napisane

Element Przycisk bez atrybutu typu określonego oznacza to samo jako element przycisk z atrybutem type ustawionym na „wyślij”

+4

Mam ten sam problem co OP, ale moje przyciski mają określony typ - i nadal klikam powoduje odświeżenie. Jakieś inne miejsca, w których mógłbym wyglądać? –

+0

Sugeruje to, że twój problem jest w javascript. Problem, na który moja odpowiedź polega, jest bardziej kwestią między domem a przeglądarką. Niektóre javascript obsługujące kliknięcie przycisku prawdopodobnie powodują ponowne załadowanie. Szczęśliwe polowanie;) – LOAS

+0

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

18

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

Od docs ngSubmit http://docs.angularjs.org/api/ng.directive:ngSubmit

umożliwia wiązanie kątowe do wyrażenia onSubmit wydarzeń.

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

+3

Upewnij się również, że nie ustawiono właściwości 'action' w formularzu: form (action = "/ login", lng-submit = "login()") Ponieważ spowoduje to odświeżenie strony, nawet jeśli masz -submit zestaw. – jenso

+0

Przesyłanie formularza i zapobieganie domyślnej akcji Ponieważ rola formularzy w aplikacjach Angular po stronie klienta jest inna niż w przypadku klasycznych aplikacji typu roundtrip, pożądane jest, aby przeglądarka nie tłumaczyła przesyłania formularza na pełne przeładowanie strony, które wysyła dane na serwer. Zamiast tego należy uruchomić niektóre logiki javascript, aby obsłużyć przesłanie formularza w specyficzny dla aplikacji sposób. Z tego powodu Angular zapobiega domyślnej akcji (przesyłanie formularzy do serwera), chyba że element

ma określony atrybut działania. - http://docs.angularjs.org/api/ng.directive:form –

+0

Mam formularz z ng-submit = {wyrażenie} i przycisk z type = "submit". Działa dobrze, z wyjątkiem BB10. Jeśli użyję funkcji Prześlij klawiaturę BB10, strona się odświeży. Jeśli użyję przycisku, który zadeklarowałem w mojej formie, działa dobrze. – Michael

67

Można próbować zapobiec domyślny handler:

html:

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

JS:

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

Nice! To naprawdę przyniosło mój scenariusz! – Richard

+2

To działało dla nas, gdy używamy AngularJS w formularzu SharePoint. Musiałem dodać "event.stopPropagation();" ale także. –

15

używam dyrektywy, aby zapobiec zachowanie domyślne:

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> 

Dyrektywa ta może być również używany z <a> i wszystkie inne znaczniki

+0

+1 Dzięki! Jest to przydatne, gdy nie masz dostępu do znacznika '' i dlatego nie można użyć dyrektywy 'ng-submit'. – jackvsworld

+0

Dziękuję za to, ale muszę również anulować ng-click w dyrektywie –

+0

Zapobiegnie to również uruchomieniu formularza wywołania zwrotnego ng-submit, prawda? –

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

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

2

Zastanawiam się, dlaczego nikt nie zaproponował możliwie najprostsze rozwiązanie:

Nie używaj <form>

<whatever ng-form> robi IMHO lepiej i bez formularza HTML, nie ma nic do przedłożenia przez samą przeglądarkę. Które jest dokładnie właściwe zachowanie, gdy używasz kątowe.

+0

jak wymusić formalizację na kliknięciu, a następnie bez tagu formularza? –

+1

@RizwanPatel Domyślam się, nie rozumiem, ale z 'ng-form = someForm', otrzymujesz' $ scope.someForm' i ma on '$ valid'. Dostaję wszystko, czego potrzebuję, używając przycisku '

0

Dodaj akcję do swojego formularza.

<form action="#">

0

Ta odpowiedź nie może być bezpośrednio związane z pytaniem. Jest tak tylko w przypadku, gdy przesyłasz formularz za pomocą skryptów.

Według ng-submit code

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

 
    event.preventDefault(); 
 
}; 
 

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

Dodaje złożyć detektor zdarzeń na formularzu. Ale funkcja zgłaszania zdarzeń nie zostanie wywołana, gdy zgłoszenie zostanie zainicjowane przez wywołanie metody form.submit(). W takim przypadku ng-submit nie zapobiegnie domyślnej akcji, musisz wywołać funkcję preventDefault samodzielnie w procedurze ng-submit;

Aby zapewnić rozsądny ostateczną odpowiedź, element HTML Form Składanie Algorytm 5 stanowi, że forma wywoła tylko przedstawić zdarzenia, jeżeli nie został złożony przez wywołanie metody dołączania (co oznacza, że ​​tylko wywołuje przedstawić zdarzenia, jeśli przedkładane za pomocą przycisku lub innej metody niejawnej, np. naciśnięcie klawisza enter, gdy fokus znajduje się na elemencie tekstowym typu wejściowego).

Zobacz Form submitted using submit() from a link cannot be caught by onsubmit handler

Powiązane problemy