1 // /<reference path="vswd-ext_2.0.2.js" />
2 /*
3 *作者:大笨
4 *日期:2009-10-20
5 *版本:1.0
6 *博客地址:http://yage.cnblogs.com
7 *QQ:14202190
8 */
9 Ext.BLANK_IMAGE_URL = ' ../extjs/resources/images/default/s.gif ' ;
10
11 Ext.onReady( function () {
12 Ext.QuickTips.init();
13
14 // 格式化日期
15 function formatDate(value) {
16 return value ? value.dateFormat( ' Y年m月d日 ' ) : '' ;
17 }
18
19 // 别名
20 var fm = Ext.form;
21
22 // 构造一个只能包含checkbox的列
23 var checkColumn = new Ext.grid.CheckColumn( {
24 header: ' Indoor? ' ,
25 dataIndex: ' indoor ' ,
26 width: 55
27 } );
28
29 // 构造ColumnModel
30 var cm = new Ext.grid.ColumnModel( {
31 columns: [ {
32 id: ' common ' ,
33 header: ' Common Name ' ,
34 dataIndex: ' common ' ,
35 width: 220 ,
36 // 使用上边定义好的别名
37 editor: new fm.TextField( {
38 allowBlank: false
39 } )
40 } , {
41 header: ' Light ' ,
42 dataIndex: ' light ' ,
43 width: 130 ,
44 editor: new fm.ComboBox( {
45 typeAhead: true ,
46 triggerAction: ' all ' ,
47 transform: ' light ' ,
48 lazyRender: true ,
49 listClass: ' x-combo-list-small '
50 } )
51 } , {
52 header: ' Price ' ,
53 dataIndex: ' price ' ,
54 width: 70 ,
55 align: ' right ' ,
56 renderer: ' usMoney ' ,
57 editor: new fm.NumberField( {
58 allowBlank: false ,
59 allowNegative: false ,
60 maxValue: 100000
61 } )
62 } , {
63 header: ' Available ' ,
64 dataIndex: ' availDate ' ,
65 width: 95 ,
66 renderer: formatDate,
67 editor: new fm.DateField( {
68 format: ' Y年m月d日 ' ,
69 minValue: ' 01/01/06 ' ,
70 disabledDays: [ 0 , 6 ],
71 disabledDaysText: ' Plants are not available on the weekends '
72 } )
73 } ,
74 checkColumn
75 ],
76 defaults: {
77 sortable: true
78 }
79 } );
80
81
82 // 构造一个Store对象
83 var store = new Ext.data.Store( {
84
85 url: ' plants.xml ' ,
86
87 reader: new Ext.data.XmlReader(
88 {
89 record: ' plant '
90 } ,
91
92 [
93 { name: ' common ' , type: ' string ' } ,
94 { name: ' botanical ' , type: ' string ' } ,
95 { name: ' light ' } ,
96 { name: ' price ' , type: ' float ' } ,
97 { name: ' availDate ' , mapping: ' availability ' , type: ' date ' , dateFormat: ' m/d/Y ' } ,
98 { name: ' indoor ' , type: ' bool ' }
99 ]
100 ),
101
102 sortInfo: { field: ' common ' , direction: ' ASC ' }
103 } );
104
105 // 构造可编辑的grid
106 var grid = new Ext.grid.EditorGridPanel( {
107 store: store,
108 cm: cm,
109 renderTo: ' grid ' ,
110 width: 600 ,
111 height: 300 ,
112 autoExpandColumn: ' common ' ,
113 title: ' Edit Plants? ' ,
114 frame: true ,
115 plugins: checkColumn,
116 clicksToEdit: 1 ,
117 listeners: {
118 " afterEdit " : {
119 fn: afterEdit,
120 scope: this
121 }
122 } ,
123 tbar: [ {
124 text: " 保存 " ,
125 handler: function () {
126 var modified = store.modified;
127 updateData(modified);
128 }
129 } ]
130 } );
131
132 // 触发数据的加载
133 store.load();
134
135 // 发送数据到服务器端进行更新
136 function updateData(modified) {
137 var json = [];
138 Ext.each(modified, function (item) {
139 json.push(item.data);
140 } );
141 if (json.length > 0 ) {
142 Ext.Ajax.request( {
143 url: " EditGrid.aspx " ,
144 params: { data: Ext.util.JSON.encode(json) } ,
145 method: " POST " ,
146 success: function (response) {
147 Ext.Msg.alert( " 信息 " , " 数据更新成功! " , function () { store.reload(); } );
148 } ,
149 failure: function (response) {
150 Ext.Msg.alert( " 警告 " , " 数据更新失败,请稍后再试! " );
151 }
152 } );
153 }
154 else {
155 Ext.Msg.alert( " 警告 " , " 没有任何需要更新的数据! " );
156 }
157 }
158
159 // 编辑后触发的事件,可在此进行数据有效性的验证
160 function afterEdit(e) {
161 if (e.field == " common " ) {
162 if (e.value == " 大笨 " ) {
163 Ext.Msg.alert( " 错误 " , "大笨是人物不是植物 " , function () { grid.startEditing(e.row, e.column) } );
164 }
165 }
166 }
167 } );
红色部分是新增加的代码,我们首先给grid增加了一个afterEdit事件,顾名思义,该事件在编辑之后被触发,我们可以在此时对数据的有效性进行验 证,在本例中,我们只是简单的让common列的值不能等于一个特定的字符串,实际的项目中可能需要对每一列用正则表达式来进行验证。在触发 afterEdit事件的时候会传递一个事件对象,该对象有如下几个属性:
grid:当前grid。
record:当前行。
field:当前列名。
value:被设置的值。
originalValue:编辑前的值。
row:行索引。
column:列索引。
我们还在grid上加了一个工具栏,上边放了一个保存按钮,用以将修改后的数据传递到服务器进行保存。由于记录的集合是一个复杂的json对象,我们需要 的只是相关数据的几个,因此第137-140行对该集合进行了处理。当然,我们还需要在服务器端接收数据然后进行处理,在系列一中我们已经学习到相关的方 法,这里不再赘述。我们看一看运行之后的效果图:
通过firebug,我们可以看到向服务器投递的数据:
接下来看看如何添加数据,我们在工具栏里边添加一个增加按钮,相关代码如下:

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

在向grid中插入数据之前,必须要先获得插入数据的格式,Store类的recordType属性返回Record的构造函数,表明了数据的格式,然后 通过构造函数传递数据,这样就准备好了要插入的数据了。接下来将grid的编辑状态关闭,插入数据,然后把要插入数据的第一列设置为编辑状态。运行后点击 增加按钮后的效果如下:
可以看到,在grid的最上边增加了一行,对应行索引0,第一列出于编辑状态,对应列索引1,增加行中的默认初始数据就是我们在构造函数中传递进来的数据。注意,新增加的数据在修改之前是不会保存在store的modified属性里边的。
我们再来看看如何进行删除操作。在进行删除之前,我们必须要选择需要删除的行,grid有单元格选择模型和行选择模型两种,分别以类 CellSelectionModel和RowSelectionModel来表示,默认是单元格选择模型,也就是在点击单元格的时候选中的是当前单元 格,可以通过配置属性selModle(可简写为sm)来指定选择模式:sm:new Ext.grid.RowSelectionModel({singleSelection:true}), 这样就把选择模型改为了行选择模型,参数singleSelect指明是否是单选的,为真的时候只能选择一行,默认是false,可以按下ctrl键或者 shift键进行多行的选择。选择好之后,我们就来看看如何删除吧:

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

我们先通过grid的getSelectionModel方法获得当前的选择模型,由于当前我们使用了行选择模型,所以返回的是 RowSelectionModel的对象,然后通过该对象的hasSelection方法判断有没有行呗选中,没有的话就弹出一个对话框,如果有选中的 行要被删除,弹出一个提示框让用户确定删除操作,如果确实要删除,使用RowSelectionModel对象的getSelections方法返回所有 被选择行的集合,遍历此集合,从store中去掉集合中的行。看看效果图:
点击“是”,所有选中的行被删除,通过firebug可以看到被删除的行在store的removed属性中保存。
但是有些人可能不习惯这里所谓的行选择模型,他们可能喜欢看到在每一行的前边有一个checkbox,勾选了之后表示选择该行,extjs中的 CheckboxSelectionModel类可以方便的让我们实现这一点,该类继承自RowSelectionModel,说明这只是一种特殊的行选 择模型。我们具体来看看怎么进行操作。首先需要定义一个CheckboxSelectionModel的对象:var sm=new Ext.grid.CheckboxSelctionModle({checkOnly:true}),这里chckOnly:true表明只能通过 checkbox来选择行,为false的话则还可以通过我们上边提到的方法来选择行。接下来需要把原来的行选择模型替换成我们新的sm,然后运行一下看 看吧。我们没有看到预期中的效果,这是为什么呢?仔细想一想,确实应该是看不到什么效果,我们知道列都是在ColumnModel里边配置的,我们的 CheckboxSelectionModel需要添加一列,自然也要在其中配置。那我们就加上去吧,完整的代码如下:

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167
168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

再运行一下看看,OK,我们想要的效果出来了:
最后我们来总结一下,当修改grid中的内容时,Store类的modified会自动将被修改的行保存下来;当删除的时候,Store类给我们提供了一 个 removed属性,但不知道为什么不自动保存删除的行,不过自己添加也很简单;增加是最麻烦的,我们可能需要一些小技巧来保存添加的行,无论是修改的还 是未修改的,可以都放到Store类的modified属性之中,也可以放在自己建的一个集合中,但是需要从modified里边去被添加之后修改的行。 无论是编辑,增加或者删除操作,都是在本地进行,需要自己写代码将改动发送到服务器端进行处理。