Skip to content Skip to sidebar Skip to footer

Extending Ember Linkview

Ember.LinkView, the the view class behind the handlebars {{linkTo}} helper is now public in Ember 1.0 RC2. I want to extend it so I can create a custom view without having an extr

Solution 1:

LinkView is intended to be created via a helper, which passes (and provides default values for) some options.

Your error occurs when trying to determine whether your custom class is active or not. You'll need to do one of the following

  • pass or supply the expected default options when using your App.MyLinkView
  • override the active function and implement what you need
  • just pass options to {{linkTo}} for the behavior you want
  • reopen Ember.LinkView to provide the app-wide behavior you'd want

Solution 2:

I needed to do this to override Ember.LinkView's call to transitionTo in order to come up with a solution for jQuery animations between transitions. It seems to me that there are a couple of viable ways to override LinkView. The second one I succeeded with is Trek's last option, and is simpler. This is method #2:

Method #2

{{#linkTo 'items'this eventName="myEvent"}} Link to {{title}} {{/linkTo}}

Now rewrite the app-wide LinkView:

Ember.LinkView.reopen({
  // this handler is still called on click, but// if we specify eventName in our template,// we can call that handler only when we need to,// or not at all
  click: function (e) {
    var evtName = this.get('eventName');

    // transitionTo was already invoked by// this._invoke() if evtName was `click`if (evtName === 'click') return;

    e.preventDefault();

    // do some stuff herevar args = [].slice.call(arguments);
    this.trigger.apply(this, [evtName].concat(args));
  }
});

Method #1

The first method I came up with was to extend Ember.LinkView and create a custom Handlebars helper. The Ember source was really handy here for reading, but I had to override a private method, so I don't think this is really ideal. Here's the implementation. Keep in mind I was trying to control when the View triggered a transitionTo:

{{#appLinkTo 'items'this}} Link to {{title}} {{/appLinkTo}}

Now code it up!

App.LinkView = Ember.LinkView.extend({
  // always called after this.invoke(),// which calls transitionTo
  click: function (e) {
    e.preventDefault();
  },

  // already bound to the click event by this.init().// our click handler above always gets called after this one
  _invoke: function (event) {
    // we need to simulate the old _invoke if we// want to override its call to transitionTo// // https://github.com/emberjs/ember.js/blob/v1.0.0/packages/ember-routing/lib/helpers/link_to.js#L297var isSimpleClick = Ember.ViewUtils.isSimpleClick;
    if (!isSimpleClick(event)) { returntrue; }
    event.preventDefault();
    if (this.bubbles === false) { event.stopPropagation(); }
    if (this.get('_isDisabled')) { returnfalse; }

    if (this.get('loading')) {
      Ember.Logger.warn("This link-to is in an inactive loading state because at least one of its parameters presently has a null/undefined value, or the provided route name is invalid.");
      returnfalse;
    }

    // now we can start messing aroundvar routeArgs = this.get('routeArgs');
    // routeArgs seems to have format ['routeName', models for dynamic segments]this.set('routeArgs', ['group', routeArgs[1]]);

    // if we use:this.get('controller').send('someAction', routeArgs);

    // the controller can do in its `someAction` handler:// `this.transitionToRoute.apply(this, routeArgs);`
  }
});

// besides the naming, this is verbatim from the end of:// https://github.com/emberjs/ember.js/blob/v1.0.0/packages/ember-routing/lib/helpers/link_to.js
Ember.Handlebars.registerHelper('app-link-to', function(name) {
    var options = [].slice.call(arguments, -1)[0],
        params = [].slice.call(arguments, 0, -1),
        hash = options.hash;

    hash.disabledBinding = hash.disabledWhen;
    hash.parameters = {
      context: this,
      options: options,
      params: params
    };

    return Ember.Handlebars.helpers.view.call(this, App.LinkView, options);
});

Ember.Handlebars.registerHelper('appLinkTo', Ember.Handlebars.helpers['app-link-to']);

Method #3

If you want the best of both, you could combine both methods and extend Ember.LinkView, create a custom Handlebars helper, and use custom event names to signify which actions you want to take. That way, overriding Ember.LinkView, and overwriting _invoke aren't necessary.

Good luck!

Post a Comment for "Extending Ember Linkview"