Как предотвратить дефолт на якорных тегах?
допустим, у меня есть якорный тег, такой как
<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()
Эд автоматически.преимущества:
- вы не должны проходить уродливый
$event
объект в код
хотя Рено дал отличное решение
<a href="#" ng-click="do(); $event.preventDefault()">Click</a>
Я лично обнаружил, что вам также нужно $ event.stopPropagation() в некоторых случаях, чтобы избежать некоторых побочных эффектов
<a href="#" ng-click="do(); $event.preventDefault(); $event.stopPropagation();"> Click</a>
будет мое решение
Итак, читая эти ответы, @Chris все еще имеет самый "правильный" ответ, я полагаю, но у него есть одна проблема, он не показывает "указатель"....
Итак, вот два способа решить эту проблему без необходимости добавлять курсор: стиль указателя:
использовать
javascript:void(0)
вместо#
:<a href="javascript:void(0)" ng-click="doSomething()">Do Something</a>
использовать
$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() }
Так как вы делаете веб-приложение, зачем вам нужны ссылки?
замените якоря на кнопки!
<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, но я не могу из-за моей репутации.
самый безопасный способ избежать событий на 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 }); }]);