Как preventDefault на якорных тегах?

предположим, у меня есть якорный тег, такой как

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

Как я могу запретить браузеру переходить к # in AngularJS ?

26 ответов


обновление: С тех пор я изменил свое мнение об этом решении. После большего развития и времени, потраченного на это, я считаю, что лучшее решение этой проблемы-сделать следующее:

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


по словам документы для 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 />

вы можете передать объект $event в свой метод и вызвать $event.preventDefault() на нем, так что обработка по умолчанию не произойдет:

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

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

Я предпочитаю использовать директивы для такого рода вещей. Вот пример

<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 объект в код

хотя Рено дал отличное решение

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

Я лично обнаружил, что вам также нужно $ event.stopPropagation () в некоторых случаях, чтобы избежать некоторых побочных эффектов

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

будет моим решением


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

самое простое решение я нашел это :

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

Итак, читая эти ответы, @Chris все еще имеет самый "правильный" ответ, я полагаю, но у него есть одна проблема, он не показывает "указатель"....

Итак, вот два способа решить эту проблему без необходимости добавлять курсор: стиль указателя:

  1. использовать javascript:void(0) вместо #:

    <a href="javascript:void(0)" ng-click="doSomething()">Do Something</a>
    
  2. использовать $event.preventDefault() на ng-click директива (так что вы не мусорите свой контроллер с DOM-related литература):

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

лично я предпочитаю первое последнему. javascript:void(0) имеет другие преимущества, которые здесь обсуждается. Существует также обсуждение "ненавязчивого JavaScript" в этой ссылке, которая пугающе недавняя и не обязательно напрямую применяется к угловому приложению.


вы можете сделать следующее

1.Удалить href атрибут из anchor (a) tag

2.Установите курсор указателя в css на ng click elements

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

HTML-код

здесь pure 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>

поскольку вы делаете веб-приложение, зачем вам ссылки?

поменять якоря на кнопки!

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

если все еще актуально:

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

...

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

...

Я бы пошел с:

<a ng-click="do()">Click</a>
  • потому что в соответствии с документами вы должны иметь возможность оставить href, а затем Angular будет обрабатывать предотвращение по умолчанию для вас!

вся эта вещь предотвращения по умолчанию сбивает меня с толку, поэтому Я создал JSFiddle там иллюстрируют, когда и где Angular предотвращает default.

JSFiddle использует директиву Angular - поэтому она должна быть точно такой же. Вы можете увидеть исходный код здесь: исходный код тега

Я надеюсь, что это поможет прояснить для некоторых.

Я хотел бы опубликовать документ в ngHref, но я не могу из-за моей репутации.


Это то, что я всегда делаю. Работает как шарм!

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

самый безопасный способ избежать событий на href-определить его как

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

или если вам нужен inline, то вы можете сделать это:

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

многие ответы кажутся излишними. Для меня это работает

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

мне нужно наличие значения атрибута 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>

заимствование из ответа теннисджента. Мне нравится, что вам не нужно создавать пользовательскую директиву для добавления всех ссылок. Однако, я не мог заставить его работать в IE8. Вот что, наконец, сработало для меня (используя angular 1.0.6).

обратите внимание, что "bind" позволяет использовать jqLite, предоставляемый angular, поэтому нет необходимости обертывать полный 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();
                    }
                })
            }
        };
    }
])

я столкнулся с этой же проблемой при использовании якорей для углового загрузочного раскрывающегося списка. Единственное решение, которое я нашел, чтобы избежать нежелательных побочных эффектов (т. е. раскрывающийся список не закрывается из-за использования preventDefault()) должен был использовать следующее:

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

Если вы никогда не хотите идти в href... вы должны изменить разметку и использовать кнопку, а не тег привязки, потому что семантически это не привязка или ссылка. Наоборот, если у вас есть кнопка, которая выполняет некоторые проверки, а затем перенаправляет, она должна быть тегом ссылки / якоря, а не Кнопкой... для SEO целей тестирования [здесь вставить тестов].

для ссылок, которые вы только хотите перенаправить условно, как приглашение сохранить изменения или признать грязное состояние... вы должны использовать ng-click= " someFunction ($event)" и в someFunction на вашем validationError preventDefault и / или stopPropagation.

и просто потому, что вы можете не означает, что вы должны. javascript: void (0) хорошо работал в тот день... но из-за гнусных хакеров/взломщиков браузеры флаг приложений/сайтов, которые используют javascript в href... не вижу причин для ducktype выше..

Это 2016 с 2010 года должно быть никаких причин, что бы использовать ссылки, которые действуют как кнопки... если вам все еще нужно поддерживать IE8 и ниже, вам нужно переоценить свое место работы.


/* NG CLICK PREVENT DEFAULT */

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

что вы должны сделать, это опустить


вы можете отключить перенаправление url внутри Html5Mode $location для достижения цели. Вы можете определить его внутри конкретного контроллера, используемого для страницы. Что-то вроде этого:--2-->

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

альтернативой может быть:

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