2. Формирование JSON данных для TreePanel на сервере

advertisement
Mera, Tektronix
Ext.tree.TreePanel training
на примере проекта «test»
Нижний Новгород 2012
Contents
1.
Создание TreePanel............................................................................................................................................. 3
2.
Формирование JSON данных для TreePanel на сервере ................................................................................. 3
3.
Обработка кликов ............................................................................................................................................... 5
4.
Контекстное меню .............................................................................................................................................. 5
5.
Добавление/изменение/удаленение элементов. ........................................................................................... 6
a.
Добавление ..................................................................................................................................................... 6
b.
Изменение ....................................................................................................................................................... 7
c.
Удаление.......................................................................................................................................................... 7
1. Создание TreePanel
Основные параметры концигурации дерева:
- загрузчик дерева. Определяется полем «loader», загрузчик TreePanel определяется классом TreeLoader.
Для TreeLoader определяем url, значение которого будет использоваться загрузчиком для запроса данных
на сервер.
- корень.
var Tree = Ext.extend(Ext.tree.TreePanel, {
. . .
loader: new Ext.tree.TreeLoader({
url: 'application/getTree',
requestMethod: 'GET'
}),
. . .
root:{
nodeType: 'async',
text: 'mera',
orgid: '1'
},
. . .
});
Загрузчик делает Ajax – запрос на сервер по url: application/getTree
2. Формирование JSON данных для TreePanel на сервере
Запрос приходит на сервер и по правилам, определенным в файле /grails-app/conf/Url-Mappings.groovy
определяется, каким контроллерам и действиям должны направляться входящие запросы. URL
преобразуется по схеме «/controllerName/actionName/id».
class UrlMappings {
static mappings = {
"/$controller/$action?/$id?"{
Рассмотренный выше запрос направляется в контроллер «ApplicationController». Выполняется
действие – «getTree».
Метод «getItems» собирает коллекцию обьектов на основе данных из БД.
class ApplicationController {
. . .
def getTree = {
def items = getItems()
def inorg = items[0]
def ldep = items[1]
def lprj = items[2]
def ldev = items[3]
def res = getDepartmentTreeByOrg(inorg.id)
render res as JSON
}
. . .
}
Далее формируется набор данных с необходимыми полями для каждой конкретной сущности
(Organization/Department/Project/Developer). Формирование данных начинается с корневого элемента,
далее при инициализации поля «children» вызывается метод, формирующий данные по департаментам.
Для каждого элемента депертамента также определяются дочерние элементы в поле «children», и далее
для каждого проекта в «children» заносятся данные по разработчикам.
Для форматирования данных используется метод «collect», который выполняет обход коллекции,
применяя заданное замыкание.
def getDepartmentTreeByOrg(def orgid){
Organization org = Organization.get(orgid)
return Department.findAllByOrganization(org).collect{[depid:it.id.toString(),
text:it.name,
children: getProjectTreeByDep(it.id)
]}
}
Сформированные на стороне сервера данные в формате JSON могут выглядеть, как показано ниже:
[
{ "depid": "1", "text": "wac", "children": [
{ "prjid": "1", "text": "tektronix", "children": [
{ "devid": "1", "text": "alex", "leaf": "true" },
{ "devid": "2", "text": "tony", "leaf": "true" } ]
},
{ "prjid": "2", "text": "movius", "children": [
{ "devid": "3", "text": "sergey", "leaf": "true" } ]
}
]
},
{ "depid": "2", "text": "sig", "children": [] },
{ "depid": "3", "text": "uc", "children": [] }
]
Далее данные посылаются на сторону клиента.
- поле «…id» используется в качестве идентификатора элемента,
- поле «text» для отображения элемента в дереве,
- поле «leaf» для определения, является ли элемент «листом дерево», то есть нераскрываемым,
- поле «children» в качестве контейнера для дочерних элементов.
--- > дерево отображается в соответствющем виде.
3. Обработка кликов
Нажатие по элементу дерева порождает определенное событие (event).
Левый клик порождает event «click».
Правый клик порождает event «contextmenu».
Обработчики событий определяются в поле «listeners» :
var Tree = Ext.extend(Ext.tree.TreePanel, {
. . .
listeners:{
contextmenu: contextMenuActions,
click: function(node, e){
renderTo: Ext.getBody();
handler: getGridItems(node.id);
}
},
. . .
});
4. Контекстное меню
В данном проекте объект меню для дерева создаётся во время инициализации объекта дерева.
contextMenu: new Ext.menu.Menu({
items: [{itemId: 'add', text:'Add', handler: addItem},
{itemId: 'edit', text: 'Edit', handler: editItem},
{itemId: 'delete', text:'Delete', handler: deleteItem}],
id: "contextMenuID"
})
Обработчик правого клика настраивает меню в соответствии с типом элемента дерева, по которому
совершили клик. Элементы меню могут активироваться/дезактивироваться, может меняться текст меню и
т.д.
var contextMenuActions = function(node, evtObj)
{
node.select();
var ctxMenu = node.getOwnerTree().contextMenu;
. . .
var addItem = ctxMenu.getComponent('add');
var editItem = ctxMenu.getComponent('edit');
var deleteItem = ctxMenu.getComponent('delete');
. . .
// VISIBILITY
if (node.isRoot)
addItem.enable();
else{
. . .
5. Добавление/изменение/удаленение элементов.
Обработчики add/edit/delete назначаются для элементов контекстного меню дерева в поле «handler»:
contextMenu: new Ext.menu.Menu({
items: [{itemId: 'add', text:'Add', handler: addItem},
{itemId: 'edit', text: 'Edit', handler: editItem},
{itemId: 'delete', text:'Delete', handler: deleteItem}],
id: "contextMenuID"
})
a. Добавление
Действия обработчика добавления элемента:
1)Инициализировать набор элементов для формы ввода (TextArea, DateField…)
2)Создать объект формы, который служит контейнером для рассмотренных выше полей.
3)Добавить в форму необходимые кнопки.
4)Назначить обработчик нажатия кнопки вызывает метод submit формы, который посылает в Ajax запросе
введенные пользователем данные на сервер.
5)Описать обработку success/failure от сервера – добавить новый элемент в дереве, либо вывести
сообщение об ошибке.
6)Создать и отрисовать объект окна, которое служит контейнером для формы ввода.
var createAddForm = function()
{
var type_item = getTreeItemID();
var textarea = new Ext.form.TextField({. . .});
var addForm = new Ext.FormPanel({
url: 'application/create?'+type_item,
. . .
items: [textarea],
buttons: [{
text: 'Add',
handler: function() {
addForm.getForm().submit({
. . .
success: function(form, action) {
Ext.Msg.alert('Status', 'Action is successfully.');
. . .
},
failure: function(form,action){
Ext.Msg.alert('Status','Action is failed:'+action.result.errormsg);
. . .
}
});
}
}]
});
var createWindow = new Ext.Window({
. . .
items: addForm
});
createWindow.show();
};
b. Изменение
Процедура изменения элемента отличается от процедуры добавления тем, что формы ввода заполняются
соответствующими данными из базы данных. Для этого удобно сделать Ajax запрос на сервер для
получения информации по изменяемому элементу и всем полям ввода присвоить начальное
соответствующее значение.
var createEditForm = function(selNode)
{
Ext.Ajax.request({
url
: 'distributor/getElement',
params : {
node: selNode.id
},
success: function(response, opts) {
. . .
Далее процедура изменения повторяет процедуру добавления элемента: вызывается метод «submit»,
обрабатываются success/failure с сервера.
c. Удаление
Обработчик «удаления элемента» вызывает появление окна с предупреждающим сообщением на экране,
при подтвержденнии удаления на сервер посылается Ajax запрос на сервер на удаление элемента из базы
данных. Далее – обработка success/failure от сервера.
var deleteItem = function(ev){
. . .
Ext.Msg.show({
title:'Delete',
msg: 'item ['+devname+'] will be deleted. Are you sure?',
buttons: Ext.Msg.YESNO,
fn: function(buttonId,text){
if (buttonId == 'yes')
sendDeleteDevAjaxRequest(id,devname);
. . .
});
var sendDeleteDevAjaxRequest = function(id,devname){
Ext.Ajax.request({
url: 'application/delete?'+type_item,
success: function(response, opts){. . .}
failure: . . .
params: {node: node.id}
});
}
}
}
Download