网格映射到一个MySQL表,使用直接和PHP第1部分
导言
在本教程中,我们将寻求在如何建立一个表,或“网格”,从一个MySQL数据库的数据接收。它旨在用JavaScript,PHP和MySQL的最大熟悉,但新的Ext JS框架的人。通过本教程结束时,我们将有一个网格组件,看起来像这样:
二。入门
1.1要求
你将需要:
- 用PHP(5.3±)和MySQL的服务器(4.1.3)安装
- 用Ext JS 4兼容的浏览器
- 一个文本编辑器
1.2什么是外部电网?
在Ext JS网格是“基本上增压的<TABLE>
“,引述其文档。它允许你通过排序和筛选,操纵数据,并获取新的数据,因此它远远超过你的表运行的轧机动态。正如你可以想像,这允许你做一些很酷的事情。
1.3什么是直接分机?
分机直接提供了一种方法,使用更少的代码,浏览器和服务器之间的通信比传统方法(如PHP)的实际数据做的东西。
1.4什么是这样做的好处?
有一些使用分机直接处理数据的好处:
- 这是与平台无关,所以它不会不管你使用PHP,Java或C#的数据服务。
- 您可以提供尽可能多的数据,只要你想,客户端没有负面影响。
- 它有3个类型的“供应商”,以不同的方式与服务器通信,我们将使用
RemotingProvider
。 - 它可以捆绑成一个单一的请求的AJAX请求(默认情况下,所有在第一10ms的发送者),所以只在服务器发回一个响应。
现在,我们已经全部被说服,让建设。
第三。设立
入门指南在强调一个Ext应用程序的最佳实践之后,我们可以设立一个index.html文件和一个空白的JavaScript文件名 为一个骨骼目录结构grid.js.
index.html的
<DOCTYPE HTML>
<HTML>
<HEAD>
<META HTTP-EQUIV = “内容类型”的 内容= “text / html的字符集= UTF-8” >
<TITLE> 迅猛业主名单</ TITLE>
< - -EXT
的JS - >
<脚本 的src = “grid.js” > </ SCRIPT>
<脚本 的src = “PHP / api.php” > </ SCRIPT>
</ HEAD>
<BODY>
</ BODY>
</ HTML>
因为我们使用了HTML5文档类型,我们可以省略在脚本标签的类型。它假定所有的<script>
标记的JavaScript,这有助于削减我们的字节。然而,你可能也注意到奇特api.php文件,肯定是不可能的JavaScript?所有将于解释。
现在,该指数指向所有正确的地方,解压缩到一个文件夹名为“EXTJS”EXT 4副本。我们现在准备开始构建应用程序。
四。编写应用程序
我们将开始写的东西给我们看,当我们开始尝试调试PHP应用程序的JavaScript部分。内grid.js,我们首先要声明的Ext框架的哪些部分,我们将处理,这将可能是ActionScript和Java用户一个熟悉的过程,但我们的休息,这是非常简单。因为我看到未来,我知道,我们将使用直接分机,分机数据和外部电网,以显示数据,所以我们需要以下:
grid.js
分机要求([
'Ext.direct *。' ,
'Ext.data *' ,
'Ext.grid *。'
]);
星号(“ *
在这种情况下)加载的Ext JS的这些领域内的所有类,我们可以在年底,我们使用的类只需要优化。然后,我们希望做一个漂亮的网格来看看,但首先,有轻微的题外话。
4.1模型和商店,概述
(如果你已经熟悉概念模型和商店,你可以跳过这一节)
用户呈现动态数据模型和商店是关键。一个“模型”是一个什么商店看起来像蓝图。说你有一个啤酒的菜单,该模型将确定什么样的标题,期望,在这种情况下,类型(啤酒,黑啤酒等),名称,价格,和ABV(酒精体积)。“商店”,然后将包含的个别属性,因此,类型:“啤酒”,名称:“宝石”,价格:4.00元,酒精含量:5.0%。商店可以在许多方面代表和来自许多地方,但最终被转换为与分机使用到JSON。
4.2返回到App
要创建一个模型,我们编写以下内容:
grid.js
分机定义(“PersonalInfo' , {
延长: “Ext.data.Model' ,
字段: [ 'ID' , '名' , '地址' , '国家' ]
});
我们在这里所做的是给它一个名称(PersonalInfo),告诉它这个延伸 Ext.data.Model(幸好我们并不需要编写所有必要的代码得到一个模型的工作,我们只是告诉它这扩展了Ext JS框架已经提供),并告诉它哪些领域(标题),我们打算向它提出的。所有令人兴奋的东西,我相信你一定会同意。
现在,我们不想呈现网格启动前的框架已加载的JavaScript,这是接近原生速度运行在浏览器的JavaScript越来越重要。为了解决这个问题,我们要使用Ext.onReady
,这将等待分机满载和DOM完全初始化之前,我们开始尝试把我们的电网。
grid.js
分机。onReady (函数() {
/ /创建
业主,
renderTo : 分机。getBody ()
});
});
DOM是准备一旦我们使用Ext.create
作出新的电网。网格需要一个商店,否则它不会有一个目的。我们将使用该模型我们前面定义与“PersonalInfo'的名称和使用的代理类型直接
告诉它,我们将使用分机直接给它一个商店。代理告诉我们将如何与存储通信的应用程序。有许多不同的类型,你可以在这里找到更多的信息。
然后,我们给电网与单柱宽度和文本的属性(数组中的包裹,我们将加入更晚)。可能不熟悉这里的唯一的部分是的dataIndex
-这是什么商店绑定列,所以它必须具有相同的名称。在这之后,一切都应该是不言自明,除了renderTo:Ext.getBody()
。这是一个函数,获取该文件的身体和电网连接。请记住,我们在包装这一切onReady
功能?就是这样,我们不要试图将其附加到<BODY>
前<BODY>
存在。
希望,你的努力将得到回报,这个时候你刷新页面:
4.3工作与MySQL
现在,我们有一个基本的网格工作中,我们将继续提供一些数据。对于我们的例子中,我们将上市的每个人都拥有在美国的迅猛。你会想到这是一个相当小的数据集-它不是。下载并执行这个SQL文件。,你知道是谁避开。声明,所有这些数据已自动生成虚拟数据的脚本,任何与现实相关,纯属巧合。
如果一切顺利,你现在应该有一个MySQL表有1000条记录,我们将在我们的网格显示填充。
在我们的应用程序的根目录,创建文件夹PHP
另一个里面它叫班
。在类中,创建称为文件QueryDatabase.php
。
我们将利用PHP的mysqli扩展的MySQL 4.1.3及以上(2004年中期以后发布的任何版本将做工精细)。
首先,我们将作出一个新的类,并声明一些变量:
QueryDatabase.php
< PHP
类 QueryDatabase
{
私人_db ;
保护_result
$结果 ;
}
在这个类中,我们要作出一个函数,将连接到数据库,(请注意,你不写...,它表示,这个代码块继续从最后一个)。
QueryDatabase.php
...
公共 函数__construct ()
{
$ _db = 新的mysqli ('主机' , '用户名' ,'密码' , '数据库' );
($ _db - > connect_error ) {
模具(“连接错误(' $ _db - > connect_errno 。 ')“ 。美元_db - > connect_error );
}
返回$ _db ;
}
第10行,取代'主机','用户名','密码'和“数据库”,与自己的配置。如果这一切看起来有点外国人给你,但你使用PHP,它使用被称为“面向对象编程的风格,你可以阅读更多关于它的网上。- > 被称为箭头操作,并从该对象的一个方法(即函数)。因此,我们呼吁,connect_error
和connect_errno
从功能的mysqli
对象与箭头商在此脚本。
我们也想关闭数据库连接,一旦我们用它做,这简直是足够做:
QueryDatabase.php
...
公共 功能__destruct ()
{
$ _db = $ 此- > __construct ();
$ _db - > ();
返回这个美元;
}
请注意,在我们已经把括号元_db
?这意味着,这个函数会想到一个参数传递给它的,即它预计美元_db
否则将不得不关闭无关。
现在我们已经有了一个连接到我们的数据库中的开幕式和闭幕式,我们可以查询。要做到这一点,我们将创建一个新的功能,被称为getResults。
QueryDatabase.php
公共的 功能getResults (美元的params )
{
$ _db = $ - > openConnection ();
$ _result = $ _db - > 查询(“SELECT ID,名称,地址,国家所有者” ) 或 死亡(“连接错误(' $ _db - > connect_errno 。 ')' 。$ _db - > connect_error );
结果= 阵列();
而 ($行= $ _result - > FETCH_ASSOC ()) {
array_push ($结果,$行);
}
$本- > closeConnection ($ _db );
返回$结果为何;
}
这都为我们的第一个PHP文件。总的来说,我们声明一些变量在类的顶部,然后做了3个功能,将帮助我们,因为我们扩大我们的应用程序。第一个函数的定义要使用的数据库访问它所需的凭据和失败,如果它无法连接(希望提供详细的错误消息)。第二个是一个简单的函数,关闭数据库连接。
第三个功能,使用功能从领域打开一个连接并查询数据库的所有记录:'ID','名','地址'和'国家'。我们也可以使用通配符运算符(The third function uses the first function to open a connection and queries the database for all of the records from the fields: 'id', 'name', 'address' and 'state'. We could have used the wildcard operator (**
)做同样的,但在较大的表,你可能只想显示领域的一个子集,所以最好单独指定他们。) to do the same, but in larger tables you'll probably only want to reveal a subset of fields so it's better to specify them individually. We then push all of the results into a an array called $results
in a while statement, close the connection to the database once we're done and return the results.
网格映射到一个MySQL表,使用直接和PHP第2部分
导言
在过去的教程中,我们创建拉一个网格,使用分机直接从MySQL数据库的信息。通过电源和电网的简单,我们创造了什么是本质上是一种荣耀的表(尽管“涡轮增压”)。要添加的活力,电网向我们提出,我们将添加CRUD(创建,读取,更新,删除)以及能力。一个典型的场景,从这个好处是后端接口,一个客户可能要更新某人的地址做什么,或重新命名的博客文章。我们已经得到了它从数据库中读取,所以我们一季度的方式有!
通过本教程结束时,我们应该有看起来像这样的东西。
二。入门
2.1需求
你将需要:
- 用PHP(5.3±)和MySQL的服务器(4.1.3)安装
- 用Ext JS 4和调试工具兼容的浏览器
- 一个文本编辑器
就我个人而言,我觉得用Firebug的Firefox最好的内线调试。
它强烈建议您在完成第1部分开始本教程之前,充分了解我们在做什么。在这里,我们将下面就可以找到的基本文件。
第三。编写应用程序
3.1的API
去年我们在这个系列教程从账面上,我们写了一个文件叫grid.js安置我们的外部应用程序的JavaScript部分。现在,如果我们要向前推进到这位勇敢CRUDing新的世界,我们需要做一些修改。
以前,我们定义了代理,但在商店单独保存记录,因为我们会做,会更有意义,它在我们的模型,定义PersonalInfo
。删除商店
内的代理
配置,我们将取代单一的直接函数(得到的结果)四大功能,将创建,读取,更新和删除。要做到这一点,需要以下:
grid.js
...
proxy: {
type: 'direct',
api: {
create: QueryDatabase.createRecord,
read: QueryDatabase.getResults,
update: QueryDatabase.updateRecords,
destroy: QueryDatabase.destroyRecord
}
},
所以应该不再是一个directFn
,它已经取代了一个更强大的API。写这告诉它,它是一类称为QueryDatabase和方法的名称(如createRecord
)。
虽然我们的编辑模式,一些你可能已经注意到在过去的教程,ID字段,排序时,显示一些奇怪的行为。我们没有设定一个ID类型,因此认为它是一个字符串,它引起的不排序依次。这可以固定,像这样的ID字段添加一个类型:
领域: [{ 名称: '身份证' ,类型: '诠释' , '名' , '地址' , '国家' ],
下一步,我们将在第一个教程中,我们补充揭露这些方法在我们的config.php文件,getResults
到我们的服务器端API,现在我们要增加我们其他的PHP函数的名称,我们将建立不久。
config.php文件
<?PHP
$API = array(
'QueryDatabase'=>array(
'methods'=>array(
'getResults'=>array(
'len'=>1
),
'createRecord'=>array(
'len'=>1
),
'updateRecords'=>array(
'len'=>1
),
'destroyRecord'=>array(
'len'=>1
)
)
)
);
3.2插件
回到grid.js,下方的商店
变量,我们要添加一个被称为电网的行编辑器插件。这将使叠加,使得它很简单,为用户更改字段的内容,就像这个样子:
grid.js
VAR rowEditing = 分机。创建(的“Ext.grid.plugin.RowEditing' , {
clicksToMoveEditor : 1 ,
autoCancel : 虚假
});
通过存储在一个变量的行编辑器,它会更容易引用,后来作为配置选项,clicksToMoveEditor
是多少次用户点击移动到不同的记录在我们的电网。autoCancel
意味着他们不能丢弃在移动之前的变化,将出现一个箭头指着说,他们需要先提交他们的修改记录。每当添加一个新的组件,它的价值就可以检查出相应的API文档,找出所有的配置可能性。
我们还需要指定每个领域,我们将要在网格编辑的字段类型,只需追加下面的名称,地址和状态列:
grid.js
...
文字: “名称”
字段: {
类型: '文本框' ,
allowBlank : 虚假
}
为状态栏,我们打算做一点点特别的东西,以及添加验证检查。
grid.js
...
字段:
类型: “文本框” ,
allowBlank : 虚假
vtype : '阿尔法'
}
vtype
代表验证类型,我们要求只允许从字母表中的字符,要进入到这个领域,没有一个国家有一个数字。
真正能够漂亮的行编辑界面,我们需要参考我们先前创建的插件来编辑我们的电网。网格内的变数仍然写:
grid.js
...
插件: [
rowEditing
]
但是,如果您尝试添加一个记录,并键入一个空格,一个国家,如纽约,你会发现,你不能键入空格,因为我们只允许字母表中的字符。为了解决这个问题,我们需要编写一个自定义vtype
。
以上我们的电网变量,创建一个新的变量称为alphaSpaceTest
,有趣的寻找后,这个字符串是一个正则表达式将只允许连字符,空格和字母。
grid.js
...
VAR alphaSpaceTest = / ^ [ - \ SA-ZA-Z的+ $ / ;
分机。申请(分机。形式。领域。VTypes , {
/ /验证vtype功能
alphaSpace : 功能(VAL ,场) {
返回alphaSpaceTest 。测试(VAL );
}
/ / vtype Text属性:错误文本时显示验证函数返回假
alphaSpaceText : '不是一个有效的状态,不能包含数字或特殊字符。' ,
/ /的vtype面膜财产:按键过滤口罩
alphaSpaceMask : / ^ [ - \ SA-ZA-Z] + $ /
}) ;
然后改变以前读vtype:α
vtype:alphaSpace
和我们将有两全其美的vtype 。
3.3用户界面
到目前为止,我们的网格看上去一点点稀疏,我们现在来加强了一下,并添加一些额外的控制,以最小的努力。在我们的网格
变量,我们要添加属性,将持有的所有信息我们华丽的UI dockedItems
。
grid.js
dockedItems : [{
的xtype : '工具' ,
码头: '底部' ,
}]
工具栏设置的xtype
将容纳的按钮,我们将稍后创建。您也可以尝试与码头试验,看你喜欢哪个位置(可能的值是顶部
,左
,右
和底部
),你甚至可以添加帧:真实的
,它只是一个优先事项。
3.4更新
现在我们要添加一个函数,将我们的MySQL表更新通过我们QueryDatabase.php文件。因为这是一个可以在一个会话中多次使用的功能,我们为它的使用和mysqli PREPARE语句的安全性和速度的改善。
QueryDatabase.php
...
公共的 功能updateRecords (stdClass的美元的params )
{
$ _db = $ - > __construct ();
($ stmt的= $ _db - > 准备(“??更新业主名称=,地址,国家= WHERE ID =” )) {
$ stmt的- > bind_param (SSSI“ ,名称,$地址,美元的状态,$ ID );
$ NAME = $的params - > 名称;
$地址= $的params - > 地址;
$状态= $的params - > 状态;
/ /施放ID为int
$ ID = (INT )美元的params - > ID ;
$ stmt的- > 执行();
$ stmt的- > ();
}
返回美元的params ;
}
bind_param
当我们说,我们告诉它的顺序和类型将出现在我们的变量,所以SSSI
意味着三个字符串和一个整数。略有反直观,那么,我们说这些变量是什么,并迫使$ ID
是一个整数,默认情况下它是因为它与外部直接解析的字符串。然后,我们执行的语句,并关闭它。
回到我们grid.js文件,我们要在最后加上触摸,使更新。一旦我们完成编辑行,编辑
事件被调用。我们将利用我们的优势,以保存记录,一旦它被编辑。网格
变量下面我们编写以下内容:
grid.js
网格。上(“编辑” 功能( E )
{ E 。纪录。保存();
});
变量
e 表示的属性与编辑事件数量。我们呼吁触发,要么createRecord
或updateRecords
在我们的内线直接代理的保存
方法。
你会看到,当你更新记录的值会出现一个小的,红的直角三角形上更新的领域,这意味着该记录是脏。肮脏的纪录,是一个具有从它的不同的价值originalValue
和需求,与实体店同步。一旦保存功能已经取得了成功,你应该找到三角形消失,并不再脏。注意使用分机的JS 4.0.2a,你会看到一个三角形不会被删除,这是固定在Ext JS的用户提供更高版本。
3.5创建
在生活中,创作是最复杂的过程,但与分机,我们将通过它没有太多的汗水。要在我们开始,我们要为用户添加一个按钮,点击添加记录dockedItems
。要做到这一点,我们做一个项目数组。
grid.js
...
项目: [
{
iconCls : '添加' ,
文本: “添加”
}]
在我们自己的CSS文件,给它一个合适的图标,,iconCls
将被引用。这仅仅是美学,使其正常工作,我们必须添加一个处理程序
,并洒了PHP。
一个处理程序
可以是一个函数变量的引用或包含了函数内联,在这种情况下,我已经做了它内联,但你可以安排所有的CRUD功能的顶部或底部和参考文件,它想处理程序:addRecord
。
grid.js
...
文字: '添加' ,
处理程序: 函数() {
rowEditing 。了CancelEdit ();
/ /从PersonalInfo创建一个空白记录
VAR 纪录= 分机创建(“PersonalInfo );
/ /插入顶部
商店。插入(0 记录);
/ / 0 行的编辑。startEdit (0 0 );
}
这个匿名函数的第一个取消编辑,如果正在编辑另一条记录,然后创建一个新的记录,从我们的模型PersonalInfo
,这为我们的姓名,地址和状态字段插入空值。然后,我们使用插入方法插入存储这个'幻影'记录,然后告诉行编辑器开始编辑的最高记录-我们插入的记录。
Ext是美妙的,它不能处理我们开放我们的QueryDatabase.php文件,我们要创建一个新的方法,将记录插入到数据库中的服务器端逻辑。
QueryDatabase.php
...
公共 功能createRecord (stdClass的美元的params )
{
$ _db = $ 此- > __construct ();
($ stmt的= $ _db - > 准备(“INSERT成为业主(姓名,地址,国家)VALUES(?? )?“ )) {
$ stmt的- > bind_param ('SSS' ,$的名称,$地址,$状态);
$name = $_db->real_escape_string($params->name);
$address = $_db->real_escape_string($params->address);
$state = $_db->real_escape_string($params->state);
$ stmt的- > 执行();
$ stmt的- > ();
}
返回美元的params ;
}
我们的方法名对应的名称,我们成立时宣布我们的API,即grid.js createRecord
,然后说,“数据类stdClass的(router.php)将分配给一个变量的params,这是为增加安全性使攻击不能被欺骗从另一个文件。有问题的数据看起来像这样:
这清楚地表明我们正在调用这些类和方法,包括一个JSON数据对象,我们访问我们的数据库中的各个字段。工贸
署 是在本次会议的POST请求的事务ID,所以这是第二次(第一次是当它加载数据)。
然后,我们准备我们的MySQL语句,正如我们以前所做的。问号挂到下一行,我们绑定参数,“SSS”
表示有三个变量都是字符串,然后映射之后,在执行前一定要逃脱输入到我们的数据库中,作为最后一个安全措施我们的查询。
在这个阶段,如果您添加新记录的ID字段将保持在0。如果你想解决这个问题,加元的params-> ID = $ _db> INSERT_ID;,
内createRecord
功能,之前返回
。这得到最后插入的ID和设置它的ID
,在美元的params
,然后返回用于电网。这个缺点是保存记录时,因为ID的变化,分 机ID字段解释为脏。
3.7的删除
破坏总是比创造更方便,下一节将教你如何成为一个分机湿婆。我们已经有一个按钮来添加所以现在我们要做的同一进程中删除,完成处理程序。
grid.js
...
}, {
iconCls: 'delete',
text: 'Delete',
handler: function() {
rowEditing.cancelEdit();
var sm = grid.getSelectionModel();
store.remove(sm.getSelection());
store.sync();
}
}
我们已经看到了前两个属性前增加,所以我要直接跳到我们正在做的处理程序
。我们得到摆脱的编辑覆盖,如果它是开放的,得到的记录已被电网选中,然后取出排的商店(使用选择模型)和最终同步的一切了,所以我们的数据库中是最多,最新的同我们的商店。
然后,我们需要编写相应的PHP片段从我们的MySQL数据库中删除记录。
QueryDatabase.php
...
公共 功能(stdClass的美元的params )
{
$ _db = $ - > __construct ();
$ ID = (INT )的params - > ID ;
(is_numeric ($ ID )) {
如果($ stmt的= $ _db - > 准备(“删去业主WHERE ID = 1的极限吗?” )) {
$ stmt的- > bind_param ('我' ,$ ID );
$ stmt的- > 执行();
$ stmt的- > ();
}
}
返回这个美元;
}
从我们抢ID
变量$的params
对象和检查,它是一个数字(而不是一些讨厌的SQL注入攻击)之前将它传递到我们的SQL语句。我们使用相同的PREPARE的方法,正如我们前面使用完全相同的方式工作。限制只有一条记录的声明,保证一次只有一个记录将被删除。
您现在应该能够添加,更新和删除记录,但我们并没有完全结束。
3.8 UX的:裸按钮和不良行为
注意到按钮看起来有点光秃秃的呢?添加一个图标,我们将写一些老学校的CSS。类是不是任意的,编码的按钮时,我们添加了一个的iconCls
到每一个,这增加了,我们现在在CSS中使用的类的名称。这里是一个zip文件图标。
style.css文件
{
背景: #ededed;
}
。附加{
背景:网址('图像/ add.png的' );
}
删除 {
背景:网址('图像/ delete.png的' );
}
当然,我们也有像这样在我们的index.html链接:
index.html的
...
< 链接rel = “ 样式” HREF = “style.css的” 类型= “文本/ CSS” >
只要下方的EXT的CSS文件,因为它是和在<HEAD>
标签,不要紧,你把它放在。
别的东西你可能已经注意到,永远和容易,这可能被错误做删除记录是多么容易。要少粗鲁给我们的用户,我们要添加一个对话框,确认删除。
确认删除的处理也不是很难的。首先,我们要找到我们的代码的一部分,涉及删去的东西-我们删除按钮的处理程序。第二,我们要分成两部分,破坏性和非破坏性行为的处理程序。前两行非破坏性的,所以我已经离开他们,使他们得到只要用户点击删除运行在顶部,但我们只希望删除和同步,当他们确认,这就是他们想要做的。
我们调用Ext.Msg.show
一些配置选项。的标题和消息是不言自明,按钮选项决定哪些按钮,用户将能够在这种情况下,点击“是”或“否”我们还增加了一个对话的图标,以便用户立即知道,一个他们的行动是必要继续。当用户决定FN
的选项并点击相应的按钮,我们可以检查哪一个是通过提供一个回调函数选择之一。这是功能(没有意外)的简写,并以同样的方式工作作为我们添加的处理程序和“删除”按钮,我们只需检查,如果他们说,(小写总是)是如果是这样,需要做什么。如果我们是非常好的,我们可以添加其他
和恢复他们的编辑,在他们离开的。
grid.js
...
处理程序: 函数() {
rowEditing 了CancelEdit ();
VAR SM = 网格的。getSelectionModel ();
分机。讯息。显示(
标题:删除记录?“ ,
味精: '你是永久删除一条记录,这不能撤消。
瞧,现在我们有一个不错的,用户友好的消息,确认他们的行动。
这就是它!你现在应该有一个全功能的网格,看起来像这样:
四。结论
在本教程中,我们已经讨论了很多地面。现在您应该知道如何实现分机直接从数据库中创建,读取,更新和删除。我们也看到了在容易分机上的应用有直接的影响,并创造更好的用户体验整体的对话和警报。
如果你要融入生产代码,你可以考虑如何优化使用分机装载机只加载的类,我们使用 “保存更改”按钮,在批次或过程的行动,以便永久性的变化不会立即。
最后,以供参考,你可以发现这里完成的源文件。
编辑的网格做的CRUD
第一部分:设置堆栈
网格面板是一个功能强大的方式来显示表格数据。这是一个从数据库中显示动态数据的理想解决方案。它也可以允许用户编辑网格中显示的数据。DataSet的更改,可以很容易地保存到服务器。本指南介绍了如何创建此功能使用Ext的MVC应用程序架构。如果你不熟悉,那么我建议你检查指导更多的细节。本教程的第一部分将包括设立客户端和服务器上的应用,在这里我们可以从数据库中读取数据,并显示在网格点。在第二部分中,创建,更新和删除在网格中的记录将被覆盖。
我们将构建一个数据库驱动的应用程序,所以我们需要:
- Web服务器
- 服务器端编程环境
- 数据库
传统上,这已经完成一个LAMP(Linux操作系统,Apache,MySQL和PHP)堆叠,或(在Windows)ASP.NET。本指南中,我已决定使用新块孩子:Node.js的。特别快车,基于节点的Web应用框架,提供了一个快速简便的方法,同时举办静态内容和一个现成的Web应用程序框架。至于数据库,MongoDB的,这需要使用SQL关系型数据库,如MySQL或Postgres提供了一个轻量级替代。所有这些技术都是基于JavaScript。
这个工具的一个限制是,它是目前不支持Windows。虽然节点正在被移植到Windows,这项工作尚未完成。此外,节点程序包管理器使用符号链接,如Unix的功能,根本没有目前Windows上工作。所以,如果你正在使用Windows,您将需要使用虚拟机运行Ubuntu(或其他Linux发行版)。VirtualBox和VMware的虚拟化解决方案都是免费的。如果您正在使用的Mac OS X或Linux,你将被罚款。
快速建立连接,这是一个SenchaLabs项目。这提供了一些保证,它不会消失明日(这可能是一个关注的东西这么年轻)。Node.js的是在用户数量,数字图书馆(模块),支持它的托管服务提供商的数量方面的增长十分迅速。联机文档是优秀的,也显然是非常有用的IRC社区。还有,应击中货架今年晚些时候在作品中的几本书。似乎MongoDB是作为最流行 的NoSQL数据库。
安装
而一个完整的节点,故宫,和MongoDB的安装,配置和使用指南,超出了本指南的范围是,这里是为我工作的命令。
Node.js的
我下载了最新的稳定的收入来源的包,在写作时是节点v0.4.11。存档下载文件夹中,然后执行以下命令:
焦油zxvf节点- V0 。4.11 。焦油。广州
CD节点- V0 4.11
/ 配置
使
sudo的安装
'做'的阶段,将需要几分钟。
故宫
故宫网站上的说明说,执行这个命令:
卷曲的http :/ / npmjs.org / install.sh | SH
出于某种原因,这不为我工作,甚至当我在它前面添加'sudo'的。所以我打破命令分为以下步骤:
wget的HTTP :/ / npmjs.org / install.sh
CHMOD + X 安装。SH
须藤/ 安装。SH
“wget的是类似卷曲,但有一点简单的使用,因为它只是下载到本地文件的URL。“apt-get的安装wget的',你可以安装在Ubuntu上,或者”wget的BREW安装在Mac上,如果您使用的是自制的。
MongoDB的
MongoDB的网站上的安装过程是有据可查的。它应该是可以的,但你的包管理系统。本指南稍后将讨论建立一个数据库的细节。
特快
现在,我们可以简单地使用故宫安装:
须藤故宫安装- G 快递
设立应用
表达自己!
我们将处理的示例数据集,是一套电脑爱好者喜欢的电影。这是一个见仁见智的问题,因此在编辑方面具有重要意义。因此,我们将调用演示程序“geekflicks”。作为快递网站上的指示,只需创建您的应用程序使用“快车”命令:
快递geekflicks
这应该输出,它创造了以下文件:
创建:geekflicks
创建:geekflicks / 包。JSON
创建:geekflicks / 应用程序。JS
创建:geekflicks / 公众/ 使用javaScripts
创建:geekflicks / 公共/ 样式
创建:geekflicks / 公共/ 样式/ 风格。
创建:geekflicks / 公共/ 图像
创造:geekflicks / 意见
创建:geekflicks / 意见/ 布局。玉
创建:geekflicks / 视图/ 索引。
请注意,公共/目录是Ext JS的应用将生活在那里。为了完成设立快速应用程序,我们还需要从内“geekflicks”目录执行此命令:
故宫安装- D
这将安装额外的节点需要的软件包。“package.json”的文件,该文件默认情况下,看起来像这样的依赖关系的定义:
0.0.1“
} }
MongoDB数据库访问在我们NodeJS的应用程序,我选择使用猫鼬,它提供了一个很好的高层次的API。让我们添加作为明确在package.json文件的依赖,并改变我们的应用程序的名称,而我们在这:
{
“名称” : “geekflicks” ,“版本”
: “0.0.1” ,“私”
: 真正的
“依存关系” : {
“明示” : “2.4.6” ,“玉”
: “> = 0.0.1 “ ,
“猫鼬”, “> = 2.0.0”
} }
现在,如果我们重新执行“故宫安装d'命令,我们看到它拿起额外的依赖,并安装它。事实上在这里的是,在安装称为“node_modules”文件夹的依赖。他们没有安装全球,这意味着我们的应用程序都有其自己的副本,这些模块,这是一个很好的事情,因为它使您的系统上的全球节点模块独立。
要运行我们的webapp,进入“geekflicks”目录,并运行以下命令:
节点的应用程序。JS
应该说,在端口3000上运行的应用程序。如果你打开一个浏览器为http://localhost:3000,你应该看到一个页面的消息:“快报”和“快”。这是如何工作?嗯,在的geekflicks / app.js文件,有一个“路线如下定义:
/ /路由
应用。('/' , 函数 (REQ ,水库)
水库渲染(“指数” , {
标题: '快'
});
});
它说,每当一个请求,Web服务器的根,它应该呈现的意见“目录”索引“的模板,使用给定的数据对象。这玉的模板系统,使用捆绑成快递。虽然这是整齐的,我们希望它做的是重定向到内的“公共”文件夹,这是我们将建立我们的Ext JS的应用程序的index.html文件。使用重定向,我们可以做到这一点:
/ /路由
应用。('/' , 函数 (REQ ,水库)
水库重定向(“/ index.html的' );
});
创建Ext JS的应用
让我们为我们的Ext JS的应用在'公众'目录中所述,创建一个目录结构入门指南:
geekflicks /
公共/
应用程序/
控制器/
模型/
商店/
视图/
EXTJS
...
EXTJS /文件夹的ExtJS的4 SDK(或它的一个符号链接)。在GeekFlicks文件夹中,我们创建一个具有以下的index.html文件:
<!DOCTYPE HTML>
<HTML>
<HEAD>
<荟萃 字符集= “UTF-8” >
<TITLE> 可编辑
</ BODY>
</ HTML>
我建议使用HTML5的语法在这里,虽然这是没有必要的。此外,请注意,我已经包含了“分机全debug.js'不是'ext.js”。这将确保所有的Ext JS类是可立即,而不是动态地加载每个类文件,这是会发生什么,如果你用“ext.js”(或EXT-debug.js),后加载的应用程序。网格确实需要大量的类,并趋于放慢初始页面加载,并弄乱了一堆类,这使得寻找自己的类更难类列表。然而MVC应用类确实需要启用装载机,它默认是禁用的,当您使用“内线所有的版本。所以我手动重新启用在这里。
app.js有:
怪才“ ,
HTML : 添加您最喜爱的古怪电影'
}]
});
} } );
所以如果你现在停止快速的网络服务器(打字发出“节点app.js”命令,在那里你在终端按Ctrl-C),并重新启动它(再次发出'的节点app.js“命令),并导航到HTTP: / /本地主机:3000(或刷新浏览器),你应该看到一个标题面板“怪才笔触”文本“您最喜爱的令人讨厌的电影”底下。如果没有,检查控制台的错误...... 或许是得到了错位。现在,我们仍然没有一个网格面板在视线内的任何地方,所以让我们的补救办法。
查看与视口
现在,让我们的应用程序设置的MVC组件,而不是在一个文件中有这一切。这将允许我们采取的Ext JS 4的应用程序框架的功能优势。创建一个可编辑的数据网格,被称为“电影”,在“意见”的文件夹,用下面的代码:
分机定义(“GeekFlicks.view.Movies' , {
延长: “Ext.grid.Panel” ,
别名: “widget.movieseditor”
的initComponent : 函数 () {
/ /硬编码存储静态数据
存储= {
字段: [ '标题' , '年' ,
数据: [{
标题: “黑客帝国” ,
一年: '1999'
}, {
标题: “星球大战:返回绝地,
一年: '1983'
}]
};
列= [{
头: “标题” ,
dataIndex : '标题' ,
柔性: 1
}, {
头: '年' ,
dataIndex : '年' ,
柔性: 1
}];
。callParent (参数);
} } );
这将创建一个新的视图类被称为“电影”延伸网格面板和硬编码在一家商店,这简直是声明为inline的一些数据。这将重构后,但足以让我们现在去。此外,代替的Viewport在app.js文件手动创建“启动”事件引发时,我们可以作为一个单独的类称为“Viewport.js”视图/文件夹中创建我们的应用程序的主视口。它包括电影查看我们刚刚创建的,使用它的xtype:
分机定义(“GeekFlicks.view.Viewport' , {
延长: “Ext.container.Viewport
布局: “适合” ,
项目: [{
的xtype : “面板的
标题: “前的所有时间”野人笔触,
物品: [{
的xtype : 'movieseditor'
}]
}]
});
在应用程序启动时自动加载的Viewport的顺序,我们设置“autoCreateViewport”属性真正在app.js(见下一节的上市)。
控制器
现在让我们创建的控制器,在“控制器”文件夹,如下:
分机。定义(的“GeekFlicks.controller.Movies” , {
延长: “Ext.app.Controller
意见:
“电影”
]
INIT : 函数 () {
控制({
“movieseditor” : {
渲染 。onEditorRender
}
});
}
onEditorRender : 函数 () {
控制台日志(“电影编辑器,渲染” );
} } );
此设置为我们刚刚创建的,包括在意见
阵列控制器。由应用程序启动时被自动调用的 init ()
方法。控制()
方法添加onEditorRender的
事件侦听选定ComponentQuery表达movieseditor
(选择组件的xtype,或“别名”),这是由电影编辑网格。这是很好的,因为它意味着不知道任何有关控制器(或模型),所以它可能会被重用在多个上下文的观点。
现在我们已经增加了视图和控制器听其事件。现在我们需要告诉它的应用。我们设置控制器的
阵列,包含电影
控制器。我们主要app.js文件现在这个样子。
分机。应用({
名称: “GeekFlicks” ,
appFolder : “应用程序” ,
autoCreateViewport : 真实,
控制器: [
'电影'
]
});
现在,当您刷新浏览器,你应该看到实际的网格面板的数据,我们硬编码到视图显示。下一步,我们将重构这使该数据加载动态。
模型
MVC的三位一体的模型元素组成的几类具体职责。它们分别是:
- 型号:定义数据架构(认为它是一个数据模型或对象模型)
- 存储:存储记录的数据(这是由模型定义)
- 代理:加载从服务器(或其他存储)的存储和保存更改
这些都涵盖在更详细的数据包指南。所以让我们确定我们的数据,通过创建第一Movie.js
的“模式”文件夹中的方法:
分机定义('GeekFlicks.model.Movie' , {
延长: “Ext.data.Model' ,
领域: [{
名称: '标题' ,
类型: '字符串'
}, {
名称: “今年,
类型: '诠释'
}]
});
然后,在商店/ Movies.js
,添加以下内容:
分机定义(“GeekFlicks.store.Movies' , {
延长: “的Ext.data.Store” ,
模型: “GeekFlicks.model.Movie
数据: [{
标题: “黑客帝国” ,
一年: '1999'
}, {
标题: “星球大战:绝地归来” ,
一年: '1983'
}]
});
这仅仅是从视图复制,它曾在initComponent()
方法。一个变化是,内联定义的领域,而不是我们刚刚创建的,在那里它们被定义的模型,有一个参考。现在清理的观点来引用我们的商店... 改变视图/ Movies.js
到的内容:
分机定义(“GeekFlicks.view.Movies' , {
延长: “Ext.grid.Panel” ,
别名: “widget.movieseditor”
商店: “电影” ,
initComponent : 函数 () {
/ /注:商店
。callParent (参数);
} } );
请注意,存储
配置属性设置为“电影”,这将导致在运行时被实例化,并分配到网格的电影商店的实例。
控制器还需要了解模型和存储,所以我们告诉他们增加几个配置项,命名(惊喜!)模型
和商店
:
分机。定义(的“GeekFlicks.controller.Movies” , {
延长: “Ext.app.Controller
型号: [ '电影' ,
商店: [ “电影” ],
意见: “电影” ],
INIT : 函数 () {
控制({
“movieseditor” : {
渲染 。onEditorRender
}
});
}
onEditorRender : 函数 () {
控制台日志(“电影编辑器,渲染” );
} } );
代理服务器
我们仍然有硬编码的数据在我们的商店,因此允许使用代理的修复程序。代理会从我们的快速应用程序加载的数据。具体来说,它会访问的URL /电影
。我们必须定义在路线geekflicks / app.js的
。这第一个版本只是回显了当前电影的JSON表示。下面是这条新航线的定义:
应用程序获得(/电影 功能 (REQ ,水库)
水库的contentType (“JSON” );
水库JSON ({
成功: 真实,
数据: [{
标题: “黑客帝国” ,
一年: 1999年
},
标题: “星球大战:绝地归来” ,
一年: 1983年
}]
});
});
这里的格式是显着的:JSON响应必须是一个单一的对象,成功的
财产,和一个数据
属性,这是一个记录匹配的模型的定义数组。其实你可以自定义这些属性通过配置您的代理的读者
不同,但重要的是服务器发送的相同的名称,读者期待。现在,这个数据仍然是硬编码-只是在服务器端。在下一节,我们将阅读本数据库。但至少我们可以从我们的商店中删除硬编码数据,并更换代理的定义:
分机定义(“GeekFlicks.store.Movies' , {
延长: “Ext.data.Store”
自动加载: 真,
字段: [ '标题' , '年' ,
/ /数据删除,而不是使用
如果你重新启动服务器的应用程序,并重新加载页面,你应该看到它与前两个电影网格。
建立数据库
我们是真正的动态和交互式的应用程序,我们需要一个数据库来存储我们的电影,由于其简单和JavaScript语法英寸,我们将使用这个演示MongoDB的。如果你还没有安装,在开始本指南描述,你应该做的,现在。一旦你的MongoDB的
守护进程运行,键入蒙戈
将投入到MongoDB的控制台,你可以创建一个新的数据库和集合(类似于在SQL表)。然后,您可以使用一个很好的JavaScript API插入预设的电影,如下(您刚刚开始“>”,这是蒙戈提示行上键入的命令。)
$蒙戈
MongoDB的外壳版本: 2.0 0
连接到:测试
使用的例子。
切换到DB的例子
> DB 。电影。插入({ 标题: “黑客帝国” ,一年: 1999 });
> DB 。电影。插入({ 标题: “星球大战” ,一年: 1977 });
> DB 。电影。找到()
{ “的_id” : 的ObjectId (“4e7018a79abdbdfb5d235b6c” ),“标题” : “黑客帝国” , “年” : 1999年 }
{ “的_id” 的ObjectId (的“4e7018dd9abdbdfb5d235b6d” ),“称号” : “星球大战” , “年“ : 1977 }
> 退出()
找到()命令是像SQL SELECT *
。它返回的收集,确认加入该行如预期的所有成员。请注意,他们也被赋予一个唯一的ID。现在,在数据库中的数据是,我们只需要与我们的节点的JS应用中拉出来。这可以通过使用猫鼬定义一个模型,然后修改/电影
路线app.js
查询:
VAR 猫鼬= 要求(“猫鼬” ),
DB = 猫鼬。连接(mongodb的:/ / 127.0.0.1/example“ ),
/ /创建的电影模式,使用“电影”作为数据源收集
movieModel = 猫鼬。模型(“电影” , 新的猫鼬。架构({
标题: 字符串,
一年: 数
}));
/ / ...
app.get('/movies', function (req, res) {
movieModel.find({}, function (err, movies) {
res.contentType('json');
res.json({
success: true,
data: movies
});
});
});
重新启动服务器后(这将需要进行服务器代码看到任何变化,但不改变后的Ext JS代码)我们的应用程序的索引页会显示我们进入到数据库上面的电影。注意:星球大战电影的标题和日期的变化。这是什么应用程序应该在这一点上,如:
诚然,这是不是很兴奋,因为它只是从数据库中的数据显示。然而,我们已成立一个完整的网络协议栈,从数据库到UI,使用NodeJS和Ext JS的应用框架。现在,我们正处在一个很好的位置,添加更多功能的应用程序,特别是创造了新的电影,更新或删除现有的。这将在本教程的第二部分。