We have all been there, we need to create an editable report and one of the columns contains a checkbox. So how should you handle this?
If you are using one of the recent APEX versions the easiest way is a tabular form. Just edit the column attributes of your checkbox column and at display as select “Simple Checkbox”. At the list of values definition type “Y,N”, where Y is the value the column will get when the checkbox is checked.
But what if you have multiple editable reports that have this requirement on one page? Then it starts to get interesting, since you can no longer use tabular forms.
With multiple editable reports we will be making our own editable report by using the API APEX_ITEM. You can read more about the APEX_ITEM API here.
We first create a report, and in our query we add our “active” column. We create two items there using the APEX_ITEM API: a checkbox and a hidden item. The parameter p_idx is the number that apex uses to identify the items and write them in an APEX collection when the page is submitted. This has to be unique on the page. We set the value of both items to the id of the column. Why we need these will become clear later on.
SELECT APEX_ITEM.HIDDEN(p_idx =>1, p_value => id)
||APEX_ITEM.CHECKBOX(p_idx => 2, p_value => id , p_attributes => DECODE(active,’Y’,’checked=”checked”‘, NULL)) active
Next we go to report attributes, edit our active column and set display as Standard Report Column. This will allow APEX to render this properly.
Before we precede let me explain how checkboxes work. In HTML a checkbox that is not checked has no value it is considered NULL. This is something you will have noticed when you create a checkbox page item in APEX in a form. So if we loop over our APEX collection containing the checkboxes we will only loop over the checkboxes that have a value. This is no issue when you only need it to delete rows, but let me show you what happens if you try to use it to update rows. Let’s assume we have two columns, one contains our ID, and one contains our Checkbox with value Y.
|APEX_ITEM.HIDDEN(p_idx => 1, p_value => id)||APEX_ITEM.CHECKBOX(p_idx => 2, p_value => ‘Y’)|
Assume we then loop over our first collection and do an update statement in our table:
FOR i in 1..APEX_APPLICATION.G_F01.COUNT LOOP
UPDATE MYTABLE SET active=NVL(APEX_APPLICATION07.G_F02(i),’N’)
WHERE id = APEX_APPLICATION.G_F01(i);
Looks correct doesn’t it? Well it isn’t. When our process goes over the first row it will update correctly. When he tries to update the 2nd row he will update it wrongly to ‘Y’. And the 3rd row will give an error. That is because our 2nd APEX collection only contains two rows. It does not contain the rows that are not checked.
So now that I explained the problem let’s have a look at the solution.
TYPE t_checkboxes IS TABLE OF VARCHAR2(1);
l_checkboxes t_checkboxes := t_checkboxes();
FOR i IN 1..APEX_APPLICATION.G_F01.COUNT LOOP
FOR j IN 1..APEX_APPLICATION.G_F02.COUNT LOOP
IF APEX_APPLICATION.G_F01(i) = APEX_APPLICATION.G_F02(j) THEN
l_yesno := ‘Y';
l_yesno := NVL(l_yesno,’N’);
l_checkboxes(i) := l_yesno;
l_yesno := ‘N';
FORALL i IN INDICES OF APEX_APPLICATION.G_F01
SET ACTIVE = l_checkboxes(i)
WHERE id = APEX_APPLICATION.G_F01(i);
We start by looping over our APEX collection containing our ID, inside that same loop we loop over the APEX collection with our checkboxes. Both contain as value our ID. If the values match, then the checkbox containing that ID has value ‘Y’. We insert this into a PL/SQL collection that we made for this purpose.
Lastly we do an update in our table, to set our new values. Notice how we only did one update statement using FORALL, and by doing so we limited our context switch to just one, and boosted our performance.
I now hope that everyone got a better idea of how they can deal with checkboxes rather easy, using only PL/SQL and APEX API’s.