Implementing a “conditional” back button in ember.

2019-03-21 04:25发布

问题:

I am working on an ember.js (version 1.2) based mobile application and I am trying to find the most idiomatic way of implementing the global menu toggle/back button pattern that is common in many mobile apps. Specifically, its a button that sits on the left side of a fixed-top toolbar, which toggles a hidden drawer main menu when the user is at the app's home/index view, however upon moving into a sub route, the button displays a back arrow, and when clicked, it takes the user back to the previously viewed route (or back to the index route if there is no previous history states, i.e. if the user came into a sub route directly upon loading the app).

Fyi, currently I have my app structured with the fixed-top toolbar and menu toggle/back button in the root application template. Ideally this functionality would work no matter how a routes are being transitioned to, whether via transitionTo(), or {{#link-to}} helpers, ect.

So essentially I want to know if Ember internally maintains any sort of accessible history/log of what routes were transitioned to over the course of the app's lifetime, and also what would be the best way to conditionally change the action that the toggle/back button performs and its display (aka its icon) depending on the current route. And/or is there a way to listen to ember's route change events so I could implement that history myself if need be?

回答1:

I hate to be the bearer of bad news, but I also hate to leave you hanging.

Ember doesn't keep track of the history, there isn't a general use case for it (especially since the browser keeps track of it for you).

Fortunately you can monitor route changes in the application controller, something like this should get you started (Note I didn't spend time working out an awesome solution that works perfectly, just showed you the basics you need for it, I'll let you figure out the workflow that works well for you)

http://emberjs.jsbin.com/IZAZemEP/1/edit

App.ApplicationController = Em.Controller.extend({
  history: [],

  hasHistory: function(){
    return this.get('history.length')>1;
  }.property('history.length'),

  watchHistory: function(){
    this.get('history').pushObject(this.get('currentPath'));
  }.observes('currentPath'),

  actions: {
    goBack: function(){
       // implement your own history popping that actually works ;)
       if(this.get('hasHistory')){
         this.get('history').popObject();
         window.history.back(); 
         this.get('history').popObject(); // get rid of route change here, don't need it
       }
     }
   }
 });