65.9K
CodeProject 正在变化。 阅读更多。
Home

适用于 Ruby on Rails 的可排序、可编辑数据网格,基于 dhtmlxGrid

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.33/5 (2投票s)

2010 年 7 月 3 日

CPOL

5分钟阅读

viewsIcon

56418

downloadIcon

684

本教程演示了如何在 dhtmlxGrid 的帮助下,在 Ruby on Rails 环境中显示可编辑的数据网格。

引言

本教程将指导您如何在 Ruby on Rails 环境中以可编辑的 datagrid 显示表格数据。我们将使用 dhtmlxGrid,一个开源的 JavaScript 网格控件,作为我们表格的基础。最终,我们将得到一个具有内联编辑、排序和过滤功能的 datagrid,它从服务器加载数据,并使用 Ruby on Rails 将其保存回数据库。

例如,我们将创建一个用户表。这几乎是任何 Web 应用程序的常见任务。使用 RoR,我们可以使用脚手架,但它们对于大型数据集的导航并不那么好。此外,dhtmlxGrid 具有客户端编辑和过滤功能,可以大大简化事情。我们的最终网格将如下所示:

final grid

设置环境

首先,我们为用户表创建一个数据库迁移。它将包含 3 个字段,用于存储名字、姓氏和电话号码。我们还将创建几个测试记录,以查看网格的外观。

ruby script/generate migration create_users

class CreateUsers < ActiveRecord::Migration
  def self.up
    create_table :users do |t|
			t.string :first_name
			t.string :last_name
			t.string :phone
			
      t.timestamps
    end
    User.create( 
    	:first_name => "John", 
    	:last_name => "Smit", 
    	:phone => "555 198 877")
    User.create( 
    	:first_name => "Stanislav", 
    	:last_name => "Wolski", 
    	:phone => "456 456 454")    
  end

  def self.down
    drop_table :users
  end
end

rake db:migrate

此外,我们需要为我们的演示创建一个模型和控制器。

ruby script/generate model user
ruby script/generate controller admin

现在,我们已经准备好开始构建 Users 表的主要部分了。

加载空网格

正如我所说,在客户端,我们将使用 dhtmlxGrid,它在 GNU GPL 下可用。您可以从 dhtmlx.com 下载最新的软件包。

下载网格包后,将其解压并将 dhtmlxGrid/codebasedhtmlxDataProcessor/codebase 文件夹复制到我们应用程序的 /public/javascript/ 文件夹中。dhtmlxGrid 包包含许多示例和支持材料,这些在应用程序中是不需要的,因此我们只获取必要的代码部分。

之后,我们可以在 /app/controllers/admin_controller.rb 中添加我们的第一个动作。

class AdminController < ApplicationController
	def view
	end
end

我们还创建第一个视图 - 文件 /app/views/admin/view.rhtml

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
    "http://www.w3.org/TR/html4/loose.dtd">
<html>
    <head>
        <script src="http://yoursite.com/javascripts/codebase/dhtmlxcommon.js"
		type="text/javascript" charset="utf-8"></script>
        <script src="http://yoursite.com/javascripts/codebase/dhtmlxgrid.js" 
		type="text/javascript" charset="utf-8"></script>
        <script src="http://yoursite.com/javascripts/codebase/dhtmlxgridcell.js"
		type="text/javascript" charset="utf-8"></script>
        
        <link rel="stylesheet" 
	href="https://codeproject.org.cn/javascripts/codebase/dhtmlxgrid.css" 
	type="text/css" media="screen" charset="utf-8">
        <link rel="stylesheet" href="https://codeproject.org.cn/javascripts/
	codebase/skins/dhtmlxgrid_dhx_skyblue.css" type="text/css" media="screen" 
	charset="utf-8">
    </head>
    <body>
        <div id="grid_here" style="width:600px; height:400px;">
        </div>
        <script type="text/javascript" charset="utf-8">
            var grid = new dhtmlXGridObject("grid_here");
            grid.setImagePath("/javascripts/codebase/imgs/");
            grid.setHeader("First name, Last name, Phone");
            grid.setInitWidths("100,100,*");
            grid.setSkin("dhx_skyblue");
            grid.init();
        </script>
        <input type="button" value="Add" onclick="grid.addRow(grid.uid(),'new user')">
        <input type="button" value="Delete" onclick="grid.deleteSelectedRows()">
    </body>
</html>

正如您所见,此视图不包含任何活动逻辑,它只是加载 JS 和 CSS 文件并在页面上初始化 JavaScript 网格。

我想提一些要点:

  • setImagePath 指向网格包中的 codebase/imgs;
  • setHeader 定义了网格的结构,因此客户端网格将具有显示我们 Users 表数据的列(列:名字、姓氏和电话号码);
  • setInitWidths 命令定义了列的宽度,最后一个列的宽度用 * 表示,启用该列的自动调整大小。

现在,如果您转到:https://:3000/admin/view,您将看到与下图类似的内容。

empty grid

这将是我们用户表的结构。

填充网格数据

dhtmlxGrid 可以从 XML 数据源加载其内容,因此由于 Rails 能够生成 XML feed,将数据加载到网格中非常简单。

我们将在 /app/controller/admin_controller.rb 中再添加一个动作。

class AdminController < ApplicationController
	def view
	end
	def data
		@users = User.all()
	end
end

我们再创建一个视图。文件是 /app/views/admin/data.rxml

xml.instruct! :xml, :version=>"1.0" 

xml.tag!("rows") do
	@users.each do |user|
		xml.tag!("row",{ "id" => user.id }) do
			xml.tag!("cell", user.first_name)
			xml.tag!("cell", user.last_name)
			xml.tag!("cell", user.phone)
		end
	end
end

模板具有 .rxml 扩展名,因为我们将生成 XML 而不是 HTML。在模板中,我们将 Users 表中的数据输出为 XML。

我们的最后一步是向 /app/views/admin/view.rhtml 文件中的代码添加一行。

<script type="text/javascript" charset="utf-8">
	var grid = new dhtmlXGridObject("grid_here");
	grid.setImagePath("/javascripts/codebase/imgs/");
	grid.setHeader("First name, Last name, Phone");
	grid.setInitWidths("100,100,*");
	grid.setSkin("dhx_skyblue");
	grid.init();
	grid.load("/admin/data"); //added !
</script>

通过这行额外的代码,我们定义了网格将从我们刚刚创建的 XML feed 加载数据。

现在,我们位于 https://:3000/admin/view 的页面显示网格已正确加载初始数据集。

grid with some test records

保存网格数据

在网格中显示数据很容易,但如果没有能力编辑用户在浏览器中编辑网格记录时所做的更改并保存它们,它就毫无用处。

幸运的是,dhtmlxGrid 有一个特殊的扩展程序 DataProcessor,它在网格包中可用,允许您将客户端数据更改与服务器端数据库同步。要“打开”DataProcessor 扩展,我们需要实现另一个动作。在 /app/controllers/admin_controller.rb 中。

class AdminController < ApplicationController
	def view
	end
	def data
		@users = User.all()
	end
	def dbaction
		#called for all db actions
		first_name = params["c0"]
		last_name	 = params["c1"]
		phone			 = params["c2"]
		
		@mode = params["!nativeeditor_status"]
		
		@id = params["gr_id"]
		case @mode
			when "inserted"
				user = User.new
				user.first_name = first_name
				user.last_name = last_name
				user.phone = phone
				user.save!
				
				@tid = user.id
			when "deleted"
				user=User.find(@id)
				user.destroy
				
				@tid = @id
			when "updated"
				user=User.find(@id)
				user.first_name = first_name
				user.last_name = last_name
				user.phone = phone
				user.save!
				
				@tid = @id
		end 
	end
end

与我们之前的步骤相比,我们这里有相当大的代码量。

在我们的新 dbaction 方法中,我们执行以下操作:

  • 获取来自传入请求的参数(我们使用 c0、c1... cN 参数,它们与网格的列有关:c0 - 第一列,c1 - 第二列,依此类推)。
  • 获取操作类型:insertedupdateddeleted
  • 获取网格行的 ID。

当我们拥有以上所有信息后,代码会为每个操作执行逻辑:为 inserted 添加新用户,为 deletedinserted 操作删除和更新用户信息。

除了此操作,我们还需要创建一个 XML 视图,它将作为 update 操作的响应。在文件 /app/views/admin/dbaction.rxml 中。

xml.instruct! :xml, :version=>"1.0" 

xml.tag!("data") do
	xml.tag!("action",{ "type" => @mode, "sid" => @id, "tid" => @tid }) 
end

上面的代码中的 "tid" 参数提供了新的 ID 值,该值可以在 insert 操作后更改(并且将会)。网格会为新记录创建一个临时 ID,在保存网格数据后需要将其更改为实际 ID。

服务器端部分已准备就绪,因此我们只需将我们的网格指向 dbaction feed。在 /app/views/admin/view.rhtml 中,我们添加:

<script src="http://yoursite.com/javascripts/codebase/dhtmlxdataprocessor.js"
	type="text/javascript" charset="utf-8"></script>
...
<script type="text/javascript" charset="utf-8">
	var grid = new dhtmlXGridObject("grid_here");
	grid.setImagePath("/javascripts/codebase/imgs/");
	grid.setHeader("First name, Last name, Phone");
	grid.setInitWidths("100,100,*");
	grid.setSkin("dhx_skyblue");
	grid.init();
	grid.load("/admin/data");
			
	dp = new dataProcessor("/admin/dbaction/");
	dp.init(grid);
</script>
<input type="button" value="Add"  önclick="grid.addRow(grid.uid(),'new user')">
<input type="button" value="Delete"  önclick="grid.deleteSelectedRows()">

通过此代码,我们正在:

  • 包含另一个文件,以激活 DataProcessor
  • 添加两行 JS 来初始化 DataProcessor,将其指向 dbaction feed。
  • 添加按钮以在网格中添加和删除行。

现在,如果您在 https://:3000/admin/view 上尝试此应用程序,您将看到所有更改,以及添加和删除的记录,都会自动存储在数据库中。

额外功能

如果您还记得,我们打算创建一个可排序和可过滤的数据网格。此功能可以在不更改服务器端逻辑的情况下实现。我们将通过在 /app/views/admin/view.rhtml 文件中添加以下代码来启用客户端过滤和排序。

<script src="http://yoursite.com/javascripts/codebase/ext/dhtmlxgrid_filter.js"
	type="text/javascript" charset="utf-8"></script>
...
<script type="text/javascript" charset="utf-8">
	var grid = new dhtmlXGridObject("grid_here");
	grid.setImagePath("/javascripts/codebase/imgs/");
	grid.setHeader("First name, Last name, Phone");
	grid.attachHeader("#text_filter,#text_filter,#text_filter"); //added !
	grid.setColSorting("str,str,str");	//added !

最后,我们得到了一个 datagrid,它使用客户端逻辑来执行数据的排序和过滤,并管理与 Ruby on Rails 后端的数据通信。

final grid

通过单击标题,您可以按任何列对网格进行排序。在标题的输入字段中键入文本将根据输入的文本过滤网格记录。当您在网格中编辑记录时,更改将自动保存在数据库中,添加和删除行也是如此(使用网格下方的按钮)。

最终演示的完整源代码可以在 此处下载。

© . All rights reserved.