Add a powerful AJAX Table to your Rails Application in 5 minutes

jq.png
I needed to add an AJAX grid/table component with all the bells and whistles (AJAX sorting, pagination, multiple row select, AJAX add/delete etc) to an application I am working on right now (will blog about it when we roll out a good-enough version). We are using jQuery so I started looking for a suitable plugin.

I believe I have found it – it’s called jqGrid and it’s super sexy, feature rich and the documentation is on par with a commercial tool – so I created a Rails plug-in enabling you to add it to your Rails app in no time! Follow the 10 steps below to find out how.

  1. Create a blank Rails app (in your home dir – or change the path in the next step):
    rails -d mysql grid_test
    
  2. install jQuery:
    curl http://jqueryjs.googlecode.com/files/jquery-1.2.6.pack.js > ~/grid_test/public/javascripts/jquery.js
    
  3. install jquery\_grid\_for_rails – I am using giternal (how to install), so this is what you need to do in this case:
    open config/giternal.yml and enter:

    jquery_grid_for_rails:
      repo: git://github.com/scrubber/jquery_grid_for_rails.git
      path: vendor/plugins
    

    then run

    giternal update
    

    (obviously you can use script/plugin, git submodules, piston, braid or whatever floats your boat)

  4. Generate a migration to test out stuff with:

    script/generate resource person
    
    class CreatePeople < ActiveRecord::Migration
      def self.up
        create_table :people do |t|
          t.string :first_name, :last_name, :title, :i_can_has_cheezburger 
        end
      end
    
      def self.down
        drop_table :people
      end
    end
    
  5. generate dummy data

    script/generate migration create_dummy_people_data_migration
    
    class CreateDummyPeopleDataMigration < ActiveRecord::Migration
      def self.up
        Person.create :first_name =>"He", :last_name => "Man", :title => "Hero", :i_can_has_cheezburger => "Sure"
        Person.create :first_name =>"Bat", :last_name => "Man", :title => "Mr.", :i_can_has_cheezburger => "Yeah"
        Person.create :first_name =>"Cat", :last_name => "Woman", :title => "Ms.", :i_can_has_cheezburger => "Yes"
        Person.create :first_name => "Super", :last_name => "Man", :title => "d00d", :i_can_has_cheezburger => "Nope"
        Person.create :first_name => "Spider", :last_name => "Man", :title => "Mr.", :i_can_has_cheezburger => "Meh"
        Person.create :first_name => "Chuck", :last_name => "Norris", :title => "Sir", :i_can_has_cheezburger => "Who is asking?"
        Person.create :first_name => "G.I.", :last_name => "Joe", :title => "Sgt", :i_can_has_cheezburger => "What is a cheezeburger?"
      end
    
      def self.down
        Person.destroy_all
      end
    end
    
  6. Time to run the migrations!

    Set up the db first:

    rake db:create
    

    run teh migrations:

    rake db:migrate
    
  7. Set up the controller (PeopleController) - add this method:

      def grid_data
        @people = Person.all(:order => "#{params[:sidx]} #{params[:sord]}")
        
        respond_to do |format|
          format.xml { render :partial => 'grid_data.xml.builder', :layout => false }
        end    
      end
    
  8. Modify config/routes.rb to look like

    map.resources :people, :collection => {:grid_data => :get}
    
  9. This goes into your application layout (create a new file - views/layouts/application.html.erb):

    
    	
    		
    		
    		<%= javascript_include_tag 'jquery' %>
    		<%= include_jquery_grid_javascript %>
    		<%= include_jquery_grid_css %>
    	
    	
    		<%= yield %>
    	
    	
    
  10. The last step: views (views/people/_grid_data.xml.builder, views/people/index.html.erb)

    xml.instruct! :x ml, :version=>"1.0", :encoding=>"UTF-8"
    xml.rows do
      xml.page params[:page]
      xml.total_pages (@people.size.to_i / params[:rows].to_i)
      xml.records{@people.size}
      @people.each do |u|
        xml.row :id => u.id do
          xml.cell u.title
          xml.cell u.first_name
          xml.cell u.last_name
          xml.cell u.i_can_has_cheezburger
        end
      end
    end
    
      <%= jquery_grid :sample, {:url => grid_data_people_url } %>
      
    My cool AJAX grid!
    <%= jquery_grid_table %> <%= jquery_grid_pager %>
  11. That's it! Start script/server, point your app to http://localhost:3000/people and if you did everything according the tutorial, you should (hopefully) see something like this:


    ajax_grid.png

    I have uploaded the app to github, be sure to check it out (WARNING - don't copy and paste from the above code, the code highlighting plugin has some problems and you'd get strange results. Clone the repo instead).

    Note that the installed plug-in is included in .gitignore so you have to run "giternal update" after you clone it.

    Drop me a comment if you experience any problems!

45 thoughts on “Add a powerful AJAX Table to your Rails Application in 5 minutes

  1. Pingback: Web 2.0 Announcer

  2. However I get the following error:

    Errno::ENOENT in People#index

    No such file or directory – /home/…./grid3/config/jquery_grid/sample.yml

    2: <%= jquerygrid :sample, {:url => griddatapeopleurl } %>

  3. Ali… indeed, the file /config/jquery_grid_sample.yml is missing for some reason – please clone the example app repo (git clone git://github.com/scrubber/jquery_grid_for_rails_sampleapp.git) and copy it from there.

    Strange though that it is missing…

  4. Pingback: links for 2008-12-13 « pabloidz

  5. That’s what I’ve done. I’ve solved the problem by copying the jquery_grid in config folder of the project.

    Thanks Peter

  6. Hi Peter.

    How do you do to delete a row?

    I’ve tried with :function_onclickSubmit: “(params){alert(‘kos’); }” with no results.

    Thanks

  7. Thanks for this tutorial! It has been helpful.

    Step 10 instructs you to create “views/people/griddata.xml.builder”, which is not the file referenced by the controller. This should be “views/people/_grid_data.xml.builder”. (Note: I attempted to paste the correct filename here in the blog comment, but the blog is treating the leading underscore as an escape character. Heh. I used an HTML escape to render things properly…)

    I tried giternal as you suggested, but also ran into the sample.yml problems. I was also missing the CSS and JS files in my public/ dir. I went with script/plugin instead, which correctly copied all these files for me.

    Thanks again!

  8. “Excellent point! I read most of your article and establish it great. The points you furnished in your article are magnificent. I am actually waiting for your following conceived of.

    Thanks and best of luck!”

  9. Man – this tutorial really helped. Good Job! Got it up and running easily.
    If I now could find a example REST-App which allows to add/delete rows and to edit/select cell data/pulldowns I’d be happiest man in the world.
    I tried to do this in Dojo and jmaki but it didn’t work. Jsgrid looks easier to cope with.

    Do you know about an display/edit app ?

  10. ooooook……
    thanks for the link. It’s written for experienced web programmers. Tried it , but as a pure Rails and man and Ajax newbee i can’t transfer his hints onto your example to get a RESTful grid. The leap from readonly to full edit seems to be as high as with Dojo. Do you have any more idea where to look ? Thanks in advance.

  11. Not really… I am planning to create a second part of this tutorial, which would include the stuff you are requesting. Now that I know that people would need it (you are not the first, and most probably not the last one to ask for this) I might force myself to write part II…

  12. hehe, my wife is also my boss, kinda (my pair programming partner and officially the CEO of our LLC) so at least you don’t have to hassle with more people :-)

    Ok, I’ll look into it during the weekend, I guess a mid-week blog post sounds realistic (or next weekend… or something :-) don’t like to make promises as I am mega-swamped w/ ‘real’ work ;-)

  13. Is there any working demo on using yield, Ajax for dynamic content? or a Dynamic Help System.

    Regards.

    David

  14. Hi, thanks very much for the tutorial! I tried to use it for my own program but I can’t get it to display the data. If i go to http://127.0.0.1:3000/planets it only shows me the table heading.

    If I go to http://127.0.0.1:3000/planets/grid_data however it does show the correct information (tho it complains “This XML file does not appear to have any style information associated with it. The document tree is shown below.” but I think that is normal).

    I’ve tried various things but I just can’t get it to work :(
    Any chance someone can take a look at this and tell me where I’m going wrong, or give some hints?

    Here’s what I think are the most relevant bits of the source files:
    app/views/planets/index.html.erb:

    <%= jquerygrid :sample, {:url => griddataplanetsurl } %>

    using this doesnt work either: <%= jquerygrid :sample, {:url => “http://127.0.0.1:3000/planets/griddata” } %>

    Planets – Uni40.org
    <%= jquerygridtable %>
    <%= jquerygridpager %>

    app/controllers/planets_controller.rb:

    [...]
    def grid_data
    params[:sidx]=:id
    params[:sord]=”asc”
    params[:rows]=20
    @planets = Planet.all(:order => “#{params[:sidx]} #{params[:sord]}”)

    respond_to do |format|
      format.xml { render :partial => 'grid_data.xml.builder', :layout => false }
    end
    

    end
    [...]

    app/views/layouts/application.html.erb:

    Railpot in Ajax

    app/views/planets/griddata.xml.builder:

    xml.instruct! :x ml, :version=>”1.0″, :encoding=>”UTF-8″
    xml.rows do
    xml.page params[:page]
    xml.totalpages(@planets.size.toi / params[:rows].toi)
    xml.records{@planets.size}
    @planets.each do |u|
    xml.row :id => u.id do
    xml.cell u.universe
    id
    xml.cell u.playername
    xml.cell u.galaxy
    no
    xml.cell u.systemno
    xml.cell u.planet
    no
    end
    end
    end

  15. a bit too complicated for a person like me who is not a computer literate but very clever if it works for some, not for me though good luck to the person who created it.

  16. I am dying to take this for a drive except …

    I installed the it as a plugin:
    script/plugin install git://github.com/scrubber/jquerygridfor_rails.git

    no errors

    created everything. run it, got error: undefined method `jquerygrid’ for #
    rechecked the code yup – included jquery in view/layout/application.html.erb file
    <%= javascript
    includetag ‘jquery’ %>
    <%= include
    jquerygridjavascript %>
    <%= includejquerygrid_css %>

    checked the vendor/plugin folder – yup – it’s there – but it’s empty.

    I am a newbie. Tried to get giternal – link that you provided gone, so found giternal by Pat Maddox. Don’t know what to do with it since there are no install instructions. Darn.
    http://github.com/pat-maddox/giternal/tree/master

    So I download the scrubber jquery from github, untarred it, and copied the jquery folder from config into my app. No dice. same error.

    I am sure that I am making a foolish error somewhere – any ideas?

    TIA, Farida

  17. Tried using the giternal posted by Pat Maddox on github: http://github.com/pat-maddox/giternal/tree/master

    Any help about what to do after the downloading. I tried:

    gem sources -a http://gems.github.com
    gem install giternal
    giternal update

    C:grid_test>giternal update
    C:/ruby/lib/ruby/gems/1.8/gems/giternal-0.0.2/bin/../lib/giternal/repository.rb:
    23:in update': Directory 'jquery_grid_for_rails' exists but is not a git reposi
    tory (RuntimeError)
    from C:/ruby/lib/ruby/gems/1.8/gems/giternal-0.0.2/bin/../lib/giternal/a
    pp.rb:8:in
    update’

    TIA, Farida

  18. Hi,

    Dan Croak helped me out. He said to get the it:
    http://github.com/scrubber/jquerygridfor_rails (click the “download”
    button)

    and save it to vendor/plugins
    I did it and renamed the file jquerygrid. Then I copied over the config/jquerygrid folder with the sample.

    Yeah – no errors. Darn – no grid either. More head scratching. Checked above code. Yup looks good. Did change the file name like Heath said because it was rendering partial. He also mentioned about plugin install – but being a newbie I was not exactly what to do.

    Any suggestions what I screwed up? View source shows that it is getting:
    var lastsel2;
    jQuery(document).ready(function(){
    jQuery(“#sample”).jqGrid({
    imgpath: “/stylesheets/jqGrid-themes/basic/images”,
    pager: jQuery(‘#samplepager’),
    mtype: “GET”,
    onSelectRow: function(id) {
    if(id && id!==lastsel2) { $(‘#sample’).restoreRow(lastsel2); $(‘#sample’).editRow(id,true); lastsel2=id; }
    },
    datatype: “xml”,
    sortname: “first
    name”,
    colNames: ["title", "first name", "last name", "i can has cheezburger?"],
    sortorder: “desc”,
    colModel: [{"editable": true, "index": "title", "name": "title", "width": 40}, {"editable": true, "index": "firstname", "name": "firstname", "width": 130}, {"editable": true, "index": "lastname", "name": "lastname", "width": 130}, {"editable": false, "index": "icanhascheezburger", "name": "icanhascheezburger", "width": 200}],
    rowNum: 10,
    url: “http://localhost:3000/people/grid_data”
    });
    });

    Thanks, Farida

  19. Tried http://localhost:3000/people/grid_data

    Mysql::Error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ” at line 1: SELECT * FROM people ORDER BY

    tried grid_data with a comma
    @people = Person.all(:order => “#{params[:sidx]}, #{params[:sord]}”)

    same error with a comma in it ORDER BY ,

    hmm. Any suggestions where I went wrong?
    Thanks, Farida

  20. What happens if you want to use this plugin for two or more grids in the same view?

    Since this specifies the grid in the view:
    <%= jquerygridtable %>
    <%= jquerygridpager %>

    How can you specify a second grid?

  21. Thanks for the great demo. I had a problem that I fixed, but I don’t understand why I had the problem. I’m using RadRails in Eclipse. I loaded the jquerygridforrails plugin using git, and everything appeared under vendor/plugins/jquerygridforrails. But when I ran the app, it couldn’t find any of the javascript or stylesheets. When I compared my code to the demo code on github, I saw that these files were directly in the app’s public javascripts and stylesheets directories. When I copied these directories from the plugin to my app, everything worked. My question is why wouldn’t my app load from the vendor/plugins directory? Is there a configuration change I need to make to tell it to do that?

  22. Anybody tried to use this w/ will_paginate? The “next” icon doesn’t work.
    Please advice.

  23. Had to define a show action within PeopleController to get it to work, as follows:
    def grid_data

      end
    
     def show
        @people = Person.all(:order => "#{params[:sidx]} #{params[:sord]}")
          respond_to do |format|
            format.xml { render :partial => 'griddata.xml.builder', :layout => false }
          end
     end
    

    Control was never passed to the grid_data method at all, so I removed the logic altogether from it.

    routes.rb contains both
    map.resources :people
    map.resources :people, :collection => {:grid_data => :get}

    Any ideas what is going on ?

  24. Thanks for the great tutorial. This demo is working nicely in my application without error.

    How to use pagination in this application?. Any idea.

  25. how do I change the cell format in terms of integer value?
    I want my numbers to be classified in 000 unit. ie the comma on every 1000th unit.
    eg 1000 <- 1,000

    please help

  26. i find your plugin very intrusive and dont appreciate you’re moving all these files into my app espeically without asking me, including copies of jqgrid, which i already had installed, css files, and more. Then it didnt take long to realize you hardcode view parameters in the config/ yaml file, violating the mvc paradigm and app structure, in my opinion. Thanks for your interesting work, but no thanks on your implementation.

  27. Pingback: JavaScript grid editor: I want to be Excel « Eltit Golb

  28. I got it working, but… what if my People-class has an association to e.g. pets, and pets has race, birthday, name. Now I want to show a table with people.firstname, people.lastname, people.pet.name?

    Right now rails fails after asking the database “SELECT * FROM people ORDER BY pet.name desc”. I understand that this fails, but I don’t know how to fix this :(

    Could you please help me out with an example?

    thanks!
    ben

  29. Maintain up the great perform mate. This website submit indicates how nicely you comprehend and know this subject.

  30. I am a affiliate of the church choir and tomorrow we will be presenting our talents at a wedding. I’ll be singing at such an occasion and I can’t wait to see the bride and groom. They are both beautiful and good people in our town.

  31. Hey, quite good website. I truly came across this on Bing, and I am happy I did. I will definately be coming back here a lot more frequently. Wish I could add for the conversation and bring somewhat more for the table, but am just absorbing as much information as I can at the second. Thank You

  32. I have

    ActionView::MissingTemplate (Missing partial people/griddata.xml with {:handlers=>[:erb, :rjs, :builder, :rhtml, :rxml], :formats=>[:xml], :locale=>[:en, :en]} in view paths “/home/alex/Projects/gridtest/app/views”, “/home/alex/Projects/gridtest/vendor/plugins/jquerygridforrails/app/views”):
    app/controllers/peoplecontroller.rb:5:in block (2 levels) in grid_data'
    app/controllers/people_controller.rb:4:in
    grid
    data’

    Please help!

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>