Getting meta from JSON payload


#1

I’m working on pagination, and i’m stuck on getting meta data from the server. It is sent as Active Model Serializer format.

I saw that Ember supports usage of meta-data — https://github.com/emberjs/data/pull/815 —but I can’t figure out how to integrate it. Can anyone help?


#2

Hi!

I tried to implement the meta data myself. The only solution I found was to write a custom serializer that writes the meta information into a global variable accessible by the app.

We are using this currently on an ember 1.0-pre4 app and it’s working as expected. I think a better solution would be to work with a pagination controller that gets passed the meta information instead of relying on an object in the app namespace but I haven’t had the time to refactor my current solution yet.


#3

@LevelbossMike Thanks, but i don’t think this is the right solution for me. A global variable for all may have some troubles later with me.


#4

As I pointed out I am aware that the global variable approach is not a good solution. The interesting part is to extract the meta information and this can be done with a custom serializer.


#6

It works. @LevelbossMike the code below uses Ember’s default meta data getter with each model on its own. So you don’t need to use a custom method or override serializer.

var serializer = DS.RESTSerializer.create();

App.Adapter = DS.RESTAdapter.reopen({
  serializer: serializer,
});

serializer.configure({
  since_id: 'since_id',
  max_id: 'max_id'
});

App.Store = DS.Store.extend({
  adapter: App.Adapter.create()
});

To test it, go to chrome console, reload and run this command

App.store.typeMapFor(App.Post).metadata

#7

Nice! I’ll give this a try! :+1:


#8

@seif Did you get this to work with computed properties? I am able to get the meta information into the store and to access it via the typeMapsFor method of the store on the console. But I am not able to bind on the metadata for a model.

Does anybody know how to access the metadata from a controller?

SomeController = Ember.ArrayController.extend
  pagination: ( ->
    # won't work! taken from https://github.com/emberjs/data/pull/815
    this.get('content.store.typeMaps.metadata') # => undefined
  ).property('content.store.typeMaps.@each.metadata')

As I have read in the Ember-Data source it seems to be impossible to bind to the typemaps array of the store. So I am pretty clueless how this should work.

I think it would be nice to have a property on the ResultArray for the meta information but his also does not seem to work as one might expect:

SomeController = Ember.ArrayController.extend
  pagination: ( ->
    this.get('content.meta') # => undefined
  ).property('content.isLoaded')

I guess several people are using the undocumented meta information hook in ember data but I wasn’t able to find any example apps. Did anybody of you get this to work in a nice way?


#9

No, haven’t tried that. But why would you bind it to the model, shouldn’t the controller be responsible for paging?


#10

I want this to be in the controller. I tried to access the metadata from the model/content property of the controller as suggested in the pull request you referenced.


#11

try this

var metadata = App.store.typeMapFor(App.Post).metadata;
posts = App.Post.find({max_id: metadata.max_id});

#12

Thx! Unfortunately this won’t work when I want to build a pagination based on metadata information passed in a serializer because I need to observe the metadata property to use it in a pagination controller / template.

This is basically what I want to do:

App.SomethingRoute = Ember.Route.extend
  model: ->
    App.Something.find()

App.SomethingController = Ember.ArrayController.extend
  pagination: ( ->
    this.get('model.metadata.pagination') # => of course this won't work
  ).property('model.isLoaded')

I don’t think I am the only one who needs pagination in his/her apps. Accessing the metadata is the last missing piece in the puzzle. :wink:


#13

Here is how I paginate using max_id. This is the code for my pagination, it was from a blog post.

App.PostsIndexRoute = Ember.Route.extend({
    events: {
        more: function() {
            console.log('Loading posts...');
            var metadata = App.store.typeMapFor(App.Post).metadata;
            
            posts = App.Post.find({max_id: metadata.max_id});
            if (posts.content.length > 0) {
                this.controllerFor('posts').pushObject(posts);
            }
        }
    }
});

App.PostsIndexView = Ember.View.extend({

    didInsertElement: function() {
        var view = this;
        $(window).bind("scroll", function() {
            view.didScroll();
        });
    },
    // When this view is destroyed we need to unbind the scroll event.
    willDestroyElement: function() {
        $(window).unbind("scroll");
    },
    didScroll: function() {
        if(this.isScrolledToBottom()) {
            this.get('controller').send('more');
        }
    },
    isScrolledToBottom: function() {
        var distanceToTop = $(document).height() - $(window).height(),
            top           = $(document).scrollTop();
        return top === distanceToTop;
    }
});

Hope this helps.


#14

I answered my original question on stackoverflow myself. The described way works with the typeMaps property of the store. If anybody knows better please comment on the SO issue.


#15

Just merged a solution for meta into master. Should land in the next beta. This allows you to bind directly to recordArray.meta However, there needs to be discussion around whether it will make it into Ember Data 1.0 and in what form. See the pull request.

In my opinion we should be able to bind on the meta object so we can display this information in templates e.g. page, total count, page count, search facets etc.