フォーム内のボタンをクリックするとページが更新される


217

Angularに2つのボタンタグが含まれているフォームがあります。1つのボタンでフォームを送信しng-clickます。もう1つのボタンは、純粋にを使用したナビゲーション用ng-clickです。ただし、この2番目のボタンがクリックされると、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/issues/1238(残念ながら、この修正が1.0.1リリースに含まれているかどうかを確認できるほど、githubの使い方がわかりません) 。
Mark Rajcok、2012

見ましたが、場所を変えていないので当てはまらないと思います。この他のボタンが何らかの形で送信を引き起こしているのでない限り、送信タイプとして定義されていません。ng-clickを離しても、ボタンはフォームを送信しません。
chubbsondubs 2012

この問題の実用的なデモを提供していただければ幸いです。おそらく次から始まる:Angular Plnkr
ピートBD


重複しているようです。stackoverflow.com/questions/16703215/...
Vaibs

回答:


471

W3C仕様を見てみると、ボタン要素type='button'に送信させたくない場合にボタン要素にマークを付けるのは当然のことのようです。

特に注意することはそれが言うところです

type属性が指定されていないbutton要素は、type属性が "submit"に設定されたbutton要素と同じことを表します


4
OPと同じ問題がありますが、ボタンのタイプが指定されていますが、クリックしても更新が発生します。私が見ることができる他の場所はありますか?
Mateo Velenik 2015

これは、あなたの問題がJavaScriptにあることを示唆しています。私の答えが対処している問題は、domとブラウザの間の問題です。ボタンのクリックを処理するjavascriptが原因でリロードが発生している可能性があります。ハッピーハンティング;)
LOAS

これはまさに私が探していたものです。エラーのみを表示し、送信しないことになっていたので、私のページでは非常に迷惑でした。
reaper_unique 2015年

type = "button"のマークが付いたボタンがあり、問題もあります。私のng-clickハンドラーには、$ event.stopPropagation()があります。取り外してもリロードしない。私はそれも必要です。なぜそれがページのリロードを引き起こすのか?
felixfbecker 2015

@freshfelicio:を追加してみてください$event.preventDefault()。これは私の場合に役立ちました。しかし、理由はわかりません:-\
TimBüthe15年

72

デフォルトのハンドラを回避することができます:

html:

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

js:

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

いいね!それは本当に私のシナリオに取り込まれました!
Richard

2
これは、SharePointフォーム内でAngularJSを使用するときに機能しました。「event.stopPropagation();」を追加する必要がありました。同様に。
Nick DeMayo 2015年

19

あなたは、属性を宣言する必要がありng-submit={expression}、あなたに<form>タグ。

ngSubmit docs http://docs.angularjs.org/api/ng.directive:ngSubmitから

onsubmitイベントへの角度式のバインドを有効にします。

さらに、デフォルトのアクション(フォームの場合はサーバーにリクエストを送信し、現在のページを再読み込みすることを意味します)を防ぎます。


3
また、フォームに 'action'プロパティが設定されていないことを確認してください:form(action = "/ login"、lng-submit = "login()")これにより、ng-submitが設定されている場合でもページが更新されます。
ジェンソ2013年

フォームの送信とデフォルトアクションの防止クライアント側のAngularアプリケーションでのフォームの役割は従来の往復アプリとは異なるため、ブラウザがフォームの送信をデータをサーバーに送信する全ページの再読み込みに変換しないことが望ましい。代わりに、アプリケーション固有の方法でフォームの送信を処理するために、JavaScriptロジックをトリガーする必要があります。このため、<form>要素にaction属性が指定されていない限り、Angularはデフォルトのアクション(サーバーへのフォーム送信)を防止します。- docs.angularjs.org/api/ng.directive:form
Jignesh Gohel

ng-submit = {expression}を含むフォームとtype = "submit"を含むボタンがあります。BB10以外は問題なく動作します。BB10キーボードの[送信]を使用すると、ページが更新されます。フォームで宣言したボタンを使用すると、問題なく動作します。
マイケル

これは私のために働いていません。私は正確に指示に従いました。ページはまだ
ポストバックし

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 2015

これはありがとう
ござい

これにより、フォームがng-submitコールバックをトリガーすることもできなくなります。
Jhourlad Estrella、2015


2

おそらく最も簡単な解決策を誰も提案しなかったのはなぜでしょうか。

使用しないでください <form>

A <whatever ng-form>はIMHOの方が優れており、HTMLフォームがなければ、ブラウザ自体から送信するものはありません。これは、angularを使用する場合の正しい動作です。


formvalidをフォームタグなしでクリックして強制する方法は?
リズワンパテル

1
@RizwanPatel私の推測では、私は理解していないが、とng-form=someFormあなたが得る、$scope.someFormそしてそれが持って$validフィールドを。だから私は必要なものすべてを手に入れました<button ng-disabled="!someForm.$valid">
maaartinus


1

この回答は、質問に直接関連しているとは限りません。スクリプトを使用してフォームを送信する場合のみです。

よると、コードをNG-提出

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

  event.preventDefault();
};

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

フォームに送信イベントリスナーを追加します。ただし、送信イベントハンドラーは、form.submit()の呼び出しによって送信が開始されたときに呼び出されません。この場合、ng-submitはデフォルトのアクションを妨げません。ng-submitハンドラーでpreventDefaultを自分で呼び出す必要があります。

合理的な決定的な回答を提供するために、HTMLフォーム送信アルゴリズムアイテム5は、フォームがsubmitメソッドの呼び出しによって送信されなかった場合にのみ送信イベントをディスパッチすることを示しています(つまり、ボタンまたはその他の暗黙的に送信された場合にのみ送信イベントをディスパッチします。メソッド、たとえばフォーカスが入力タイプのテキスト要素にあるときにEnterキーを押す)。

リンクからsubmit()を使用して送信されたフォームをonsubmitハンドラーでキャッチできないを参照してください。


0

最初のボタンはフォームを送信し、2番目は送信しません

<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

ただ、追加FormsModuleimportsの配列app.module.tsファイル、および追加import { FormsModule } from '@angular/forms';このファイルの先頭に...これは動作します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.