понедельник, 9 апреля 2007 г.

Apex. Создаем Master - Detail страницу.

Классическим примером для любого средства разработки интерфейса к БД является отражение связи "родитель-потомок" (Mater-Detail). Не будем нарушать традиций и попробуем реализовать данную функциональность в Oracle Application Express.


Для примера будем использовать системную таблицу - Object_Type. Суть приложения будет заключаться в том, чтобы в главной части формы выводить типы имеющихся в БД объектов, а в подчиненной - названия объектов выбранного типа.

Для начала необходимо создать новое приложение. Для этого, выбрать "Application Builder -> Create Application -> Create Application" на главной странице Oracle Application Express:



Далее, указать название приложения ("MasterDetail"), выбрать новую модель ("From scratch") и название Oracle схемы:



Следующим шагом будет добавление новой (пустой) страницы в приложение. Назовем ее "Main":



После этого, решаем, нужны ли закладки в приложении - не нужны:

На следующем шаге мастера построения приложений, указываем, что никаких компонент из других приложений копировать не надо:


Далее выбираем схему аутентификации пользователей. Так как приложение демонстрационное, то никаких ограничений не нужно:


На следующем шаге создания приложения выбираем схему оформления (выбрали 17ую схему) и на последнем шаге подтверждаем создание приложения.

Следующим шагом в создании Master-Detail формы будет уже непосредственно редактирование графического интерфейса и добавление небольшой логики в приложение. Сразу после создания приложения, описание первой страницы выглядит следующим образом:



Добавляем следующие элементы графического интерфейса на первую страницу:

  • Создаем регион, в котором будут выводиться все типы объектов, имеющиеся в схеме:

    • Region type: "Report"
    • Report Implementation: "SQL Report"
    • Title: "Типы объектов"
    • Region Template: "Reports Region"
    • Display Point: "Page Template Body (3. items above region content)"
    • Source:
Select Object_Type, Count(*)
From User_Objects
Group By Object_Type

  • Добавляем невидимый элемент управления, который будет хранить название типа, для которого необходимо отразить объекты в подчиненной части страницы:
    • Item Type: "Hidden"
    • Item Name: "P1_TYPE"
    • Region: "Типы объектов"
    • Item Source: "- Not Computed -"
  • Создаем еще один регион, который будет выводить названия объектов, которые имеют заданный в главной части страницы тип. Указываем следующие атрибуты:
    • Region type: "Report"
    • Report Implementation: "SQL Report"
    • Title: "Названия объектов"
    • Region Template: "Reports Region"
    • Display Point: "Page Template Body (3. items above region content)"
    • Source:
Select object_name, created, status
From User_Objects
Where Object_Type = :P1_TYPE


    • Condition Type: "Value of Item in Expression 1 Is Not NULL"
    • Expression 1: "P1_TYPE"
Таким образом, на странице будут работать 2 отчета. Первый будет показывать все типы объектов схемы ("Типы объектов"). А второй ("Названия объектов") будет показывать все объекты заданного типа. Кроме того, второй отчет будет виден на странице только если есть значение в элементе P1_TYPE.

И последний штрих - добавим небольшой функционал в главную часть страницы - отчет
"Типы объектов": возможность выбора типа объекта. Для этого: переходим на страницу описания главного отчета:

Далее переходим к описанию столбца "COUNT(*)":

И в разделе "
Column Link" выставляем следующие значения для "Link Text", "Page", "Item Name", "Item Value":


Вот и все! Итоговая master-detail страничка должны выглядеть следующим образом:

Посмотреть приложение в работе можно на apex.oracle.com.

10 комментариев:

Zumbi комментирует...

Спасибо, матёрый человечище! Первый разумный пост про Apex для новичка, который я нашёл. :))

Timoshinin Evgeny комментирует...

Рад был помочь.

valvas комментирует...

Тоже преогромное спасибо!
ЗдОрово! Ничего лишнего и понятно!
Пиши еще!
;-)

Timoshinin Evgeny комментирует...

Предлагайте темы, в которых есть сомнения/трудности/вопросы ;).

valvas комментирует...

Вопросов много, может поможешь? Да и народу думаю полезно будет...
1) Можно ли реализовать одновременное редактирование нескольких строк? Скажем, выделили несколько строк товара и хотим изменить продавца их продавшего?
2) Можно ли реализовать добавление новых строк, с повтором значений определенных столбцов из предыдущей вставки. Например, оператору нужно заполнить данные суточных продаж. При этом, хотелось бы, чтобы при добавлении N строки не приходилось каждый раз вводить отдел и продавца, указанные при вводе строки №1? (желательно конечно, чтобы была возможность в настройке колонок указывать "Повторять при вставке", на подобии настройке сортировки)
3) В апексе есть возможность импорта данных из внешних источников (coma-separated file, Excel и т.д.). Можно ли в своем application реализовать данный функционал, чтобы оператор мог ежедневно производить загрузку внешних данных?

Пока что наверное хватит, а то больно нагло выходит...

Если возможно, очень буду рад советам! Спасибо!

Timoshinin Evgeny комментирует...

Привет. Извиняюсь за задержку. Был далеко от компьютера ;).

1) Можно ли реализовать одновременное редактирование нескольких строк? ... Да, можно. Если это Tabular Form, то у нее всегда есть checkbox'ы. Таким образом, рядом с этой формой можно сделать поле ввода и кнопку "Сменить продавца". По нажатию этой кнопки для всех строк, у кот. отмечен check-box, делать update.
Еще один вариант реализации многострочного редактирования описан на оф. сайте.

2) Можно ли реализовать добавление новых строк, с повтором значений определенных столбцов из предыдущей вставки...Да, это чистый JavaScript. Вот пример такой фичи . Там же есть ссылочки на обсуждения в форуме.

3) В апексе есть возможность импорта данных из внешних источников (coma-separated file, Excel и т.д.)...Да, такое тоже возможно. Есть такой Item - File Browse. Он отвечает за выбор файла пользователем. Все загруженный файлы будут лежать в таблице APEX_APPLICATION_FILES. Более детально загрузка файлов описана в документации.

valvas комментирует...

Добрый день! Огромнейшее спасибо за ценные советы! Можно еще вопрос над которым уже долго бьюсь?
Суть такова: есть табулар репорт с колонками ID страны, области, города и т.д. Пытаюсь организовать зависимые выпадающие списки. Т.е. при вводе страны отображать только ее области, для области только ее города и т.д.
Для этого в свойствах колонки репорта я задаю "Tabular Form Element"."Display As" = "Select List (query based LOV)", в разделе "List of Values" добавил текст запроса с Where строкой "area_id = :P14_AREA_ID", где P14_AREA_ID - созданный невидимый Item, у которого "Source Type"="Database column", "Source value or expression" = "AREA_ID" (поле запроса). В результате, в выпадающем списке вижу только лишь текущее значение. В чем может быть проблема? Подскажите плз!
Посмотрел массу примеров (Denes Kubicek и др.) Там есть реализация, но все используют доп. java script. Можно ли обойтись без этого? За ранее, огромное спасибо!

Timoshinin Evgeny комментирует...

Привет.

Для каскадного обновления LOV без полной перерисовки страницы, никакие средства, кроме JavaScript'a не помогут.

Я для этого использовал библиотечку ApexLib от Patrick'a Wolf ( Generic solution for cascading select lists/lovs ).

Вот еще пара веток обсуждений аналогичной проблемы на форуме oracle.com:
cascading LOV
Dynamic select list

А вот примеры реализации:
ApexLib Out-of-the-box cascading lovs
Ajax Select List

Анонимный комментирует...

как обнулить в запросе компонент P4_xxx
SELECT .... ....
WHERE field = :P4_xxx or :P4_xxx is null

таким образом некатит. поможешь, советом, пожалуйста

Анонимный комментирует...

ах да, и это ниспадающий список cbox