앵커 태그에서 기본값을 방지하는 방법은 무엇입니까?


342

다음과 같은 앵커 태그가 있다고 가정 해 봅시다.

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

AngularJS 에서 브라우저가 #으로 이동하지 못하게하려면 어떻게 해야합니까?


14
Chris가 아래에 말한 것처럼을 제외하십시오 href.
Jesse

13
제시 href=''는 마우스 포인터 동작을 유지하기 위해 사용 하는 것이 아닙니다 .
oma

1
href에서 # 기호를 제거하면 괜찮습니다.
HENG Vongkol

4
또는 href = "javascript : void (0);"를 사용하십시오. 포인터를 유지하지만 동작이 없음 (다른 클릭 핸들러를 추가 할 때까지)
Robba

1
- 당신은 대부분의 크리스 하나 선정 최고의로 변경 허용 대답하시기 바랍니다 수 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

1
다른 답변에서 언급했듯이 공백 href속성은 브라우저마다 다르게 작동합니다. 나는 그것이 가장 깨끗하고 가장 효율적인 솔루션이라는 데 동의하지만 브라우저 간 문제가 있습니다. 지시어 접근 방식을 사용하면 브라우저가 <a>평소와 같이 태그 를 처리 할 수 있지만 여전히 원하는 답을 OP에 표시 할 수 있습니다.
tennisgent

2
이것은 매우 간단한 문제로 심각하게 과도하게 작동합니다. Angular를 사용하면 $ event로 이벤트 객체에 액세스 할 수 있으므로 일반 js 또는 jquery 클릭 이벤트에서 수행 할 작업을 정확하게 수행 할 수 있습니다. 이 답변을보십시오 stackoverflow.com/a/19240232/1826354 그리고 그것에 대한 내 의견
Charlie Martin

1
네. 할 수 있습니다. 이 게시물에는 이미 설명하고있는 다른 두 가지 답변이 있습니다. 그리고 나는 동의합니다. 그것은 과잉입니다. 그래서 업데이트를 한 것입니다.
tennisgent

6
사이트의 접근성 에 신경 쓰지 않으면 괜찮습니다 . href를 생략하면 키보드를 사용하여 해당 항목을 탭할 수 없습니다. tabindex를 추가하지 않은 경우 모든 것을 염두에두고, preventDefault를 사용하지 않는 이유는 무엇입니까? 그것이 거기에있는 것입니다.
duhseekoh

319

ngHref문서에 따르면 href 또는 do 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을 또는 기본 이벤트를 감동 필요 아무거나는 의문이다
빈센트

4
이것이 정답입니다. <a> 속성에서 href를 삭제하면 AngularJS는 기본값 방지를 호출합니다.
pkozlowski.opensource

25
href 속성을 제거하는 유일한 단점은 링크를 가리킬 때 정상적인 '포인터'커서를 잃는다는 것입니다. 스타일 시트에 규칙을 추가하여이 문제를 해결할 수 있습니다. a : hover {cursor : pointer; }
karlgold

35
또한 태그를 탭할 수 없게되므로 접근하기가 쉽지 않습니다.
Richard Szalay

3
나를 위해 브라우저는 여전히 클릭 동작을 버블 링합니다 : /
Matej

238

기본 이벤트 $event.preventDefault()가 발생하지 않도록 $ event 객체를 메소드에 전달하고 호출 할 수 있습니다.

<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

1
작성된 시점에 href를 비워 두거나 IE8 / 9 및 Opera 에서 href를 비워 두지 않았습니다 . 이것은 1 년 전이며 다시 시도 할 기회가 없었습니다 (Github에서 문제를 다시 열었지만 몇 시간 전에 문제를 재설정했다고 생각합니다). 이것이 고정되어 있거나 브라우저에 신경 쓰지 않는다면 반드시 Chris의 대답을 사용하십시오! 누군가가 그것을 시도하고 답변을 주석 / 편집 할 수 있다면 더 좋습니다.
mna

1
@PuerkitoBio-IE8 이하에서는 여전히 $event.preventDefault()IE 세금이 필요하다는 것을 확인할 수 있습니다 .
Scotty.NET

4
$ event를 컨트롤러에 전달한다는 것은 컨트롤러에서 DOM을 참조한다는 것을 의미합니다. 이는 뷰와 컨트롤러를 결합한 것을 의미합니다. 평가 된 표현식에서 $ event 메소드를 직접 호출 할 수 있습니다. ng-click="do(); $event.preventDefault()예를 들어, 아래의 @Chris의 답변이 올바른 것이기 때문에 필요하지는 않습니다. $event.stopPropagation()그러나 ngClick이 중첩되어 있고을 호출하려는 상황에있는 사람들에게 도움이 될 수 있습니다 .
Ben Lesh

2
마지막으로 SEO 친화적 인 솔루션. ng-view-joelsaupe.com/programming / ... 을 다시로드하지 않고 브라우저 URL을 업데이트 할 수도 있습니다. 이렇게하면 뷰를 다시로드하지 않지만 새 탭에서 열 수 있고 검색 엔진이이를 따라갈 수있는 링크가 있습니다. 예!
Tom

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 자체 세트를 제공합니다.
Neil

3
추가 이점 -이것은 중요한 경우 IE8 이하 에서도 작동 합니다.
Scotty.NET

1
나는 받고있다 Error: $ is not defined. 내가 무엇을 놓치고 있습니까?
Bilal Mirza

7
나는 노력했다 angular.element(element).bind('click', function(event){...});. 효과가있었습니다. 참조 : jQLite
Bilal Mirza

3
만약 당신이 저에게 물어 보면 그와 같은 간단한 것에 대한 지시어가 약간 부풀어 오른 것 같습니다 ... Chris에게 아래의 대답을 확인하십시오
Wilt

54

Renaud는 훌륭한 솔루션을 제공했지만

<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 객체를 스코프 함수로 전달할 수도 있습니다. ng-click = "myFunction ($ event, otherParams), 그런 다음 myFunction의 $ event.preventDefault ()와 같이 직접 지시어를 롤링하는 것은 너무 과도합니다
Charlie Martin

34

내가 찾은 가장 쉬운 해결책은 다음과 같습니다.

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

이것은 가장 쉬운 방법 일뿐만 아니라 다른 솔루션에서 제안한 것처럼 이벤트를 컨트롤러와 연결하지도 않습니다. 컨트롤러에 이벤트를 연결하는 것은 테스트를 훨씬 어렵게하기 때문에 모든 비용을 피해야합니다.
jornare

11

따라서 @Chris는이 답변을 통해 여전히 가장 "올바른"답변을 가지고 있다고 생각하지만 한 가지 문제가 있지만 "포인터"를 표시하지 않습니다 ....

따라서 커서를 추가하지 않고도이 문제를 해결하는 두 가지 방법이 있습니다. 포인터 스타일 :

  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)설명 된 다른 이점이 있습니다 . 그 링크에는 "최소한의 자바 스크립트"에 대한 토론도 있습니다.이 링크는 매우 최근에 이루어졌으며 반드시 각도 응용 프로그램에 직접 적용되지는 않습니다.


2
이것이 왜 다운 보트입니까? 또한 Chris의 답변에 포인터가 표시되지 않는 것으로 나타났습니다.
Wim Deblauwe

2
javascript : void (0)은 경로를 잘못 구성하면 경로에서 작동 할 수있는 #보다 훨씬 낫습니다. +1
Shay Elkayam

2
나는 이것에 대한 답을 쓰려고했다. 당신은 또한 할 수 있습니다javascript:;
Adrian

10

다음과 같이 할 수 있습니다

1. hrefanchor ( a) 태그 에서 속성 제거

2. CSS의 포인터 커서를 클릭 요소로 설정하십시오.

 [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

웹앱을 제작하고 있는데 왜 링크가 필요합니까?

앵커를 버튼으로 바꾸십시오!

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

2
webapps에 앵커를 가질 수 없기 때문에?
Robin van Baalen

1
나는 대부분의 웹 응용 프로그램이 웹 사이트와 같은 상대 링크를 필요로하지 않는다는 점을 언급하고 있었고, 종종 앵커 링크를 자바 스크립트 트리거로 사용하고 페이지에 링크하지 않습니다. 따라서 기본 스타일이 재설정 된 버튼은 의미가 맞지 않으면 의미 론적으로 정확합니다.
sidonaldson

3
@sidonaldson 사실, 오늘날 많은 웹앱은 링크에 크게 의존합니다. angularjs 라우팅을보십시오.
Robert

1
@Robert 예. 그러나 기본 제공 라우팅을 사용하면 기본값을 방지 할 필요가 없습니다. 나는 포스터가 그가 루트가 아닌 링크에 대해 이야기하고있는 앵커 링크를 취소하고 싶어한다고 가정합니다. 예를 들어 모달 등 시작
sidonaldson

2
이 답변에는 더 많은 투표가 있어야합니다. 대부분의 경우 기본 앵커 동작을 방지하려면 링크가 아닌 버튼으로 앵커를 사용합니다.
ItsCosmo

6

여전히 관련이있는 경우 :

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

...

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

...

6

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

성능 저하에 대한 href 속성 값이 필요합니다 (js가 꺼져있을 때), 빈 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

tennisgent의 답변에서 차용. 모든 링크에 추가하기 위해 사용자 지정 지시문을 만들 필요는 없습니다. 그러나 IE8에서 그의 일을 할 수 없었습니다. 마지막으로 나를 위해 일한 것이 있습니다 (각도 1.0.6 사용).

'바인드'를 사용하면 각도로 제공되는 jqLite를 사용할 수 있으므로 전체 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전파를 원하지만 기본 동작은 원하지 않습니다. 이 스 니펫은 권장 되지 않습니다.
Robin van Baalen

2

각도 부트 스트랩 드롭 다운에 앵커를 사용할 때도 동일한 문제가 발생했습니다. 원하지 않는 부작용을 피하는 유일한 해결책 (예 : preventDefault () 사용으로 인해 드롭 다운이 닫히지 않음)은 다음을 사용하는 것입니다.

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

2

href로 가고 싶지 않다면 마크 업을 변경하고 의미 상 앵커 또는 링크가 아니기 때문에 앵커 태그가 아닌 버튼을 사용해야합니다. 반대로 검사를 한 다음 리디렉션하는 버튼이 있으면 버튼은 아닌 링크 / 앵커 태그 여야합니다. SEO 목적뿐만 아니라 테스트도 여기 [테스트 스위트 삽입].

변경 사항을 저장하라는 메시지와 같이 조건부로만 리디렉션하거나 더티 상태를 확인하려는 링크의 경우 ng-click = "someFunction ($ event)"및 validationError preventDefault 및 / 또는 stopPropagation에 someFunction을 사용해야합니다.

또한 당신이해야한다는 것을 의미 할 수 없기 때문에 . javascript : void (0)는 하루 전에 잘 작동했지만 악의적 인 해커 / 크래커 브라우저로 인해 href 내에서 javascript를 사용하는 앱 / 사이트에 플래그가 지정되었습니다.

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 속성을 완전히 것입니다.

요소 지시문 (앵귤러 코어의 일부)에 대한 소스 코드 를 보면 a29-31 행에 표시됩니다.

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

이것은 Angular가 이미 href없이 링크 문제를 해결하고 있음을 의미합니다. 여전히 유일한 문제는 CSS 문제입니다. 다음과 같이 ng- 클릭이있는 앵커에 포인터 스타일을 적용 할 수 있습니다.

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클릭 목적으로 악용하는 것은 끔찍한 관행 입니다. @ tennisgent 's answer- href정의 되지 않은 앵커로 이동하십시오 .
Robin van Baalen

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

1
언제 클릭 할 수 있습니까? <span> Hello </ span>를 수행하는 경우 사양에 따르면 <span>은 <a> 또는 <button>과 같은 클릭 가능한 요소 내부에서 사용할 수 있습니다. 그러나 다시 모든 인라인 블록 요소 (img, span 등)를 클릭 방식으로 클릭 할 수 있습니다. 범위 자체는 클릭 할 수 없습니다.
Robin van Baalen

1
@RobinvanBaalen 위의 링크를 참조하십시오. span 요소의 onclick 속성은 HTML 4.01 이상부터 정의되었습니다.
Terence Bandoian

1
이벤트 핸들러를 추가해도 범위가 작동하지 않는다고 말한 적이 없습니다. 자바 스크립트 이벤트 핸들러를 사용하여 span, div, section, ul, li 등과 같은 클릭 할 수없는 요소를 클릭 가능하게 만드는 것은 나쁜 습관이라고 말했습니다. 의미에 관한 모든 것입니다. HTML의 의미는 적절한 요소를 사용하여 페이지 의미와 구조에 내용을 제공하는 방법입니다.
Robin van Baalen
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.