ExtJS/Rails CRUD Application in 7 Minutes

ExtJS and Rails WithUpdate 1: This tutorial assumes Rails 2.3.x and Ruby 1.8.7.
Update 2: Added a remark in the 3rd section about the changed columns configuration not being reflected in the grid (thanks Noel!).
This post will lead you through simple steps of creating a task manager web application with Ext JS, Ruby on Rails, and Netzke. It will take you approximately 7 minutes to build (if everything runs as smooth as on my own – quite ordinary – setup), and if you’re beforehand curious whether it’s worth 7 minutes of your time, go straight to the last section but one (by far the biggest in this tutorial), where we discuss what we achieved.

We’ll create an application that will allow you add, edit and remove the TODO tasks, as well as mark them done. In addition to that, you’ll be able to sort and search the tasks, edit several tasks at once, modify the view of the task list, and more. At the end of this brief tutorial, we’ll go through the thorough discussion of the tutorial’s results. You may start you stopwatch now, and let’s get to the job.

Setting things up

Create a new rails application:

> rails netzke_task_manager && cd netzke_task_manager

Install Netzke gems:

> gem install netzke-basepack

Include netzke-basepack in environment.rb:

config.gem "netzke-basepack"

Run Netzke generators:

> ./script/generate netzke_core && ./script/generate netzke_basepack

Link the Ext library and, optionally, the FamFamFam silk icons, for example (most probably no copy-pasting here):

> ln -s ~/code/extjs/ext-3.2.1 public/extjs
> ln -s ~/assets/famfamfam-silk public/images/icons

Declare Netzke routes and uncomment the root map in routes.rb:

map.netzke
map.root :controller => "welcome"

Generate the welcome controller:

> ./script/generate controller welcome index

Don’t forget to remove public/index.html.

And finally, create a simple application layout (app/views/layouts/application.html.erb):

<head>
  <meta http-equiv="Content-type" content="text/html; charset=utf-8">
  <title>Netzke Task Manager</title>
  <%= netzke_init %>
</head>
<body>
  <%= yield %>
</body>

Note that netzke_init is all what’s needed to include Ext and Netzke JavaScript and stylesheets.

3 minutes passed, and we’re ready to get to the fun part.

Creating the model

Let’s create the Task model that will have a name, priority, notes, due date, and the “done” flag:

> ./script/generate model Task done:boolean name:string notes:text priority:integer due:date

Modify the migrations file (db/migrate/xxx_create_tasks.rb) slightly to have the “done” flag set to false by default:

  t.boolean :done, :default => false

Run the migrations:

> rake db:migrate

We want our task to always have at least the name set, so, let’s add the proper validations. And set the default scope to only give us incomplete tasks:

class Task < ActiveRecord::Base
  validates_presence_of :name
  default_scope :conditions => {:done => false}
end

Embedding Netzke grid panel

We don’t have much to do to see an Ext grid as an interface to our model. Simply declare Netzke GridPanel in app/views/welcome/index.html.erb:

<%= netzke :tasks, :class_name => "GridPanel", :model => "Task" %>

Start the server:

> ./script/server

… and see how it looks on http://localhost:3000/:

Netzke Task Manager

It’s fully functional and nice-looking already. In a moment I’ll provide you with an impressive list of all the things you can do with it, but first let’s tweak it a bit, so that it looks even nicer – we still have time anyway :)

With Netzke::GridPanel you can easily customize the columns (see a comprehensive tutorial about it). Let’s do 2 simple things here: 1) provide the list of the columns that we want to see, excluding the created_at and updated_at columns that Rails adds by default, and 2) change the title of the “due” column to “Due on”.

<%= netzke :tasks, 
  :class_name => "GridPanel", 
  :model => "Task",
  :columns => [:id, :done, :name, :notes, :priority, {:name => :due, :header => "Due on"}]
%>

If this doesn’t take any effect and you still see the old “due” column, clear the netzke_preferences table in your database. It happens because once you change a column size/position/visibility, the whole column configuration is stored in that table, and from that moment on it takes precedence over what’s in the code.

Perfect. Let’s use our last 2 minutes to do the final – purely visual – touch. Let’s display our grid in the middle of the page, under a title, without that thick blue header, and with a nice border around. And also let’s adjust some columns’ default width and make them automatically occupy the whole available width of the grid.

To put the grid in the middle of the page, let’s quickly add some inline styles into the application layout (after the netzke_init helper):

<style type="text/css" media="screen">
  h1 { text-align: center; margin: 10px;}
  .netzke-widget { width: 700; margin: auto; }
</style>

To add a title, enable the border and disable the grid’s header, update the view:

<h1>Incomplete tasks</h1>

<%= netzke :tasks, 
  :class_name => "GridPanel", 
  :model => "Task",
  :columns => [:id, :done, :name, 
    {:name => :notes, :width => 200}, 
    {:name => :priority, :width => 50}, 
    {:name => :due, :header => "Due on"}
  ],
  :ext_config => {
    # Standard Ext.grid.EditorGridPanel configuration options:
    :border => true,
    :header => false,
    :view_config => {
      :force_fit => true # force the columns to occupy all the available width
    }
  } 
%>

Well, that’s it! Stop your stopwatch, and let’s discuss in details what we’ve got:

Netzke Task Manager Complete

Discussing the results

Because Netzke::GridPanel is a very powerful Netzke widget, our application gets a lot of features for free.

Multi-line CRUD operations

Adding, updating and deleting records can easily be done in a multiline way:

grid panel multiline CRUD

Pagination

Even if you data table contains tens of thousands of records, it’s no problem for a Netzke grid panel, thanks to the built-in pagination.

Context menu

Some of the button actions on the bottom of the grid are duplicated in the grid’s context menu:

grid panel context menu

Automatic detection of attribute types

In our application we’re using an integer, boolean, string, text, and date fields in the Task model – and each of them are getting its own column type (you’ll not be able to enter letters in the priority field).

Support for Rails validations

Rails validations are respected (and they play nicely with multiline editing!):

grid panel validations

Server-side sorting

Click the header of the column to enable server-side sorting:

grid panel sorting

Server-side filtering

Smart filters are enabled by default by each column, corresponding to the data type.

For due-date:

grid panel filtering by date

For priority:

grid panel filtering by priority

Persistent column visibility, position, and size

You can manipulate the columns, and your preferences will be remembered in the database.

For those who wonder: in a multi-user setup this is stored per user.

grid panel column manupulations

Adding/(multi-)editing records in a form

Sometimes adding/editing a record is much handier from within a form. Netzke gives you that, too. And even multi-record editing is supported – just select multiple rows and press “Edit in form”.

grid panel editing in form

Advanced search, with preset management

grid panel advanced search

And more

While not covered in this tutorial, Netzke grid panel also supports:

  • one-to-many (“belongs_to”) relationships (see a link for a demo below)
  • detailed dynamic configuration of columns, permissions, and appearance of the grid, enabled in the configuration mode (as shown in this screencast)

Conclusion

You’ve learnt about a small part of what Netzke can provide, on an example of Netzke::GridPanel – a very powerful, customizable and extendible widget, that you can use in your RIA. You can see more examples of using GridPanel and other Netzke widgets on live demo. In fact, Netzke is conceived to be a framework that let’s you create your own powerful components – either from scratch, or using existing widgets as building parts.

Follow me on twitter to stay updated with Netzke, and don’t forget to bookmark the official Netzke project website. Share your Netzke experience on the Google Groups, and – last but not least! – please, spread the word: Netzke is a pretty complex project, so, a larger community will mean faster development. Thanks!

Credits for the ExtJsWithRails logo go to www.extjswithrails.com

blog comments powered by Disqus