Formdaki bir düğmeyi tıklatmak sayfanın yenilenmesine neden olur


217

Angular içinde iki düğme etiketleri olan bir form var. Bir düğme formu gönderir ng-click. Diğer düğme sadece navigasyon içindir ng-click. Ancak, bu ikinci düğme tıklandığında, AngularJS, bir 404'ü tetikleyen bir sayfa yenilemesine neden oluyor. İşlevde bir kesme noktası bıraktım ve işlevimi tetikliyor. Aşağıdakilerden herhangi birini yaparsam durur:

  1. ng-clickDüğmesini kaldırırsam, düğme sayfanın yenilenmesine neden olmaz.
  2. İşlevdeki kodun yorumunu yaparsam sayfanın yenilenmesine neden olmaz.
  3. Düğme etiketini bir tutturma etiketine ( <a>) değiştirirsem href=""yenilemeye neden olmaz.

İkincisi en basit geçici çözüm gibi görünüyor, ancak neden AngularJS sayfamın yeniden yüklenmesine neden olan işlevimden sonra herhangi bir kodu çalıştırıyor? Bir böcek gibi görünüyor.

İşte form:

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

Denetleyici yöntemi şöyledir:

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

Sorunun bu olup olmadığını görün github.com/angular/angular.js/issues/1238 (Ne yazık ki, bu düzeltmenin 1.0.1 sürümünde olup olmadığını söyleyebilecek kadar github etrafında yolumu bilmiyorum) .
Mark Rajcok

Bunu gördüm, ama yerini değiştirmediğim için geçerli olduğunu düşünmüyorum. Bu diğer düğme bir şekilde gönderilmesine neden olmadıkça, ancak bir gönderme türü olarak tanımlanmadığı ve ng-click'i kaldırdığımda düğme formu göndermez.
chubbsondubs

Bu sorunun çalışan bir demosunu sunmak harika olurdu. Belki de başlayan: Angular Plnkr
Pete BD


Yanıtlar:


471

W3C spesifikasyonuna bir göz attıysanız , denemek için bariz olan şey, düğme öğelerinizi type='button'göndermelerini istemediğinizde işaretlemektir .

Özellikle dikkat edilmesi gereken şey, söylediği yer

Tür özelliği belirtilmemiş bir düğme öğesi, tür özniteliği "gönder" olarak ayarlanmış bir düğme öğesiyle aynı şeyi temsil eder


4
Ben OP aynı sorun var ama benim düğmeleri belirtilen türü var - ve yine de tıklama yenileme neden olur. Bakabileceğim başka yerler var mı?
Mateo Velenik

Bu bana sorunun javascript olduğunu gösteriyor. Cevabımın ele aldığı sorun dom ve tarayıcı arasında daha önemli. Düğme tıklatmanızı işleyen bazı javascript muhtemelen yeniden yüklemenize neden olabilir. Mutlu avcılık;)
LOAS

Tam da aradığım şey buydu. Sayfamda çok can sıkıcıydı çünkü yalnızca hataları göstermesi ve göndermemesi gerekiyordu.
reaper_unique

Benim düğmeleri type = "button" ile işaretlenmiş ve sorun da var. Ng-click işleyicimde $ event.stopPropagation () var. Kaldırdığımda yeniden yüklemiyor. Gerçi ihtiyacım var. Bir sayfanın yeniden yüklenmesine neden olduğu hakkında herhangi bir fikir var mı ?!
felixfbecker

@freshfelicio: $event.preventDefault()benim durumuma yardımcı olan eklemeyi de dene . Ama nedenini açıklayamıyorum: - \
Tim Büthe

72

Varsayılan işleyiciyi önlemeyi deneyebilirsiniz:

html:

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

js:

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

Güzel! Gerçekten benim senaryom getirildi!
Richard

2
Bu, SharePoint formunun içinde AngularJS kullanırken bizim için işe yaradı. "Event.stopPropagation ();" eklemek zorunda kaldım olsa da.
Nick DeMayo

19

Sen niteliğini beyan etmelidir ng-submit={expression}senin içinde <form>etiketi.

NgSubmit dokümanlarından http://docs.angularjs.org/api/ng.directive:ngSubmit

Gönderim sonrası olaylara bağlayıcı açısal ifadeleri etkinleştirir.

Ayrıca, varsayılan eylemi (form için isteği sunucuya gönderme ve geçerli sayfayı yeniden yükleme anlamına gelir) önler.


3
Ayrıca, formda 'action' özelliğinin ayarlanmadığından emin olun: form (action = "/ login", lng-send = "login ()") Bu ayar ng-send ayarınız olsa bile sayfanın yenilenmesini sağlayacaktır. .
jenso

Form gönderme ve varsayılan eylemi önleme Formların istemci tarafı Açısal uygulamalardaki rolü klasik gidiş dönüş uygulamalarından farklı olduğundan, tarayıcının form teslimini verileri sunucuya gönderen tam sayfa yeniden yüklemesine dönüştürmemesi istenir . Bunun yerine, form gönderimini uygulamaya özel bir şekilde işlemek için bazı javascript mantığı tetiklenmelidir. Bu nedenle, Açısal <form> öğesinde belirtilen bir eylem özniteliği olmadığı sürece varsayılan eylemi (sunucuya form gönderme) önler. - docs.angularjs.org/api/ng.directive:form
Jignesh Gohel

Ben ng-Submit = {expression} ile bir form ve type = "Submit" ile bir düğme var. BB10 hariç gayet iyi çalışıyor. BB10 klavyenin Submit'i kullanırsam sayfa yenilenir. Formumda bildirdiğim düğmeyi kullanırsam iyi çalışır.
Michael

Bu benim için çalışmıyor. Talimatları tam olarak takip ettim. Sayfa hala geri
gönderiyor

18

Varsayılan davranışı önlemek için yönerge kullanıyorum:

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

Ve sonra, html'de:

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

Bu yönerge <a>ve diğer tüm etiketlerle de kullanılabilir


+1 Teşekkürler! <form>Etikete erişiminiz olmadığında ve dolayısıyla ng-submityönergeyi kullanamadığınızda bu yararlı olur .
jackvsworld

Bunun için teşekkürler, ama aynı zamanda bir yönergede ng-click iptal etmek gerekiyor
boi_echos

Bu aynı zamanda formun ng-send geri aramasını tetiklemesini de önler, değil mi?
Jhourlad Estrella

5

Sen tutabilir <button type="submit">, ancak niteliği kaldırmalısınız action=""arasında <form>.


2

Kimsenin neden en basit çözümü önermediğini merak ediyorum:

kullanma <form>

A <whatever ng-form>, IMHO'yu daha iyi bir iş yapar ve HTML formu olmadan, tarayıcının kendisi tarafından gönderilecek hiçbir şey yoktur. Açısal kullanırken tam olarak doğru davranış budur.


form etiketi olmadan tıklama üzerine geçersiz form nasıl uygulanır?
Rizwan Patel

1
@RizwanPatel Sanırım, anlamıyorum, ama ng-form=someFormseninle geliyor $scope.someFormve bir $validalanı var. Böylece ihtiyacım olan her şeyi elde ederim <button ng-disabled="!someForm.$valid">.
maaartinus


1

Bu cevap doğrudan soruyla ilgili olmayabilir. Bu sadece formu komut dosyaları kullanarak gönderdiğinizde geçerlidir.

Göre kod ng gönderin

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

  event.preventDefault();
};

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

Forma olay dinleyicisi gönderir. Ancak, form.submit () çağrılarak gönderme başlatıldığında gönderme olay işleyicisi çağrılmaz. Bu durumda, ng-send varsayılan eylemi engellemez, ng-send işleyicisinde preventDefault'u aramanız gerekir;

HTML Form Gönderme Algoritması öğesi 5, makul bir şekilde kesin bir yanıt sağlamak için, bir formun yalnızca bir gönderme olayı göndererek gönderilmesini bildirir (yani yalnızca bir düğme veya başka bir örtük tarafından gönderilmişse bir gönderme olayı gönderir) yöntem, örneğin odak bir giriş türü metin öğesindeyken enter tuşuna basmak).

Bkz . Bir bağlantıdan gönder () kullanılarak gönderilen Form, gönderen işleyici tarafından yakalanamıyor


0

İlk Düğme formu gönderir, ikinci Düğme vermez

<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

Sadece eklemek FormsModuleiçinde importsdizisi app.module.tsdosyası ve eklemek import { FormsModule } from '@angular/forms';bu dosyanın en üstünde ... Bu çalışacaktır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.