0

On my application I have courses and events. There are two ways of showing events (which is the problematic state here):

One is by accessing this week's events ('events' state):

.state('events.show',
  url: '/events/:eventId'
  views:
    '@':
      templateUrl: '<%= asset_path('events/show.html') %>'
      controller: 'EventCtrl'
  resolve: { event: EventResolver }
)

The other when I select from a list of events scoped to course:

.state('courses.show.event',
  url: '/events/:eventId'
  views:
    '@':
      templateUrl: '<%= asset_path('events/show.html') %>'
      controller: 'EventCtrl'
  resolve: { event: EventResolver }
)

This really looks like a bad practice because of the duplication, but I'm not sure what should I do here instead, as I'd like to keep a "Back" button in the events/show.html template to go back either to the scoped events list in course or back to this week's events depending where the user accessed the resource from.

Is there a better way of keeping the "Back" button going to where I wanted without all this duplication? Should I approach this differently?

Pedro Nascimento
  • 13,136
  • 4
  • 36
  • 64
  • Why not have the `course` page send you to the `events.show` state directly? How is the back button functionality hampered here? Also, take a look at [this SO question](http://stackoverflow.com/questions/22247294/how-do-i-get-the-back-button-to-work-with-an-angularjs-ui-router-state-machine) – javinor Jul 08 '15 at 15:39
  • It is a "Back" button in the `events/show.html` template which currently is taking to `^`, not the browser native button. – Pedro Nascimento Jul 08 '15 at 15:46

1 Answers1

1

If you want to scrap the duplication, you could go with a state object definition.

var eventsState = {
  url: '/events/:eventId'
  views:
    '@':
      templateUrl: '<%= asset_path('events/show.html') %>'
      controller: 'EventCtrl'
  resolve: { event: EventResolver }  
};


$stateProvider
  .state('events.show', eventsState)
  .state('courses.show.event', eventsState)

That would be the path of least resistance as far as I'm concerned, but it's hard to tell what would be the best way to go forward - not having seen the entire state tree.


A back button that would go back to whichever state you came from could be injected into the controller using a resolve property inside the associated view.

views: 
  '@': 
    templateUrl: '....'
    resolve: {
      stateOpener: function ($state) {
        /** 
         * $state does _not_ refer to the $state you transitioned to, 
         * but the $state you came from.
         */
        return $state.current.name;
      }
    },
    controller: function ($scope, $state, stateOpener) {
      $scope.goBack = function () {
        $state.go(stateOpener);
      };
    }

You could also look into ui-router-extras#previousState, that would probably be the cleanest way to have your back button go wherever you came from.

And of course, there is the $window.history way of doing this, but (imho) you should stick to working within the realm of the state machine and not the browser history.