web-dev-qa-db-ja.com

アンカータグのデフォルトを防ぐ方法

次のようなアンカータグがあるとしましょう。

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

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

337
Micael

_ update _ :私はこの解決策について私の考えを変えました。もっと多くの開発とこれに取り組む時間を費やした後、私はこの問題に対するより良い解決策が以下をすることであると信じます:

<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アプリケーションで使用しています。

253
tennisgent

NgHrefの docsによると あなたは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 />
319
Chris

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

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

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

私は ディレクティブ を使うのが好きです。これが例です

<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オブジェクトをスタブアウトする必要がないので、あなたのコントローラはより単体テスト可能です。
109
djsmith

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

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

私は個人的にあなたがまたいくつかの副作用を避けるためにいくつかのケースで$ event.stopPropagation()が必要であることを見つけました

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

私の解決策になります

52
zainengineer
ng-click="$event.preventDefault()"
33
The Whiz of Oz

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

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

それで、これらの答えを読んで、@クリスはまだ最も「正しい」答えを持っている、と私は思いますが、それは一つの問題を抱えています、それは「ポインター」を表示しません…….

それで、カーソルを追加する必要なしにこの問題を解決する2つの方法があります:ポインタスタイル:

  1. #の代わりにjavascript:void(0)を使用してください。

    <a href="javascript:void(0)" ng-click="doSomething()">Do Something</a>
    
  2. ng-clickディレクティブで$event.preventDefault()を使用してください。

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

個人的には後者よりも前者の方が好きです。 javascript:void(0)には他にも、 ここで説明した という利点があります。そのリンクには「目立たないJavaScript」という議論もありますが、これは非常に最近のことで、必ずしも角度のあるアプリケーションには直接当てはまりません。

10
Ben Lesh

あなたは次のようにすることができます

1.アンカー(href)タグからa属性を削除

2.クリック要素にcssでポインタカーソルを設定

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

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()
}

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

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

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

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

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

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

...

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

...
5
xac

あなたはWebアプリを作っているので、なぜあなたはリンクを必要としますか?

アンカーをボタンに交換しましょう!

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

これは私がいつもすることです。魅力のように動作します!

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

私は一緒に行きます:

<a ng-click="do()">Click</a>
  • なぜなら、ドキュメントによれば、hrefの後に Angular を残すことができるはずだからです。

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

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

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

私はそのドキュメントをngHrefに投稿したいと思いましたが、評判が悪いのでできません。

4
martinmose

インラインが必要な場合は、次のようにします。

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

たくさんの答えがやり過ぎるようです。私のために、これは働きます

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

(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>
1
focused

もしhrefに行きたくないのなら...意味的にはアンカーやリンクではないので、マークアップを変更してアンカータグではなくボタンを使うべきです。逆に、チェックをしてからリダイレクトするボタンがある場合、それはボタンではなくリンク/アンカータグであるべきです... SEOの目的やテストのために[ここにテストスイートを挿入]。

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

また あなたができるという理由だけであなたがそうすべきではないという理由で 。 javascript:void(0)は当時はうまく機能していました...しかし、悪意のあるハッカーやクラッカーのブラウザは、href内でjavascriptを使用するアプリやサイトにフラグを立てています。

2010年以降の2016年は、ボタンのように機能するリンクを使用する理由がどこにもないはずです。それでもIE8以下をサポートする必要がある場合は、事業所を再評価する必要があります。

1
PDA

テニスの答えから借りた。私はあなたがすべてのリンクを追加するためにカスタムディレクティブを作成する必要がないのが好きです。しかし、私は彼を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();
                    }
                })
            }
        };
    }
])
1
Lukus

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

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

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

app.config(['$locationProvider', function ($locationProvider) {
    $locationProvider.html5Mode({
        enabled: true,
        rewriteLinks: false,
        requireBase: false
    });
}]);
0
Dash
/* NG CLICK PREVENT DEFAULT */

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

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

ソースコード を見ればa elementディレクティブ(これはAngular coreの一部です)のために、29 - 31行目で述べています。

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

これはAngularがhrefなしでリンクの問題をすでに解決していることを意味します。あなたがまだ持っている唯一の問題はcss問題です。それでも、クリックスタイルのアンカーにポインタスタイルを適用することができます。

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

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

ハッピーコーディング!

0
Justus Romijn