Как предотвратить дефолт на якорных тегах?


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

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

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

26 331

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 атрибут из якоря (a) тег

2.Установить курсор в CSS к НГ элементами

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

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>

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

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

<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, а затем угловой будет обрабатывать предотвратить по умолчанию для вас!

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

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

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

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

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

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

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

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

или, если вам нужен встроенный, то можно сделать так:

<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 (или "#"), но приведенный выше код не работает для меня, потому что мне нужна переменная event (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 для достижения цели. Вы можете определить его внутри конкретного контроллера, используемого для страницы. Что-то вроде этого:

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

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

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