среда, 21 апреля 2010 г.

ExtJS Tree в Apex

Просматривая темы на SQL.RU, набрел на пример использования Ext JS для отображения таблицы. Оказалось не так и сложно подружить Apex и Ext JS.Решил попробовать отобразить иерархические данные в виде дерева.  Стандартное дерево в Apex нельзя назвать удобным элементом управления. Постоянные обновления страницы при раскрытии/сворачивании элементов надоедают. Давно хотелось использовать дерево основанное на Ajax. И так, приступим.
Для начала необходимо выбрать источник данных. Будем использовать данные из таблицы DEMO_PAGE_HIERARCHY, создаваемой в числе прочих при установке демонстрационного приложения.
ExtJS имеет возможность асинхронно подгружать элементы дерева по мере раскрытия родительских элементов. Для этого необходим скрипт на http-сервере, который возвращает данные в формате понятном библиотеке ExtJS.
"Родным" форматом в этом случае является JSON, который понимается библиотекой без дополнительных телодвижений со стороны разработчика. Однако в Oracle 10g нет стандартных средств для работы с JSON. Поэтому обратимся за помощью к проекту PL/JSON, который предоставляет набор удобных средств для работы с JSON-данными. Установка PL/JSON затруднений не вызывает, инструкция есть в readme.txt.
Для работы страницы с деревом я написал простую процедуру, которая возвращает дочерние элементы дерева для элемента с заданным идентификатором, который передается в виде единственного параметра в процедуру:
CREATE OR REPLACE PROCEDURE TEST.GET_TREE_NODES(NODE NUMBER)
IS
  ITEM JSON;
  ITEM_LIST JSON_LIST := JSON_LIST();
BEGIN
  FOR REC IN(
    SELECT PAGE_ID ID, PAGE_NAME TEXT
      FROM DEMO_PAGE_HIERARCHY
     WHERE PARENT_PAGE_ID = NODE
  )
  LOOP
    ITEM := JSON();
    ITEM.PUT('id', REC.ID);
    ITEM.PUT('text', REC.TEXT);
    ITEM_LIST.ADD_ELEM(ITEM.TO_ANYDATA);
  END LOOP;
  HTP.P(ITEM_LIST.TO_CHAR());
END;

После этого необходимо предоставить права на запуск процедуры пользователю, от лица которого работает APEX (прописан в соответствующем DAD) и зарегистрировать в функции .wwv_flow_epg_include_mod_local
Здесь apex_owner - владелец схемы, в которую установлен APEX.

За основу javascript для определения объекта дерева был взят пример с сайта ExtJS и немного изменен. Представленный ниже текст нужно добавить в HTML Header страницы APEX. Первые 3 строки это подключение библиотеки Ext JS.

<link rel="stylesheet" type="text/css" href="http://localhost/ExtJS302/resources/css/ext-all.css">
<script src="http://localhost/ExtJS302/adapter/ext/ext-base.js"></script>
<script src="http://localhost/ExtJS302/ext-all-debug.js"></script>

<script type="text/javascript">
Ext.onReady(function(){
  Ext.BLANK_IMAGE_URL = 'http://localhost/images/s.gif';
  var PagesTreeLoader = new Ext.tree.TreeLoader({
        dataUrl   :"http://localhost:8080/apex/test.get_tree_nodes"
    });
var PagesTree = new Ext.tree.TreePanel({
        title            : 'Pages',
        collapsible      : false,
        animCollapse     : false,
        border           : true,
        id               : "tree_pages",
        el               : "mytree",
        autoScroll       : true,
        animate          : false,
        enableDD         : true,
        containerScroll  : true,
        height           : 500,
        width            : 400,
        loader           : PagesTreeLoader
    });

    var PagesTreeRoot = new Ext.tree.AsyncTreeNode({
        text        : 'Pages',
        draggable    : false,
        id        : '0'                  // this IS the id of the startnode
    });

 // Render the tree.
    PagesTree.setRootNode(PagesTreeRoot);
    PagesTree.render();
    PagesTree.expand();
});                  
</script>
Далее нужно создать HTML-регион, в Source которого нужно добавить следующее:

<div id="mytree">
</div>

Это будет служить контейнером для создаваемого дерева. Обратите внимание на строку:
dataUrl   :"http://localhost:8080/apex/test.get_tree_nodes"
Она указывает дереву, что обращаться за данными для формирования элементов нужно к процедуре GET_TREE_NODES, определенной выше.

Вот и все. Результат на картинке

Комментариев нет:

Отправить комментарий