アンカータグのDefaultを防止する方法


342

私がアンカータグを持っているとしましょう

<a href="#" ng-click="do()">Click</a>

AngularJSでブラウザーが#に移動しないようにするにはどうすればよいですか?


14
Chrisが以下で言うように、単に省略しますhref
ジェシー

13
それはクリスが言っていることではありません、ジェシー、href=''マウスポインタの動作を維持するために使用します。
oma

1
#記号をhrefから削除するだけでOKです。
HENG Vongkol

4
または、href = "javascript:void(0);"を使用します ポインタを保持するがアクションはない(別のクリックハンドラーを追加するまで)
Robba

1
承認された回答を、Chrisによる最高の最も投票された回答に変更していただけませんか?-stackoverflow.com/a/11672909
Piotr Dobrogost

回答:


259

更新:私はこの解決策に私の考えを変えました。これに取り組むためにより多くの開発と時間を費やした後、私はこの問題のより良い解決策は次のことをすることだと思います:

<a ng-click="myFunction()">Click Here</a>

次にcss、ルールを追加してを更新します。

a[ng-click]{
    cursor: pointer;
}

そのはるかにシンプルでまったく同じ機能を提供し、はるかに効率的です。これが将来このソリューションを探している他の人に役立つことを願っています。


以下は、以前の解決策ですが、レガシーの目的でここに残します。

この問題が頻繁に発生している場合、この問題を修正する簡単なディレクティブは次のとおりです。

app.directive('a', function() {
    return {
        restrict: 'E',
        link: function(scope, elem, attrs) {
            if(attrs.ngClick || attrs.href === '' || attrs.href === '#'){
                elem.on('click', function(e){
                    e.preventDefault();
                });
            }
        }
   };
});

すべてのアンカータグ(<a></a>)をチェックして、それらのhref属性が空の文字列("")またはハッシュ('#')であるか、ng-click割り当てがあるかどうかを確認します。これらの条件のいずれかが見つかると、イベントをキャッチしてデフォルトの動作を妨げます。

唯一の欠点は、すべてのアンカータグに対してこのディレクティブを実行することです。したがって、ページに多数のアンカータグがあり、少数のアンカータグのデフォルトの動作のみを防止したい場合、このディレクティブはあまり効率的ではありません。ただし、たいていはpreventDefaultを使用したいので、AngularJSアプリでこのディレクティブを使用しています。


2
@matejkramny、非常に建設的な批評に感謝します。「面倒」を少なくするための提案はありますか?
Tennisgent 2013年

1
他の回答で述べたように、空白のhref属性を持つことは、ブラウザーによって動作が異なります。私はこれがはるかにクリーンで最も効率的なソリューションであることに同意しますが、いくつかのクロスブラウザの問題があります。ディレクティブアプローチを使用すると、ブラウザー<a>は通常どおりにタグを処理できますが、OPは探していた答えを得ることができます。
Tennisgent 2013年

2
これは機能しますが、非常に単純な問題の場合は、深刻なオーバーキルを除きます。Angularでは$ eventを使用してイベントオブジェクトにアクセスできるため、単純なjsまたはjqueryクリックイベントで行うのとまったく同じことができます。この回答を参照してください。stackoverflow.com / a / 19240232/1826354とそれに対する私のコメント
Charlie Martin

1
うん。あなたはできる。この投稿には、あなたが説明していることをすでに行っている他の2つの回答があります。そして、私は同意します、それはやり過ぎです。それが、私が行った更新を行った理由です。
Tennisgent

6
これは、サイトのアクセシビリティを気にしない場合は問題ありません。hrefを省略すると、キーボードを使用してその項目にタブで移動することができなくなります。tabindexを追加しない限り。これらすべてを念頭に置いて、なぜpreventDefault ...を使用しないのですか?それが目的です。
duhseekoh 2015

319

ngHrefドキュメントによると、href を省略したり、href = ""を実行したりできるはずです。

<input ng-model="value" /><br />
<a id="link-1" href ng-click="value = 1">link 1</a> (link, don't reload)<br />
<a id="link-2" href="" ng-click="value = 2">link 2</a> (link, don't reload)<br />
<a id="link-4" href="" name="xx" ng-click="value = 4">anchor</a> (link, don't reload)<br />
<a id="link-5" name="xxx" ng-click="value = 5">anchor</a> (no link)<br />

6
それが唯一の実際の良い答えです。DOMやネイティブイベントに触れる必要があるものには疑問があります
vincent

4
これが正解です。あなたは<A>属性AngularJSからのhrefドロップした場合は、デフォルトを防ぐ呼び出します:
pkozlowski.opensource

25
href属性を省略した場合の唯一の欠点は、リンクにカーソルを合わせると通常の「ポインター」カーソルが失われることです。これを修正するには、スタイルシートにルールを追加します:a:hover {cursor:pointer; }
karlgold 2013年

35
これにより、タグがタブ化できなくなります。これは、アクセシビリティにあまり適していません。
Richard Szalay 2013年

3
私にとって、ブラウザはまだクリックアクションをバブルします:/
Matej

238

$ eventオブジェクトをメソッドに渡して呼び出す$event.preventDefault()ことができるため、デフォルトの処理は行われません。

<a href="#" ng-click="do($event)">Click</a>

// then in your controller.do($event) method
$event.preventDefault()

13
はい。また、イベントが発生しないように$ event.stopPropagation()を呼び出すこともできます(基本的に、W3Cで定義されているように、Eventオブジェクトにアクセスできます:w3.org/TR/DOM-Level-2- Events / events.html#Events-Event
mna 2012

1
この記事が執筆された時点では、hrefを空のまま(または存在しない)のままにして IE8 / 9とOpera では機能しませんでした。これは1年前で、もう一度試す機会がありませんでした(当時、Githubで問題を開きましたが、しばらく前に問題をリセットしたと思います)。これが修正された場合(またはこれらのブラウザーを気にしない場合)は、必ずChrisの回答を使用してください!誰かがそれを試してコメント/編集することができれば、さらに良い。
mna

1
@PuerkitoBio-IE8以前ではまだ$event.preventDefault()IE税が必要であることを確認できます。
Scotty.NET 2013

4
$ eventをコントローラーに渡すことは、コントローラー内のDOMを参照することを意味します。これは、ビューとコントローラーを結合したことを意味します。評価された式で$ eventメソッドを直接呼び出すことができます。ng-click="do(); $event.preventDefault()たとえば、...ただし、以下の@Chrisの答えが正しいため、これは必要ありません。これは、ngClicksをネストしていてを呼び出したい場合に役立ち$event.stopPropagation()ます。
Ben Lesh 2013年

2
最後に、SEOフレンドリーなソリューションです。ng-viewをリロードせずにブラウザのURLを更新することも できます-joelsaupe.com/programming/…このようにすると、ビューをリロードしないリンクがありますが、新しいタブで開くことができ、検索エンジンがリンクをたどることができます。わーい!
トム

111

私はこの種のもののためにディレクティブを使用することを好みます。ここに例があります

<a href="#" ng-click="do()" eat-click>Click Me</a>

そしてのディレクティブコードeat-click

module.directive('eatClick', function() {
    return function(scope, element, attrs) {
        $(element).click(function(event) {
            event.preventDefault();
        });
    }
})

これで、eat-click属性を任意の要素に追加できるようになり、属性がpreventDefault()自動的に取得されます。

利点:

  1. 醜い$eventオブジェクトをdo()関数に渡す必要はありません。
  2. $eventオブジェクトをスタブする必要がないため、コントローラーはよりユニットテストが可能です

1
@Kato Angularには、私たちの生活を簡単にするために、jQueryの独自のサブセットが付属しています。
2013

3
その他の利点 -これは、必要に応じて、IE8以下でも機能します。
Scotty.NET 2013

1
私は取得していますError: $ is not defined。何が欠けていますか?
ビラルミルザ2013

7
試しましたangular.element(element).bind('click', function(event){...});。動いた。参考:jQLite
ビラルミルザ

3
そのような単純なもののディレクティブを紹介すると、私に尋ねると少し肥大しているように見えます...クリスの回答をチェックしてください
Wilt

54

ルノーは素晴らしい解決策を提供しましたが

<a href="#" ng-click="do(); $event.preventDefault()">Click</a> 

個人的には、副作用を回避するために、場合によっては$ event.stopPropagation()も必要であることがわかりました

<a href="#" ng-click="do(); $event.preventDefault(); $event.stopPropagation();">
    Click</a>

私の解決策になります


34
ng-click="$event.preventDefault()"

13
これが最良の解決策です。もちろん、$ eventオブジェクトをスコープ関数に渡すこともできます。MyFunctionの中でクリック-ngの= "MyFunctionを($イベント、otherParams)、その後、$ event.preventDefault()枚このため、独自のディレクティブをローリングすることは行き過ぎである。
チャーリー・マーティン

34

私が見つけた最も簡単な解決策はこれです:

<a href="#" ng-click="do(); $event.preventDefault()">Click</a>

これは最も簡単なだけでなく、他のソリューションで提案されているように、イベントをコントローラーと結合しません。イベントをコントローラーに結合することは、テストを非常に困難にするため、絶対に避けなければなりません。
jornare 14

11

したがって、これらの回答を読んでも、@ Chrisはまだ「正しい」回答を持っていると思いますが、問題が1つあり、「ポインタ」が表示されません...

したがって、cursor:pointerスタイルを追加することなく、この問題を解決する2つの方法があります。

  1. javascript:void(0)代わりに使用#

    <a href="javascript:void(0)" ng-click="doSomething()">Do Something</a>
  2. ディレクティブで使用$event.preventDefault()ng-clickます(したがって、DOM関連の参照でコントローラーをジャンクしないでください)。

    <a href="#dontGoHere" ng-click="doSomething(); $event.preventDefault()">Do Something</a>

個人的には、後者よりも前者を好む。ここで説明するjavascript:void(0)他の利点があります。また、そのリンクには恐ろしいほど最近のものであり、必ずしも角度のあるアプリケーションに直接適用されるわけではない「無邪気なJavaScript」についての議論もあります。


2
なぜこれが反対投票されたのですか?また、クリスからの回答ではポインターが表示されないことにも気付きました。
Wim Deblauwe 2014

2
javascript:void(0)は、誤って構成した場合にルートで動作する#よりもはるかに優れています。+1
シェイエルカヤム2014

2
これに対する答えを書こうとしていたところです。次のこともできますjavascript:;
エイドリアン

10

次のようにすることができます

1. hrefanchor(a)タグから属性を削除する

2.CSSのポインタカーソルをng要素に設定する

 [ng-click],
 [data-ng-click],
 [x-ng-click] {
     cursor: pointer;
 }

9

HTML

ここで純粋なangularjs:ng-click関数の近くにセミコロンを区切ることでpreventDefault()関数を書くことができます

<a href="#" ng-click="do(); $event.preventDefault(); $event.stopPropagation();">Click me</a>

JS

$scope.do = function() {
    alert("do here anything..");
}

(または)

あなたはこの方法で進めることができます、これはすでにここでいくつか議論されています。

HTML

<a href="#" ng-click="do()">Click me</a>

JS

$scope.do = function(event) {
    event.preventDefault();
    event.stopPropagation()
}

7

私が見ることができるこのオプションを試してくださいまだ上にリストされていません:

<a href="" ng-click="do()">Click</a>

6

Webアプリを作成しているのに、なぜリンクが必要なのですか?

アンカーをボタンに交換してください!

<button ng-click="do()"></button>

2
ウェンはwebappsにアンカーを持つことができないので?
ロビンファンバーレン2014

1
私が言及したのは、ほとんどのWebアプリはWebサイトのように相対リンクを必要とせず、JavaScriptトリガーとしてアンカーリンクを使用するだけで、ページにリンクしないことです。したがって、デフォルトのスタイルがリセットされたボタンは、意味論的には正確ではなくても同じです。
sidonaldson 2014

3
@sidonaldson実際、今日の多くのWebアプリはリンクに大きく依存しています。angularjsルーティングを見てください。
ロバート

1
@Robertはい、ただし組み込みのルーティングを使用する場合、デフォルトの防止を管理する必要はありません。私はポスターがアンカールートをキャンセルしたいので、彼は非ルートリンクについて話していると思います。たとえば、モーダルなどの起動
sidonaldson '22年

2
この回答にはもっと多くの賛成票があるはずです。多くの場合、デフォルトのアンカー動作を防止したい場合は、アンカーをリンクではなくボタンとして使用しています。
ItCosmo、2015年

6

それでも関連がある場合:

<a ng-click="unselect($event)" />

...

scope.unselect = function( event ) {
 event.preventDefault();
 event.stopPropagation();
}

...

6

hrefでイベントを回避する最も安全な方法は、hrefを次のように定義することです。

<a href="javascript:void(0)" ....>

5

私は一緒に行きます:

<a ng-click="do()">Click</a>
  • ドキュメントによると、hrefを離れることができ、Angularがデフォルトの防止を処理するためです!

これがデフォルトを防ぐことは私を混乱させてきたので 、Angularがいつデフォルトを妨げているのかを示すJSFiddleを作成しました

JSFiddleはAngularのディレクティブを使用しているため、まったく同じである必要があります。ここでソースコードを見ることができます:タグのソースコード

これが一部の説明に役立つことを願っています。

ドキュメントをngHrefに投稿したかったのですが、自分の評判が悪かったのでできません。


5

これは私がいつもしていることです。魅力的な作品!

<a href ng-click="do()">Click</a>

4

または、インラインが必要な場合は、これを行うことができます:

<a href="#" ng-click="show = !show; $event.preventDefault()">Click to show</a>

4

多くの答えはやり過ぎのようです。私にとって、これは機能します

 <a ng-href="#" ng-click="$event.preventDefault();vm.questionContainer($index)">{{question.Verbiage}}</a>

2

(jsがオフになっている場合)低下のためにhref属性の値の存在が必要なため、空のhref属性(または「#」)を使用できませんが、イベントが必要なため、上記のコードは機能しません( e)変数。私は自分のディレクティブを作成しました:

angular.module('MyApp').directive('clickPrevent', function() {
  return function(scope, element, attrs) {
    return element.on('click', function(e) {
      return e.preventDefault();
    });
  };
});

HTML:

<a data-click-prevent="true" href="/users/sign_up" ng-click="openSignUpModal()">Sign up</a>

2

テニスジェントの答えから借りる。すべてのリンクを追加するためにカスタムディレクティブを作成する必要がないことが好きです。しかし、IE8で彼を働かせることはできませんでした。これが私にとって最終的に機能したものです(angular 1.0.6を使用)。

'bind'を使用すると、angularによって提供されるjqLit​​eを使用できるため、完全なjQueryでラップする必要がないことに注意してください。また、stopPropogationメソッドも必要です。

.directive('a', [
    function() {
        return {
            restrict: 'E',
            link: function(scope, elem, attrs) {

                elem.bind('click', function(e){
                    if (attrs.ngClick || attrs.href === '' || attrs.href == '#'){
                        e.preventDefault();
                        e.stopPropagation();
                    }
                })
            }
        };
    }
])

3
これは多くの人を殺します。たとえば、Twitter Bootstrapを使用する場合dropdown、デフォルトの動作ではなく伝播が必要です。このスニペットは推奨されません
ロビンファンバーレン2014

2

角度付きブートストラップドロップダウンにアンカーを使用すると、この同じ問題が発生しました。不要な副作用(つまり、preventDefault()を使用したためにドロップダウンが閉じない)を回避できることがわかった唯一の解決策は、以下を使用することでした。

 <a href="javascript:;" ng-click="do()">Click</a>

2

決してhrefに移動したくない場合は、マークアップを変更して、アンカータグではなくボタンを使用する必要があります。これは、意味的にはアンカーまたはリンクではないためです。逆に、いくつかのチェックを行ってからリダイレクトするボタンがある場合、それはボタンではなくリンク/アンカータグである必要があります... SEOの目的および[ここにテストスイートを挿入]の目的で。

変更を保存するか、ダーティな状態を確認するかなど、条件付きでリダイレクトするリンクの場合は、ng-click = "someFunction($ event)"およびsomeFunctionでvalidationError preventDefaultおよび/またはstopPropagationを使用する必要があります。

また、あなたができるからといって。javascript:void(0)はその日はうまく機能しました...しかし、悪意のあるハッカー/クラッカーのブラウザが、href内でjavascriptを使用するアプリ/サイトにフラグを立てるので、上記のducktypeの理由はありません。

ボタンのように機能するリンクを使用する理由は2010年以来2016年です... IE8以下をサポートする必要がある場合は、ビジネスの場所を再評価する必要があります。


1
/* NG CLICK PREVENT DEFAULT */

app.directive('ngClick', function () {
    return {
        link: function (scope, element, attributes) {
            element.click(function (event) {
                event.preventDefault();
                event.stopPropagation();
            });
        }
    };
});

1

あなたがすべきことは、href属性を完全に省略することです。

elementディレクティブ(Angularコアの一部)のソースコードを見ると、29〜31行目に次のように記述されていaます。

if (!element.attr(href)) {
    event.preventDefault();
}

これは、Angularが既にhrefなしでリンクの問題を解決していることを意味します。あなたがまだ持っている唯一の問題はCSSの問題です。ng-clicksのあるアンカーには、引き続きポインタスタイルを適用できます。例:

a[ng-click] {
    /* Styles for anchors without href but WITH ng-click */
    cursor: pointer;
}

したがって、実際のリンクを、機能を実行するリンクよりも微妙な異なるスタイルでマークすることで、サイトをよりアクセスしやすくすることもできます。

幸せなコーディング!


1

$ locationのHtml5Mode内でURLリダイレクトを無効にして、目的を達成できます。ページに使用される特定のコントローラ内で定義できます。このようなもの:

app.config(['$locationProvider', function ($locationProvider) {
    $locationProvider.html5Mode({
        enabled: true,
        rewriteLinks: false,
        requireBase: false
    });
}]);


1

Angular 8以上を使用している場合、ディレクティブを作成できます:

import { Directive, HostListener } from '@angular/core';

@Directive({
  selector: '[preventDefault]'
})
export class PreventDefaultDirective {

  @HostListener("click", ["$event"])
  public onClick(event: any): void
  {
    console.log('click');
    debugger;
      event.preventDefault();
  }

}

コンポーネントのアンカータグで、次のように配線できます。

  <a ngbDropdownToggle preventDefault class="nav-link dropdown-toggle" href="#" aria-expanded="false" aria-haspopup="true" id="nav-dropdown-2">Pages</a>

アプリモジュールには宣言が必要です。

import { PreventDefaultDirective } from './shared/directives/preventdefault.directive';


@NgModule({
  declarations: [
    AppComponent,
    PreventDefaultDirective

-1

代替案は次のとおりです。

<span ng-click="do()">Click</span>

1
spanクリック目的でaを悪用するのは恐ろしい習慣です。@tennisgentの答えにただ進んでください- href定義されていないアンカーです。
ロビンファンバーレン2014

1
@RobinvanBaalen span要素は、少なくともHTML 4.0.1:w3.org/TR/html401/struct/global.html#edef-SPAN w3.org/TR/html5/dom.html#global-attributes 以降、クリック可能として定義されています。 html.spec.whatwg.org/multipage/dom.html#global-attributes
Terence Bandoian、2015年

1
<span>こんにちは</ span>をクリックすると、いつクリックできるようになりますか?仕様ではおそらく、<span>は<a>や<button>などのクリック可能な要素内で使用できるということです。ただし、この場合も、すべてのインラインブロック要素(img、spanなど)をクリック可能にすることができます。スパン自体はクリックできません。
Robin van Baalen、2015年

1
@RobinvanBaalen上記のリンクをご覧ください。span要素のonclick属性は、少なくともHTML 4.01以降で定義されています。
Terence Bandoian、2015年

1
イベントハンドラーを追加しても、スパンが機能しないとは言いませんでした。私は、span、div、section、ul、liなどのクリックできない要素をJavaScriptイベントハンドラーを使用してクリック可能にすることは悪い習慣だと述べました。それはすべて意味論についてです。HTML内のセマンティクスは、適切な要素を使用してページのコンテンツに意味と構造を与えることです。
Robin van Baalen、2015年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.