Oracle APEX: Interactive Report with Checkboxes

У цій статті описується процес створення в середовищі Oracle APEX сторінки c інтерактивним звітом, в якому можна відзначити запису для подальшої їх обробки. Передбачається,
що читач має базові знання про середовище розробки APEX і БД Oracle.

image
Звіт з можливістю позначки окремих записів для обробки — річ дуже зручна, але, на жаль, досі не реалізована «з коробки». В APEX API є функція apex_item.checkbox2 яка дозволяє показати у звіті чекбокси, але обробляти їх доводиться програмісту. Обробку сильно ускладнює те, що в багатосторінковому звіті чекбокси існують тільки для поточної сторінки, і при переходах між сторінками звіту значення зазначених чекбоксов потрібно десь зберігати. В даному випадку для цього використовується колекція APEX.

Кілька слів про колекції APEX. Колекція APEX — це іменована структура даних, існуюча в межах користувацької сесії, призначена для маніпуляцій з даними при побудові складних форм введення даних, майстрів тощо Колекція нагадує своєю структурою таблицю з 50 атрибутів типу VARCHAR2(4000), 5 атрибутів типу Number, 5 атрибутів типу Date, 1 атрибута типу XML, 1 атрибута типу BLOB і 1 атрибута типу СLOB. Працюють з колекцією через PL/SQL API APEX_COLLECTION.

Отже, на сторінці будемо використовувати такі хитрощі і трюки:

  • чекбокси в звіт додамо за допомогою функції apex_item.checkbox2.
  • зміна стану чекбокса будемо обробляти за допомогою javascript функції, що викликається з Dynamic Action.
  • зберігати стан чекбоксов будемо в колекції APEX, для цього будемо викликати AJAX-му OnDemand процедуру запису в колекцію.
Будемо вважати, що у нас вже є сторінка з інтерактивним звітом на базі запиту:

select id, name, descr from geo

де id — поле первинного ключа таблиці. Його ми будемо передавати в якості атрибута чекбокса в колекцію, та його будемо використовувати при обробці зазначених записів.

П. 1 Створимо процес на сторінку :

Create → Page Component → Process →
Process type: PL/SQL code
Name: AJAX_UpdateChBoxCollection
Point: Ajax Callback
PL/SQL Page Process заповнюємо наступним кодом:

declare
l_value varchar2(4000);
l_seq_id number := 0;
seq number := 0;
l_collection_name constant varchar2(30) := 'CHBOXCOLL';
begin
------------------------------------------------------------------
-- Get the value of the global var which was set by JavaScript
------------------------------------------------------------------
l_value := apex_application.g_x01; 
------------------------------------------------------------------------
-- If our collection named doesn't exist yet, create it
------------------------------------------------------------------------
if apex_collection.collection_exists( l_collection_name ) = FALSE then
apex_collection.create_collection( p_collection_name => l_collection_name );
end if;
---------------------------------------------------------------------
-- See if the specified value is already present in the collection
---------------------------------------------------------------------
for c1 in (select seq_id 
from apex_collections 
where collection_name = l_collection_name 
and c001 = l_value) loop
l_seq_id := c1.seq_id;
exit;
end loop;
-------------------------------------------------------------------
-- If the current value was not found in the colleciton, add it. 
-- Otherwise, delete it from the collection.
-------------------------------------------------------------------
-- Htp.Prn('Seq:'||l_seq_id);
if l_seq_id = 0 then
begin
seq := apex_collection.add_member( p_collection_name => l_collection_name,
p_c001 => l_value );
-- Htp.Prn(' Set:'||l_value||' seq_id:'||seq);
end; 
else
begin
apex_collection.delete_member( p_collection_name => l_collection_name,
p_seq => l_seq_id );
-- Htp.Prn(' Rst:'||l_value);
end; 
end if;
commit;
end;

Ця процедура створює колекцію з ім'ям «CHBOXCOLL» якщо вона ще не була створена,
і додає/вилучає запис в колекцію для змінила стан чекбокса. Назва колекції скрізь пишеться капсом. Воно повинно бути унікальним. В результаті у колекції будуть атрибути зазначених записів.

П. 2 Далі додамо на сторінку код javascript функції який буде викликати цей процес:

Edit Page → JavaScript → Function and Global Variable Declaration

function ajax_call_func(val) 
{ apex.server.process( "AJAX_UpdateChBoxCollection", 
{ x01: val}, 
{ dataType: "text",
success: function( pData ) 
{ console.log(pData); } 
}
);
};

Ця функція викличе раніше нами створену функцію з ім'ям «AJAX_UpdateChBoxCollection» і передасть їй значення «val» через глобальну змінну apex_application.g_x01.
Результат типу «text» може бути повернений з процедури «AJAX_UpdateChBoxCollection» при
допомогою функції Htp.Prn('якийсь результат').

П. 3 Створимо чекбокси у звіті, для цього відредагуємо запит наступним чином:

select apex_item.checkbox2(p_idx => 1,
p_value => id,
p_attributes => 'class="chbox_UpdColl"',
p_checked_values => a.c001) cbox,
id,name,descr
from geo,apex_collections a
where a.c001 (+)= id
and a.collection_name (+)= 'CHBOXCOLL'

В даному випадку запит додається колонка на базі функції apex_item.checkbox2,
а також наша колекція, пов'язана з нашою таблицею по id. Колекція нам потрібна лише для отримання стану чекбокса при початковій завантаженні сторінки і при переході між сторінками звіту. Тип колонки з чекбоксами повинен бути «Standart report column».

Коротко опишу використовувані параметри apex_item.checkbox2:

p_idx => 1

номер змінної APEX_APPLICATION 1 відповідає F01; 2 — F02 і тп.

p_value => id

значення, яке будемо передавати в колекцію, в даному випадку це поле «id» таблиці

p_attributes => 'class=«chbox_UpdColl»'

HTML-атрибути, в даному випадку використовується тег class=«chbox_UpdColl» що потім використовується в якості jQuery selector у Dynamic Action.

p_checked_values => a.c001

використовує значення з колекції для вказівки стану чекбокса

Для наочності додамо ще один звіт на базі Sql-запиту, який назвемо Collecton і який буде показувати нам вміст колекції:

select a.seq_id,a.c001
from apex_collections a
where a.collection_name (+)= 'CHBOXCOLL'

П. 4 Створимо Dynamic Action який буде спрацьовувати по зміні стану чекбокса і викликати створену у П. 3 JavaScript функцію:

Event: Змінити
Selection Type: jQuery Selector
jQuery Selector:.chbox_UpdColl
Condition: none

Action: Execute JavaScript Code
When Fire Event Result Is: True
Fire On Page Load: False
Code:

var
$checkBox = $(this.triggeringElement);
ajax_call_func( $checkBox.val() );

У полі jQuery Selector записується значення атрибуту 'class' з параметрів функції apex_item.checkbox2 у П. 3. Перед ним треба обов'язково поставити крапку.

У створений Dynamic Action додамо ще одна дія — оновлення звіту колекції після натискання на чекбокс:

Action: Refresh
Selection Type: Region
Region: Collecton

Функціонал чекбоксов вже працює, залишається тільки додати обробник зазначених чекбоксами записів. Приклад такого обробника з послідовним вилученням даних з колекції за допомогою курсору і запис їх у файл збираюся оформити у вигляді окремої статті.

Основна ідея почерпнута тут. Автор зберігає зазначені чекбокси списком у Item на сторінці.
Недолік — максимальна довжина зберігається списку — 4000 символів. Використання колекції в нашому випадку знімає це обмеження.

Про використання Ajax Callback в APEX добре написано тут.

Код тестувався на сайті apex.oracle.com на Application Express 5.1.0.00.45
Побажання і конструктивна критика вітається.
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.