1
votes

I am currently using oracle APEX 4.1 and have an issue with creating radiogroups dynamically.

I have a simple requirement(!) to display a list of questions from a table and display a yes/No radiogroup button next to each question. The list of questions may vary, so is not static.

To do this, I decided to create a plsql anonymous block and a sample of the code is below:

For c1 IN (select * from question)
LOOP
v_row:=v_row+1;
v_rowName:='F'||v_row;
v_radioYes:='<input type="radio" name='||v_rowName||'  value="yes" />Yes';
v_radioNo:='<input type="radio" name='||v_rowName||'  value="no" />No';
v_radio:=v_radioYes||' '||v_radioNo;
htp.p('<tr><td>'||v_row||'. '||c1.Question_text||'</td><td>'||v_type||'</tr>');
END LOOP;

So the questions are being displayed and the radiogroups are also being displayed next to each question.

My issue is that on submit, I need to find out what options a user has selected for each question and save to a database. Easy, but I cannot reference the radiobuttons for each question to find out what a user has checked. Ideally, these radio button should have been created using the APEX tool, but I could not get this to do in a loop dynamically. Is there a way of referencing these radiogroups that have been created dynamically? Am I taking the wrong approach?

2

2 Answers

2
votes

I have encountered almost the same problem recently. My solution to find the selected option was to add p_onchange parameter to APEX_ITEM.RADIOGROUP function invocation (refer to Apex 4.1 API Refernce). You can place any javascript code there. I have written a simple function to assign selected value to a hidden input field.

Here is the js function:

function put_selected_value(sel_value) { 
  $x('P66_SELECTED_VALUE').value=sel_value;
}

and RADIOGROUP

apex_item.RADIOGROUP(10, wrk_id, null, null, null, null, 
                     'javascript:put_selected_value(this.value);')
0
votes

Pfew. At first i thought this'd be a bit easier, but after mucking around a while i found radiogroups to be quite the toothgrinder. (this is on apex 4.1 btw)

Normally i'd respond that using apex_item would be the way to go to dynamically create items. However, radiogroups react with a twist.

If you'd use for example:

for r in(select level l, 'question '||level q, 'Y' a
           from dual 
        connect by level < 6)
loop
   htp.p('<div>'||r.q);
   htp.p(
      APEX_ITEM.TEXT(
       p_idx         => 1,
       p_value       => r.a,
       p_size        => 3,
       p_maxlength   => 1)
   );
   htp.p('</div>');
end loop;

The output would be:

<div>question 1
<input type="text" name="f01" size="3" maxlength="1" value="Y"  />
</div>
<div>question 2
<input type="text" name="f01" size="3" maxlength="1" value="Y"  />
</div>
<div>question 3
<input type="text" name="f01" size="3" maxlength="1" value="Y"  />
</div>
<div>question 4
<input type="text" name="f01" size="3" maxlength="1" value="Y"  />
</div>
<div>question 5
<input type="text" name="f01" size="3" maxlength="1" value="Y"  />
</div>

Great! 5 fields generated, accessible by using apex_application.g_F01 array, where field 1 would be apex_application.g_f01(1).

Radiogroups however react differenty. What APEX_ITEM.RADIOGROUP does is not actually creating a radiogroup, but creating a radiobutton. The group would then be the f01 array. Woah! I don't like that! The F## arrays only go from 1 to 50 to start with, so if you'd generate a few items, this is not ideal. Also, your logic gets screwed: suddenly you don't have to loop over an array anymore, but over arrays.

For example, the output would be like this if you'd replace apex_item.text with apex_item.radiogroup

<div>question 1
<input type="radio" name="f01" value="Y"   />Yes?
</div>
<div>question 2
<input type="radio" name="f01" value="Y"   />Yes?
</div>
<div>question 3
<input type="radio" name="f01" value="Y"   />Yes?
</div>
<div>question 4
<input type="radio" name="f01" value="Y"   />Yes?
</div>
<div>question 5
<input

It sort of did what you asked: it created a radiogroup consisting of the items. If you'd click the button at question 4 and question 1 was previously marked, the mark will be removed from question 1 and set to 4.

It works however. When you submit and loop over the F01 array, it'll pass the value along:

--this after submit process
for i in 1..apex_application.g_f01.count
loop
apex_debug_message.log_message('array F01: item '||i||': '||apex_application.g_f01(i));
end loop;

--results in this debug message:
--array F01: item 1: Y

Okay, so what are your options then? Don't use this. It is not dynamic! You can't loop over the 50 arrays, unless you write 50 loops over each array...

So how does APEX actually work then? When looking at the output code of a page item radiogroup, this is the output:

<input type="hidden" name="p_arg_names" value="50795996117686343389" />
<fieldset id="P3_RGROUP_PAGE_ITEM" tabindex="-1" class="radio_group">
<input type="radio" id="P3_RGROUP_PAGE_ITEM_0" name="p_t01" value="Yes" checked="checked"   />
<label for="P3_RGROUP_PAGE_ITEM_0">Y</label><br />
<input type="radio" id="P3_RGROUP_PAGE_ITEM_1" name="p_t01" value="No"    />
<label for="P3_RGROUP_PAGE_ITEM_1">N</label></fieldset>

See the hidden item? I assume apex puts the selected value in that hidden item, so you can easily reference the chosen value of the radiogroup.

This is probably the best way you can solve this. Generate your radiogroups and buttons and put the selected value in a hidden item using javascript. You can create the hidden item using apex_item.hidden, which you can thankfully refer to easily in an array afterwards. If you'd use p_idx => 1, all hidden items will be stored to array g_f01.

You'll just need to piggyback this hidden item in your radiogroup container. Then bind an onchange event to your radiobuttons. Example, look at this jsfiddle. This'll keep the selected value in the hidden item, which will be posted on submit.

Sorry for the lenghty post, i didn't think it'd get so complicated. Hopefully someone comes along and shows us an easy way :)