Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to achieve that "ui-sref" be conditionally executed?

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

like image 887
rnrneverdies Avatar asked Sep 01 '14 06:09

rnrneverdies


People also ask

What does ui-sref do?

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.

What is ui-sref active in Angularjs?

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.


1 Answers

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

like image 67
rnrneverdies Avatar answered Sep 19 '22 13:09

rnrneverdies