Back button in mobile app


#1

I am currently working on a mobile app with a navbar like this: http://goratchet.com/components/#bars

I am looking for a solution where I can change according to my current controller the global

  • back button action
  • the title

Due to the usage of liquid-fire it’s important that the nav bar is part of the application template. I am therefore looking for a way to send actions down and a way to set the title variable in my application template.

Thanks in advance for you time and help :smile:


#2

You can use sendAction/action bubbling in the child routes and catch them in the application route. Keep in mind that as this will probably need to be re-architected because the action system is shifting to closure actions instead of bubbling. Currently I don’t know if there is a way to send actions to a parent route using the new closure actions.

You could also use a service to manage the current title and back button functionality. Then you can inject the service where ever you need to using Ember.inject.service or inject the service into all of the routes using an initializer (I don’t know if this changed since applicationInitializers so I can’t give you a link for this one).


#3

I wrestled with this for a bit, and couldn’t come up with a way to keep the navbar in the application template. I made something like a {{nav-bar}} component that I put at the top of each route’s template

{{mobile-subnav title=exercise.name
  leftLink='exercises.index'}}

{{mobile-subnav title='Exercises'
  rightIcon='mdi-content-add'
  rightAction='toggleWillAddExercise'}}

and so on. I wanted to handle actions in the current route, and not have to wire them up elsewhere. I wanted the current route to determine the title of the navbar, which parts of the navbar were showing, etc.

I tried a few things before this:

  • setting a routeMeta property on each route, examining this from a component in application route
  • sending an action from each route up to app route on activate
    • problem is activate doesn’t fire each time, you really need to observe application controller’s currentPath. But then how do you get this to child routes?
    • you could have your navbar component observe this then when it changes, inspect the current route for some metadata. But I couldn’t quite get this working, and it was a super nonstandard architecture.

In the end I couldn’t figure out a good way to do this. If there was a way to “send actions down” that would certainly help, but this is really hard because there are many paths down, but only one path up.

I’m not sure the best way to accomplish this kind of design.


#4

We have a similar feature in our mobile app. We ended up creating a component to which we passed properties that were set in the controller through a mixin. The mixin had these fields as required, so the controller needs to set them. To avoid repeating the same markup to include the component on every route we made it a partial. This is similar to @samselikoff’s idea, just lesser duplicate code.


#5

So, you add mixin to controller, and then controller needs to set certain properties (title etc), and then you render a single partial on each template which renders the nav?


#6

Yep a title and route name to navigate to.


#7

I managed to get this working including navigation in the application template by storing currentRouteName and currentState.routerJsState on the router in the willTransition hook. In the application route I have an action that transitions to the previous route.

  transitionToPrevious() {
      const infosWithContent = this.router.previousState.handlerInfos.filter(info => Object.keys(info.params).length > 0);
      const contexts = infosWithContent.map(info => info.context);
      this.transitionTo.apply(
        this, [this.router.previousRouteName].concat(contexts).concat([{
          queryParams: this.router.previousState.fullQueryParams
        }]));
    }