Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ember-table integration with Ember-model / Ember-data

I am trying to link ember-models to the ember-table to pull paginated records from the server and add them to the table when scrolling down.

I can get it working by just requesting my api url with page number like in the ajax example on http://addepar.github.io/ember-table/ but i cant figure out how to integrate it with ember-model to create and ember objects and then add them to the table.

Here is my code to just make an ajax request and add to table. Can anyone tell me how i can change this to use ember-model / ember-data instead.

App.TableAjaxExample = Ember.Namespace.create()

App.TableAjaxExample.LazyDataSource = Ember.ArrayProxy.extend

  createGithubEvent: (row, event) ->

    row.set 'id',       event.id
    row.set 'name',  event.name
    row.set 'isLoaded',   yes

  requestGithubEvent: (page) ->

    content = @get 'content'
    start   = (page - 1) * 30
    end     = start + 30
    per_page = 40
    # something like this ???
    #App.Detail.find(type: 'companies', page: page, per_page: per_page).on 'didLoad', ->
    url = "http:/myurl.dev/admin/details.json?type=companies&page=#{page}&per_page=30"
    Ember.$.getJSON url, (json) =>
      json.details.forEach (event, index) =>
        row = content[start + index]
        @createGithubEvent row, event
    [start...end].forEach (index) ->
      content[index] = Ember.Object.create eventId: index, isLoaded: no

  objectAt: (index) ->

    content = @get 'content'
    #if index is content.get('length') - 1
    #  content.pushObjects(new Array(30))
    row = content[index]
    return row if row and not row.get('error')
    @requestGithubEvent Math.floor(index / 30 + 1)
    content[index]

App.TableAjaxExample.TableController =
Ember.Table.TableController.extend

  hasHeader: yes
  hasFooter: no
  numFixedColumns: 0
  numRows: 21054
  rowHeight: 35

  columns: Ember.computed ->

    columnNames = ['id', 'name']
    columns = columnNames.map (key, index) ->
      Ember.Table.ColumnDefinition.create
        columnWidth: 150
        headerCellName: key.w()
        contentPath: key

    columns
  .property()

  content: Ember.computed ->
    App.TableAjaxExample.LazyDataSource.create

      content: new Array(@get('numRows'))
  .property 'numRows'

Is the possible or does this slow it down to much?

Thanks for the help. Rick

like image 858
Rick Moss Avatar asked Sep 11 '13 12:09

Rick Moss


People also ask

What is a model in Ember?

In Ember Data, models are objects that represent the underlying data that your application presents to the user. Note that Ember Data models are a different concept than the model method on Routes, although they share the same name.

How do I use Ajax in Ember JS?

Basic Usage In fact, ember-ajax is a wrapper around jQuery's method, and can be configured in much the same way. In general, you will use the request(url, options) method, where url is the destination of the request and options is a configuration hash for jQuery. ajax . import Ember from 'ember'; export default Ember.


1 Answers

Here's a JSBin that I got working with Ember Data and the RESTAdapter: http://jsbin.com/eVOgUrE/3/edit

It works very similarly to the AJAX loading example, but uses Ember Data to load the data. I created a RowProxy object that is returned immediately to the Ember Table so that it can render a row. After Ember Data loads a page full of data it sets the object property on the RowProxy which updates the view.

window.App = Ember.Application.create();

// The main model that will be loaded into Ember Table 
App.Gallery = DS.Model.extend({
  name: DS.attr('string'),
  smallUrl: DS.attr('string')
});

// This is a temporary buffer object that sits between
// Ember Table and the model object (Gallery, in this case).
App.RowProxy = Ember.Object.extend({
  object:null,
  getObjectProperty : function(prop){
    var obj = this.get('object');
    if(obj){ console.log(prop + " : " + obj.get(prop)); }
    return obj ? obj.get(prop) : 'loading...';
  },
  isLoaded : function(){ return !!this.get('object'); }.property('object'),
  name : function(){ return this.getObjectProperty('name'); }.property('object.name'),
  id : function(){ return this.getObjectProperty('id'); }.property('object.id'),
  smallUrl : function(){ return this.getObjectProperty('smallUrl'); }.property('object.smallUrl')
});

App.ApplicationController = Ember.Controller.extend({
  tableController: Ember.computed(function() {
    return Ember.get('App.TableAjaxExample.TableController').create({
      // We need to pass in the store so that the table can use it
      store : this.get('store')
    });
  })
});

App.TableAjaxExample = Ember.Namespace.create();

App.TableAjaxExample.ImageTableCell = Ember.Table.TableCell.extend({
  templateName: 'img-table-cell',
  classNames: 'img-table-cell'
});

App.TableAjaxExample.LazyDataSource = Ember.ArrayProxy.extend({
  requestPage : function(page){
    var content, end, start, url, _i, _results,
      _this = this;

    content = this.get('content');
    start = (page - 1) * 3;
    end = start + 3;

    // Find galleries and then update the RowProxy to hold a gallery as 'object'
    this.get('store').find('gallery',{page_size:3,page:page}).then(function(galleries){
      return galleries.forEach(function(gallery, index) {    
        var position = start + index;
        content[position].set('object',gallery);
      });  
    });

    // Fill the 'content' array with RowProxy objects
    // Taken from the 'requestGithubEvent' method of the original example
    return (function() {
      _results = [];
      for (var _i = start; start <= end ? _i < end : _i > end; start <= end ? _i++ : _i--){ _results.push(_i); }
      return _results;
    }).apply(this).forEach(function(index) {
      return content[index] = App.RowProxy.create({
        index: index
      });
    });
  },

  objectAt: function(index) {
    var content, row;
    content = this.get('content');
    row = content[index];
    if (row && !row.get('error')) {
      return row;
    }
    this.requestPage(Math.floor(index / 3 + 1));
    return content[index];
  }
});

App.TableAjaxExample.TableController = Ember.Table.TableController.extend({
  hasHeader: true,
  hasFooter: false,
  numFixedColumns: 0,
  numRows: 19,
  rowHeight: 35,
  columns: Ember.computed(function() {
    var avatar, columnNames, columns;

    avatar = Ember.Table.ColumnDefinition.create({
      columnWidth: 80,
      headerCellName: 'smallUrl',
      tableCellViewClass: 'App.TableAjaxExample.ImageTableCell',
      contentPath: 'smallUrl'
    });
    columnNames = ['id', 'name'];
    columns = columnNames.map(function(key, index) {
      return Ember.Table.ColumnDefinition.create({
        columnWidth: 150,
        headerCellName: key.w(),
        contentPath: key
      });
    });
    columns.unshift(avatar);
    return columns;
  }).property(),
  content: Ember.computed(function() {
    return App.TableAjaxExample.LazyDataSource.create({
      content: new Array(this.get('numRows')),
      store : this.get('store')
    });
  }).property('numRows')
});


App.ApplicationAdapter = DS.RESTAdapter.extend({
  host: 'http://files.cloudhdr.com/api/v1/public',
  // This is here to use underscores in API params
  pathForType: function(type) {
    var underscored = Ember.String.underscore(type);
    return Ember.String.pluralize(underscored);
  }
});

// Everything below is all here to use underscores in API params.
// You may or may not need this.

DS.RESTSerializer.reopen({
  modelTypeFromRoot: function(root) {
    console.log("modelTypeFromRoot " + root);
    var camelized = Ember.String.camelize(root);
    return Ember.String.singularize(camelized);
  }
});

App.ApplicationSerializer = DS.RESTSerializer.extend({
  normalize: function(type, hash, property) {
    var normalized = {}, normalizedProp;

    for (var prop in hash) {
      if (prop.substr(-3) === '_id') {
        // belongsTo relationships
        normalizedProp = prop.slice(0, -3);
      } else if (prop.substr(-4) === '_ids') {
        // hasMany relationship
        normalizedProp = Ember.String.pluralize(prop.slice(0, -4));
      } else {
        // regualarAttribute
        normalizedProp = prop;
      }

      normalizedProp = Ember.String.camelize(normalizedProp);
      normalized[normalizedProp] = hash[prop];
    }

    return this._super(type, normalized, property);
  }
});
like image 144
Jeremy Green Avatar answered Oct 11 '22 17:10

Jeremy Green