DraganTL
DraganTL

Reputation: 83

Angular ui-router ng-if current exact state

Having trouble managing my parent-child state mostly as I am new to ui-router. However, I've done research and came across solutions that require hard-coding of routes but are not dynamic.

What I currently have:

<div> <!-- parent state -->
    <div ng-if="'.' | isState">
        <!-- 
          background hierarchy that should be visible only when
          parent state is active and not a child state of the parent
        -->
    </div>
    <nav>
        <a ui-sref="." ui-sref-active="active">Parent</a>
        <a ui-sref=".child1" ui-sref-active="active">Child 1</a>
        <a ui-sref=".child2" ui-sref-active="active">Child 2</a>
    </nav>
    <div ui-view></div>
</div>

What I'm trying to accomplish? When the parent loads, I want the background to show something. It takes up the whole screen. The ui-view will not take up the whole screen. As such, I want background element to be hidden or removed when route does not exactly match the parent's state (if parent's route is /root/parent, I want background to be visible only when state is exactly /root/parent and not /root/parent/child1).

I am able to achieve what I want only when I provide the exact expected route. For example ng-if="'root.parent' | isState".

Also, ui-sref-active="active" retains active class when children views are shown (it is expected but I want the class only to be active when the route matches exactly).

However, I do not feel that it is good to hard-code route of the parent into view. I just want it to match whatever route it belongs to. As such, if I later decide to move it to /root/parent/car, I shouldn't have to update ng-if and ui-sref-active to reflect the change.

Has anyone ran into the issue and was able to resolve it?

Upvotes: 3

Views: 4016

Answers (4)

Ferie
Ferie

Reputation: 1436

The simplest solution is checking the state in the controller and do what you need to do

app.controller('appCtrl', function($scope, $state) {
    if ($state.is('my-active-state')) {
        // do stuff when the state is active
    } else {
        // do stuff when the state is NOT active
    }
});

Check the Docs for more info.

Upvotes: 0

DraganTL
DraganTL

Reputation: 83

Thanks for the replies but one of the conditions in a solution I was seeking was to try and avoid hard-coding a state. My solution is as follows:

For the nav links, I had to read the ui-router directive code to find ui-sref-active-eq directive, which I applied in the following way:

<nav>
    <a ui-sref="." ui-sref-active-eq="active">Parent</a>
    <a ui-sref=".child1" ui-sref-active="active">Child 1</a>
    <a ui-sref=".child2" ui-sref-active="active">Child 2</a>
</nav>

The directive ensure that Parent link is active only when the URL is exactly equal to the parent's URL.

As for the showing/hiding the background, I have the following code. Again, note that in neither case do I hard-code a state name:

function ParentController ($scope, $state, $stateParams, $q) {
    var model = this;
    var controllerState = $state.current.name;

    $scope.showBackground = true;

    $scope.$on('$stateChangeSuccess', onStateChange);

    init();

    function init () {
        onStateChange();
    }

    function onStateChange() {
        $scope.showBackground = $state.is(controllerState);
    }
}

And then in the View:

<div ng-if="showBackground">
    <!-- 
      background hierarchy that should be visible only when
      parent state is active and not a child state of the parent
    -->
</div>

Upvotes: 1

Sravan
Sravan

Reputation: 18647

This can be accomplished in few ways, as you might have a parentController separate.

You can check the state in controller and prevent it in view using ng-if

Controller:

app.controller('myCtrl', function($scope,$state) {
     if($state.current.name == 'your parentstate')
        {
          $scope.stateName = true;
        }
     else
        {
          $scope.stateName = false;
        }

});

View:

<div ng-if="stateName">
  // this only executes if current stateName is parent state
</div>

The above only executes if current stateName is parent state

Or,

You can simply remove active class from child routes,

 <a ui-sref=".child1">Child 1</a> 
 <a ui-sref=".child2">Child 2</a>

Now, add CSS to active class so that it only appears in background for parent.

Upvotes: 0

Abdullah Al Noman
Abdullah Al Noman

Reputation: 2878

Use $state.current.name for your condition

<div ng-if="$state.current.name === 'state1'">

</div>

Upvotes: 3

Related Questions