Search code examples
ember.jsember-dataember-old-router

Can `insertNewline` invoke a transitionTo?


Sample code for my question is here. It's a simple Ember app that displays the SearchView containing a TextField by default.

When the user enters some text and hits Enter, I want to transition to another state (displayUserProfile) passing the value entered in the textbox.

At first, in the Textbox's insertNewline callback, I called the transitionTo method of the application's router, passing the value as part of the parameter object:

App.SearchTextFieldView = Em.TextField.extend({
  insertNewline: function() {
    App.router.transitionTo('displayUserProfile', {
      username: this.get('value')
    });
  }
});

That works fine, but then I noticed that pangratz's answer on a question about infinite scrolling, uses a different approach. Instead he invokes a method on the view's controller, which in turn calls a method on the controller's target (which is the router).

This changes my code to:

App.SearchTextFieldView = Em.TextField.extend({
  insertNewline: function() {
    Em.tryInvoke(this.get('controller'), 'displayUserProfile', this.get('value').w());
  }
});

App.SearchController = Em.Object.extend({
  displayUserProfile: function(username) {
    this.get('target').transitionTo('displayUserProfile', {
      username: username
    });
  }
});

My question is: which approach is better? Calling transitionTo directly from the view or delegating it to the view's controller?


Solution

  • I would recommend a different approach. insertNewLine should trigger an action that is handled by the router, which will then transition its state.

    App.SearchTextFieldView = Em.TextField.extend({
      insertNewline: function() {
        this.get('controller.target').send('showUser', {username: this.get('value')});
      }
    });
    
    App.Router = Ember.Router.extend({
      ...
      foo: Ember.Router.extend({
        showUser: function(router, evt) {
          router.transitionTo('displayUserProfile', evt);
        });
      }
    });
    

    You should put the showUser handler at the top-most route where it is valid in your app.

    This approach follows the general pattern of events in Ember apps that views handle DOM-level events and where appropriate, turn them into semantic actions that are handled by the router.