ember-impagination icon indicating copy to clipboard operation
ember-impagination copied to clipboard

Support for router/controller actions

Open seanrucker opened this issue 9 years ago • 9 comments

In the example it suggests the fetch function should be a property of the route and that a direct reference to that function be passed to the component. This won't run the function in the scope of the route and therefore you can not access the store.

{{#impagination-dataset fetch=fetch}}
export default Ember.Route.extend({
    fetch: function(pageOffset, pageSize, stats) {
        return this.store.query(...); // fail
    })
});

I was expecting that I would pass the name of the action that should be run as a string as is consistent with other components.

{{#impagination-dataset fetch="fetch"}}
export default Ember.Route.extend({
    actions: {
        fetch(pageOffset, pageSize, stats) {
            return this.store.query(...); // success
        })
    }
});

As a temporary workaround I am doing this:

{{#impagination-dataset fetch=(action "fetch")}}

seanrucker avatar Jan 14 '16 19:01 seanrucker

Hi @seanrucker,

We realize there are some documentation issues that are causing people difficulties with ember-impagination. The issues you opened today are all great issues, and we want to address these prior to our 0.2.0 milestone.

We are working on updating the README with How To Recipes for the many implementations of ember-impagination

Here's what I believe you are looking for:

{{#impagination-dataset fetch=fetch}}
export default Ember.Route.extend({
    fetch: function(pageOffset, pageSize, stats) {
        return this.store.query(...); // fail
    }),
    setupController: function(controller, model){
        this._super.apply(this, arguments);
        controller.set('fetch', this.fetch.bind(this));
    })
});


You'll be able to access the store that way. Also see #36 for an API extension to Observe the most recently updated dataset.

flexyford avatar Jan 14 '16 22:01 flexyford

Cool. FYI I did eventually get it up and running and it is working beautifully. In combination with ember-collection it is a really slick solution. I'm loading 10k rows in batches of 100 at a time and it's performing amazing. Thanks for releasing this great component.

seanrucker avatar Jan 14 '16 22:01 seanrucker

@seanrucker that's actually a really great solution, and should be in the docs. The way that's actually in the readme was what you would do in a < 1.13 app

cowboyd avatar Jan 14 '16 23:01 cowboyd

It would be nice if it supported passing an action name rather than a function reference.

{{#impagination-dataset fetch="fetch"}}

That way the action could be defined on the controller OR on the route which is likely a better spot to be handling the data loading.

With my workaround...

{{#impagination-dataset fetch=(action "fetch")}}

... I had to define the action on the controller and that required me to inject the store into the controller.

import Ember from 'ember';

export default Ember.Controller.extend({

    store: Ember.inject.service(),

    actions: {
        fetch() {
            return this.get('store').query(...);
        }
    }
});

It works, but its a bit sloppy.

seanrucker avatar Jan 15 '16 21:01 seanrucker

It would be nice if it supported passing an action name rather than a function reference.

The impagination library, which ember-impagination wraps, must receive a fetch which is a "thenable". Therefore, we cannot pass in a string, since calling this.sendAction('fetch') does not return a promise. It's an intricacy of the original library that has our hands tied at this point.

I'm afraid that if you want to define the action on the controller, you have to inject the store into the controller. If fetch exists in the actions hash on either the route or controller, you will have to use the following syntax:

{{#impagination-dataset fetch=(action "fetch")}}

Thanks for all your hard work on this @seanrucker

flexyford avatar Jan 26 '16 17:01 flexyford

In your documentation update you mention passing the fetch function like so:

{{#impagination-dataset fetch=(action "fetch")}}

Below that you state:

We do not recommend deifning fetch inside your controller because it requires injecting the store into the controller

Unless I'm missing something, using a closure action doesn't allow defining the action anywhere but the controller.

http://stackoverflow.com/questions/31101296/how-to-call-an-action-on-a-route-using-closure-actions

When I try to move my action to the route I get the following error:

Uncaught Error: An action named 'fetch' was not found in <my-app@controller:controller-name::ember123>

In my comment above, I mentioned that I had to inject the store into the controller because it would not allow me to define the action on the route. The controller was not my preferred place to put the fetch action but I could not find a workaround.

seanrucker avatar Feb 02 '16 18:02 seanrucker

@seanrucker that is my experience as well. Closure actions must reside in the controller unless you use something like https://github.com/dockyard/ember-route-action-helper

utilityboy avatar Feb 04 '16 19:02 utilityboy

Okay, because the README for ember-impagination is lengthy, we are trying to be concise with how and where to define the fetch function. I was unaware that "Closure actions must reside in the controller". The ember-route-action-helper "will work on Ember versions 1.13.x and up only." @bjubinville did the ember-route-action-helper addon work for you? Curious if you can then define the store.

If yes, then I would like the README to reflect this! I think I will also include @seanrucker 's inject solution as an alternate to ember-route-action-helper. Thanks for the continued help on this addon @seanrucker and @bjubinville . I know you all are working to implement ember-impagination and sharing your experience. You help improve the next developer's ease of use.

I'll draft a new README with the proposed changes

flexyford avatar Feb 05 '16 16:02 flexyford

@flexyford I personally keep actions in the controller, so don't leverage that plugin right now though I'm aware of it's existence. This is possibly the best article I've come across to date about closure actions:

http://miguelcamba.com/blog/2016/01/24/ember-closure-actions-in-depth/

In my routes, I define things like this:

...
model() {
  ...
},

setupController(controller, model) {
  this._super(...arguments);

  let _this = this;
  controller.set('actions', {
    fetch() {
      return _this.store ...
    }
  });
}
...

utilityboy avatar Feb 05 '16 17:02 utilityboy