Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pass a variable to an abstract parent state using the ui-sref directive with ui-router

I am setting up a simple angularjs app that manages groups, in which I use ui-router for nested routing.

var groupsApp = angular.module('groupsApp', [
    'ui.router',
]);

Each group has participants and a program. The page /#/groups shows a list with links to each group using the ui-sref directive:

<ul>
    <li ng-repeat="group in groups">
        <a ui-sref="group.participants({group_id: {{group.id}}})">{{group.name}}</a>
    </li>
</ul>

State navigation is configured as follows:

groupsApp.config(
    function($stateProvider) {

        $stateProvider
            .state('groups', {
                url: '/groups',
                templateUrl: 'partials/groups.html'
            })
            .state('group', {
                abstract: true,
                url: '/:group_id',
                templateUrl: 'partials/group.html',
            })
            .state('group.participants', {
                url: '/participants',
                templateUrl: 'partials/participants.html',
            })
            .state('group.programm', {
                url: '/programm',
                templateUrl: 'partials/program.html'
            })
    });

And I use the following controller:

var myAppControllers = angular.module('myAppControllers', []);

myAppControllers.controller('GroupController', ['$scope', 
  function ($scope) {

    $scope.groups = [
      {'id': 'group1',
       'name': 'My first group',
      {'id': 'group2',
       'name': 'My secord group',
    ];

  }]);

The group state is abstract, the group_id determines the url. For groups with id's group1 and group2, the possible url's are:

/#/group1/participants
/#/group1/program

/#/group2/participants
/#/group2/program

With the ui-sref directive I want to navigate to the participants page of a group:

<a ui-sref="group.participants({group_id: {{group.id}}})">{{group.name}}</a>

Therefore I navigate to the group.participants state and pass along the group_id parameter to indicate for which group. However this is a parameter of the parent state group. Clicking the link results in the following url:

/#//participants

Apparently the parent class group does not get this parameter. Does anyone has an idea how this could be achieved?

p.s. I now realize that maybe the problem is the nesting of the angular expressions:

{group_id: {{group.id}}}

Is this allowed?

like image 215
Bastiaan van den Berg Avatar asked May 17 '14 13:05

Bastiaan van den Berg


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.

Which ui router directive allows you to create links connecting to your states?

Angular UI Router consists of a 'stateProvider' method that can be used to create a route or a state in an application. The 'stateProvider' function takes the name of the state and the configurations of the state as its parameter.

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.

What is ui router?

UI-Router is the defacto standard for routing in AngularJS. Influenced by the core angular router $route and the Ember Router, UI-Router has become the standard choice for routing non-trivial apps in AngularJS (1. x).


1 Answers

I created a plunker which is working and should follow your needs: here

One of the changes:

<ul>
   <li ng-repeat="group in groups">
      <!--
      <a ui-sref="group.participants({group_id: {{group.id}}})">{{group.name}}</a>
      -->
      <a ui-sref="group.participants({group_id: group.id})">{{group.name}}</a> 
   </li>
</ul>

And also the snippet of the state definitions (in fact the same as in the question, but running)

the groups defintion:

$stateProvider
    .state('groups', {
      url: '/groups',
      template: '<ul> ' +
      '    <li ng-repeat="group in groups"> ' + 
      '     <a ui-sref="group.participants({group_id: group.id})">' +
      '        {{group.name}}</a> ' +
      '   </li> ' +
      ' </ul>',
      controller:['$scope','$state',
        function ( $scope , $state){ 

          $scope.groups = [{name : "My first group" , id : "group1"}
                         , {name : "My second group", id : "group2"}];

      }],
    })

And here is the group abstract state. It does have access to the $stateParams and stores them in the scope. All child states do have access to it as well.

.state('group', {
    abstract: true,
     url: '/:group_id',
     template: '<div>' +
     '   <h4> group: {{group_id}} <a ui-sref="groups">back</a></h4>' +
     '   <div ui-view></div>' +
     ' </div>',
     controller:['$scope','$state','$stateParams',
       function ( $scope , $state , $stateParams){ 
         $scope.group_id = $stateParams.group_id;
         $scope.params = $stateParams;
         $scope.state = $state.current;
         $scope.showJson = function(x) { return JSON.stringify(x, undefined, 2); };
     }],
 })

The child states of the abastract group, can consume what was already prepared for them

 .state('group.participants', {
     url: '/participants',
     template: '<div>' +
     ' <h5>params</h5> ' +
     '   <pre>x{{showJson(params)}}</pre>' +
     ' <h5>state</h5> ' +
     '   <pre>{{showJson(state)}}</pre>' +
     ' </div>',
 })
 .state('group.programm', {
     url: '/programm',
     template: '<div>programm</div>'
 })
 ;
like image 142
Radim Köhler Avatar answered Oct 10 '22 20:10

Radim Köhler