1

I have a main list page, when click on each post, it leads to a separate page with its own detail. That part of the UI-router works fine.

I also have another page state whereby upon clicking a username (with link on main page as well as each detail page), it should bring user to a profile page of that user based on a userId.

Whats wrong with the codes at the profile state? Ive tried many permutations and even blank '' states as per view@state structures but it always jumps back to the URL.otherwise url. I read up on the github states but and am clear on the rules but somehow I cant seem to figure this out. Does it mean I need 2 states for 2 different links leading to the same profile page view?


html for link to user profile by Id

ng-href="#/users/{{ user.profile.uid }} or

ui-sref="tab.posts/users/{{ user.profile.uid }}".


The app.js states file

    .state('tab', {
      url: '/tab',
      abstract: true,
      templateUrl: 'templates/tabs.html'
    })

    .state('tab.posts', {
      url: '/posts',
      views: {
        'tab-posts': {
          templateUrl: 'templates/tab-posts.html',
          controller: 'PostsCtrl'
        }
      }
    })

    .state('tab.posts.view', {
      url: '/:postId',     
      views: {
        'tab-posts@tab':{    
          templateUrl: 'templates/tab-showpost.html',
          controller: 'PostViewCtrl'
        }
      }
    })

    .state('tab.profile', {
      url: '/users/:userId',    //tried url = '/:userId', doesnt work
      views: {
        'tab-posts@tab': {          // tried many permutations here too   
          templateUrl: 'templates/profile.html',
          controller: 'ProfileCtrl'
        }
      }
    });

  $urlRouterProvider.otherwise('auth');
});
Thinkerer
  • 1,606
  • 6
  • 23
  • 43

2 Answers2

1

This should be the proper anchors:

The href:

// instead fo this
// ng-href="#/users/{{ user.profile.uid }}
// we need parent url as well
<a href="#/tab/users/{{ user.profile.uid }}" >

The ui-sref:

// this is wrong
// ui-sref="tab.posts/users/{{ user.profile.uid }}"
// it should be almost like $state.go()
<a ui-sref="tab.profile({ userId: user.profile.uid })" >

why these adjustments?

state tab.profile does inherit from parent tab. So it must include its url in the first case

In the second, we use ui-sref the way like this: stateName({param1:value1, param2:value2})

See

ui-sref

A directive that binds a link ( tag) to a state. If the state has an associated URL, the directive will automatically generate & update the href attribute via the $state.href() method. Clicking the link will trigger a state transition with optional parameters. Also middle-clicking, right-clicking, and ctrl-clicking on the link will be handled natively by the browser.

Usage:

  • ui-sref='stateName' - Navigate to state, no params. 'stateName' can be any valid absolute or relative state, following the same syntax rules as $state.go()
  • ui-sref='stateName({param: value, param: value})' - Navigate to state, with params.

Maybe also check this Q & A

Community
  • 1
  • 1
Radim Köhler
  • 122,561
  • 47
  • 239
  • 335
  • thanks! your fast in replying! I did try those combinations, including removing /users/ from the view. Still doesnt work, and it doesnt show up in dev tools! – Thinkerer Dec 06 '14 at 09:42
  • Do you have some plunker? just very simple draft.. I can quickly fix it.. and show what is wrong. In general, my answer really should be the way... – Radim Köhler Dec 06 '14 at 09:43
  • just to confirm, the view should also be tab-posts@tab as well right? I have a plunker but its not working yet, trying to tie it all together. – Thinkerer Dec 06 '14 at 09:44
  • Well, the **tab** is parent of tab.profile, so it could be just 'tab-posts'. But 'tab-posts@tab' is also ok. What is a real MUST - the **templateUrl: 'templates/tabs.html'** must contain `ui-view="tab-posts"` – Radim Köhler Dec 06 '14 at 09:46
  • I attached the plunk above. However the post submission isnt working (says post is not defined in post.title.) Also the userid part is quite massive and ties in with an external database which I havent figured how to simplify here. – Thinkerer Dec 06 '14 at 10:59
  • I adjusted your draft, it is now working. I had to append different answer with more details – Radim Köhler Dec 06 '14 at 16:12
1

Based on this not-wroking plunker, I decided to create new answer and describe how to fix it.

This is how I can call navigation to states tab.profile

The ui-sref

<div class="row" ng-repeat="(userId, user) in users">            
  <a ui-sref="tab.profile({userId: userId})">...</a>      
</div>

The href

<div class="row" ng-repeat="(userId, user) in users">            
  <a href="#/tab/users/{{userId}}">...</a>
</div>

The state definition is mostly chnaged in the state tab.profile and its 'tab-posts@profile' view defintion where I had to use 'tab-posts' to target parent === tab

.state('tab', {
  url: '/tab',
  abstract: true,
  templateUrl: 'tabs.html'
})
.state('tab.posts', {
  url: '/posts',
  views: {
    'tab-posts': {
      templateUrl: 'tab-posts.html',
      controller: 'PostCtrl'
    }
  }
})    
.state('tab.view', { //'tab.posts.view' in local devt
  url: '/posts/:postId',  // /:postId in local devt   
  views: {
    'tab-posts@tab':{  
      templateUrl: 'tab-showpost.html',
      controller: 'PostViewCtrl'
    }
  }
})    
.state('tab.profile', {
  url: '/users/:userId', 
  views: {
    //'tab-posts@profile': { // CORE CHANGE! this must be replaced
    'tab-posts': {           // by this
      templateUrl: 'tab-profile.html',
      controller: 'ProfileCtrl'
    }
  }
});

And the otherwise

$urlRouterProvider.otherwise("/tab/posts"); //string in single quotes

There are some other chnages, just check the updated plunker

Radim Köhler
  • 122,561
  • 47
  • 239
  • 335
  • 1
    Thanks Radim, it works now. Now its having an error: `Error: Firebase.child failed: First argument was an invalid path: "null". Paths must be non-empty strings and can't contain ".", "#", "$", "[", or "]"` which has nothing to do with the states. Thanks for your help! – Thinkerer Dec 07 '14 at 03:55