Build Tabular Forms for Multi-Row Operations

After completing this How-To, you should be able to understand how to:

Table of Contents

  • Enter the following Validation:

    for i in 1..htmldb_application.g_f01.count loop if htmldb_application.g_f01(i) is not null then if replace (htmldb_application.g_f03(i),'%'||'null%',null) is null then return 'Job must have some value.'; end if; if htmldb_application.g_f06(i) is null then return 'Hiredate must have some value.'; end if; if htmldb_application.g_f07(i) is null then return 'Sal must have some value.'; end if; if replace(htmldb_application.g_f09(i),'%'||'null%',null) is null then return 'Deptno must have some value.'; end if; else if htmldb_application.g_f02(i) is not null then if replace(htmldb_application.g_f03(i),'%'||'null%',null) is null then return 'Job must have some value.'; end if; if htmldb_application.g_f06(i) is null then return 'Hiredate must have some value.'; end if; if htmldb_application.g_f07(i) is null then return 'Sal must have some value.'; end if; if replace(htmldb_application.g_f09(i),'%'||'null%',null) is null then return 'Deptno must have some value.'; end if; end if; end if; end loop; 

    The tabular form does not keep the session state when the validation fails. You can use collections to save the user input by creating a process as follows:

    1. Navigate to the Page Definition containing the tabular form.
    2. Under Processes, click Create.
    3. Under Process Attributes, specify the following and click Next:
      1. Enter create collection as the process name.
      2. Select On Submit - Before Computations and Validations as the process point.
       declare la_cks wwv_flow_global.vc_arr2; begin if htmldb_application.g_fcs.count > 0 then la_cks := htmldb_application.g_fcs; else la_cks := htmldb_application.g_f10; end if; htmldb_collection.create_or_truncate_collection('UPDATE_EMP'); htmldb_collection.create_or_truncate_collection('INSERT_EMP'); for i in 1..htmldb_application.g_f01.count loop if htmldb_application.g_f01(i) is not null then htmldb_collection.add_member( p_collection_name => 'UPDATE_EMP', p_c001 => htmldb_application.g_f01(i), p_c002 => htmldb_application.g_f02(i), p_c003 => htmldb_application.g_f03(i), p_c004 => htmldb_application.g_f04(i), p_c005 => htmldb_application.g_f06(i), p_c006 => htmldb_application.g_f07(i), p_c007 => htmldb_application.g_f08(i), p_c008 => htmldb_application.g_f09(i), p_c009 => la_cks(i)); else htmldb_collection.add_member( p_collection_name => 'INSERT_EMP', p_c001 => htmldb_application.g_f01(i), p_c002 => htmldb_application.g_f02(i), p_c003 => htmldb_application.g_f03(i), p_c004 => htmldb_application.g_f04(i), p_c005 => htmldb_application.g_f06(i), p_c006 => htmldb_application.g_f07(i), p_c007 => htmldb_application.g_f08(i), p_c008 => htmldb_application.g_f09(i), p_c009 => la_cks(i)); end if; end loop; end; 

      In order to show session state of the tabular form, you need to display the tabular form the previously saved collection. To make this happen, we will create a new tabular form region as follows:

      1. Navigate to the Page Definition containing the tabular form.
      2. Under Regions, click Create.
      3. Select Report as region type and click Next.
      4. Under Report Implementatin, select SQL Report and click Next.
      5. Enter Update Emp as the region title and click Next.
      6. Enter the following SQL Query:

      select x.empno, x.ename, x.job, x.mgr, x.hiredate, x.sal, x.comm, x.deptno, x.cks from ( select htmldb_item.hidden(1,c001) empno, wwv_flow_item.display_and_save(2,c002) ename, htmldb_item.select_list_from_query(3,c003,'select distinct job, job from emp') job, htmldb_item.popupkey_from_query(4,c004,'select ename, empno from emp',10) mgr, wwv_flow_item.date_popup(6,null,c005) hiredate, htmldb_item.text(7,c006,10) sal, htmldb_item.text(8,c007,10) comm, htmldb_item.select_list_from_query(9,c008,'select dname, deptno from dept') deptno, htmldb_item.hidden(10,c009) cks from htmldb_collections where collection_name = 'UPDATE_EMP' union all select htmldb_item.hidden(1,c001) empno, htmldb_item.text(2,c002) ename, htmldb_item.select_list_from_query(3,c003,'select distinct job, job from emp') job, htmldb_item.popupkey_from_query(4,c004,'select ename, empno from emp',10) mgr, wwv_flow_item.date_popup(6,null,c005) hiredate, htmldb_item.text(7,c006,10) sal, htmldb_item.text(8,c007,10) comm, htmldb_item.select_list_from_query(9,c008,'select dname, deptno from dept') deptno, htmldb_item.hidden(10,c009) cks from htmldb_collections where collection_name = 'INSERT_EMP') x 
      1. For the Condition Type, select PL/SQL Expression.
      2. Enter the following as expression 1:
      htmldb_collection.collection_exists(p_collection_name => 'UPDATE_EMP') and htmldb_collection.collection_exists(p_collection_name => 'INSERT_EMP') 

      To submit the values from tabular form you created previously, you need to add a button.

      To add a button, follow these steps:

      1. Navigate to the Page Definition containing the tabular form.
      2. Under Buttons, click Create.
      3. From Region, select Update EMP 1.20.
      4. Select Create a button in a region position.
      5. Under Identify Button name and Label, enter the following and click Next:
        1. For Button Name, enter UPDATE_EMP2.
        2. For Label, enter Update Employee(s).
        1. For Postion, select Top of Region and click Next.
        2. For Branch to Page, select the page number containing the tabular form.

        Since you added a new region that displays tabular form from a collection, you need to change the update process to evaulate the checksum values from the new tabular form as well.

        To change the update process, follow these steps:

        1. Navigate to the Page Definition containing the tabular form.
        2. Under Processes, click Update EMP.
        3. Change the PL/SQL process as follows:

        declare l_cks wwv_flow_global.vc_arr2; j pls_integer := 1; begin -- -- Get original MD5 checksum -- select wwv_flow_item.md5(job,mgr,hiredate,sal,comm,deptno) cks BULK COLLECT INTO l_cks from emp; if htmldb_application.g_fcs.count > 0 then -- -- Compare the original checksum, l_cks, -- with submitted checksum, htmldb_application.g_fcs. -- If they are different, raise an error. -- for i in 1..l_cks.count loop if htmldb_application.g_fcs(i) != l_cks(i) then rollback; raise_application_error( -20001, 'Current version of data in database has changed '|| 'since user initiated update process.'); return; end if; end loop; else -- -- Compare the original checksum, l_cks, -- with submitted checksum from a collection, htmldb_application.g_f10. -- If they are different, raise an error. -- for i in 1..l_cks.count loop if htmldb_application.g_f10(i) != l_cks(i) then rollback; raise_application_error( -20001, 'Current version of data in database has changed '|| 'since user initiated update process.'); return; end if; end loop; end if; -- -- update EMP -- for i in 1..htmldb_application.g_f01.count loop if htmldb_application.g_f01(i) is not null then update emp set job = replace(htmldb_application.g_f03(i),'%'||'null%',NULL), mgr = replace(htmldb_application.g_f04(i),'%'||'null%',null), hiredate = htmldb_application.g_f06(i), sal = htmldb_application.g_f07(i), comm = htmldb_application.g_f08(i), deptno = replace(htmldb_application.g_f09(i),'%'||'null%',NULL) where empno = htmldb_application.g_f01(i); else if htmldb_application.g_f02(i) is not null then insert into emp (ename, job, mgr, hiredate, sal, comm, deptno) values (htmldb_application.g_f02(i), replace(htmldb_application.g_f03(i),'%'||'null%',NULL), replace(htmldb_application.g_f04(i),'%'||'null%',NULL), htmldb_application.g_f06(i), htmldb_application.g_f07(i), htmldb_application.g_f08(i), replace(htmldb_application.g_f09(i),'%'||'null%',NULL)); end if; end if; end loop; end; 

        Now the existing tabular form region from EMP table needs to display only when there is no existing collection. To accomplish this, you need to add a conditional display as follows:

        1. Navigate to the Page Definition containing the tabular form.
        2. Under Regions, click the first Update EMP region name.
        3. Under Conditional Processing:
          1. From Condition Type, select PL/SQL Expression.
          2. Enter the following as Expression 1 Value:

          not htmldb_collection.collection_exists(p_collection_name => 'UPDATE_EMP') and not htmldb_collection.collection_exists(p_collection_name => 'INSERT_EMP') 

          Next, you will create a before header process to delete the collection. This process will ensure the application will not display the tabular form from a collection when the page is rendered initially.

          To create a before header process:

          1. Navigate to the Page Definition containing the tabular form.
          2. Under Page Rendering Processes, click Create.
          3. Under Process Attributes,specify the following and click Next:
            1. For the name, enter delete collection.
            2. For the process point, select On Load - Before Header.
            htmldb_collection.delete_collection('UPDATE_EMP'); htmldb_collection.delete_collection('INSERT_EMP'); 
            1. From Condition Type, select PL/SQL Expression.
            2. Enter following in Expression 1:
            htmldb_collection.collection_exists('UPDATE_EMP') and htmldb_collection.collection_exists('INSERT_EMP') 

            Now try to update and insert employee records. It will validate user input and do optimistic locking before doing the update and insert (see Figure 9).

            Figure 9 - Tabular form with validation

            Discuss this how-to in the OTN HTML DB Forum.