I want to validate certain condition before the browser follow the link dynamically created by ui-router.
I was looking into $rootscope.$on('$stateChangeStart', ..)
but I have no access to the controller.$scope
from there. I also need to use this in several places in the application and would be cumbersome.
Keep in mind that ui-sref
is linked to ui-sref-active
(work together), so i can't remove ui-sref
and, by say, to use $state.$go('some-state')
inside a function called with ng-click
.
The condition should be evaluated inside a $scope function
and on on-click event
(before-transition with the ability to cancel it)
I need something like this:
<li ui-sref-active="active"> <a ui-sref="somestate" ui-sref-if="model.validate()">Go Somestate</a> </li>
I tried:
<li ui-sref-active="active"> <a ui-sref="somestate" ng-click="$event.preventDefault()">Go Somestate</a> </li> <li ui-sref-active="active"> <a ui-sref="somestate" ng-click="$event.stopImmediatePropagation()">Go Somestate</a> </li>
And
<li ui-sref-active="active"> <a ui-sref="somestate"> <span ng-click="$event.stopPropagation();">Go Somestate</span> </a> </li>
Even
<li ui-sref-active="active"> <a ui-sref="somestate" onclick="return false;">Go Somestate</a> </li>
But does not work.
SANDBOX
A ui-sref is a directive, and behaves similar to an html href . Instead of referencing a url like an href , it references a state. The ui-sref directive automatically builds a href attribute for you ( <a href=...> </a> ) based on your state's url.
ui-sref-active can live on the same element as ui-sref / ui-state , or it can be on a parent element. If a ui-sref-active is a parent to more than one ui-sref / ui-state , it will apply the CSS class when any of the links are active.
This answer inspired me to create a directive that allows me to interrupt the chain of events that end up changing state. For convenience and other uses also prevents the execution of ng-click on the same element.
javascript
module.directive('eatClickIf', ['$parse', '$rootScope', function($parse, $rootScope) { return { // this ensure eatClickIf be compiled before ngClick priority: 100, restrict: 'A', compile: function($element, attr) { var fn = $parse(attr.eatClickIf); return { pre: function link(scope, element) { var eventName = 'click'; element.on(eventName, function(event) { var callback = function() { if (fn(scope, {$event: event})) { // prevents ng-click to be executed event.stopImmediatePropagation(); // prevents href event.preventDefault(); return false; } }; if ($rootScope.$$phase) { scope.$evalAsync(callback); } else { scope.$apply(callback); } }); }, post: function() {} } } } } ]);
html
<li ui-sref-active="active"> <a ui-sref="somestate" eat-click-if="!model.isValid()">Go Somestate</a> </li>
PLUNKER
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With