Using ADF 11g (ADF Faces & ADF-BC) and Oracle XE (HR Schema)
At a number of occasions I have had to create a Table that would allow user to add new rows from values of existing table. For eg. Consider creating an order by searching and adding a product. In these cases we generally create a popup for searching product and add selected products to Order.






The source code can be downloaded from here
In this sample I will add employees from HR schema into a new table my_employees.

1. Create a new table in HR schema: my_employees

drop table my_employees

create table my_employees
(
id number primary key,
emp_id number,
creation_date date,
update_date date
)

create sequence my_employees_s
start with 1
increment by 1


2. In Model Project:
Create EO, Default VO and AM for tables employees and my_employees tables
Create AO between EmployeesEO and MyEmployeesEO. Also create Impl files for both EOs.
Create VL between EmployeesVO and MyEmployeesVO.




Add Name, email attributes to MyEmployeesVO from EmployeesEO to display Name and email of selected employees.






In the MyEmployeesEOImpl add the following code to create() method
    protected void create(AttributeList attributeList) {
        super.create(attributeList);
        SequenceImpl seq = new SequenceImpl("MY_EMPLOYEES_S", getDBTransaction());
        
        setId(seq.getSequenceNumber());
        setEmpId((Number)attributeList.getAttribute("EmpId"));
        //setEmpId(new Number(1));
    }

Add VOImpl and VORowImpl to EmployeesVO & MyEmployeesVO. This will be used in AM while creating new rows.

In
AppModuleAMImpl, create a method addSelectedEmployees(Key[] selectedEmp). WHY exactly the code uses Key[] will be clear once we create UI.
    public void addSelectedEmployees(Key[] selectedEmp) {
        for(Key key : selectedEmp) {
            try {
                //Either get the row using the key
                //Or since in this case, Key is employeeId we can use key.getAttribute(1) as well
                EmployeesVOImpl empVO = getEmployees1();
                EmployeesVORowImpl empRow = (EmployeesVORowImpl)empVO.findByKey(key, 1)[0];
                NameValuePairs nvp = new NameValuePairs();
                nvp.setAttribute("EmpId", empRow.getEmployeeId());

                MyEmployeesVOImpl myempVO = getMyEmployees1();
                MyEmployeesVORowImpl myempRow = (MyEmployeesVORowImpl)myempVO.createAndInitRow(nvp);
                myempVO.insertRow(myempRow);
                
            } catch (Exception e) {
                throw new JboException("Error in addSelectedEmployees "+e.getMessage());
            }
        }
    }

In the client Interface screen of AM, add the method addSelectedEmployees in selected list. We create client interface for our method since we will call it from a ViewController via bindings.






At this point its good to execute the AM. However create new row for MyEmployees will not work since it wont get the EmpId.

3. So Next we turn our attention to ViewController project:

Create a page addEmployees.jspx.
All we will add to the page is a rich table for Myemployees and a popup containing query region for employees.

Add MyEmployees1 from Data Control to the page as read-only table. Enable the 'Row Selection' option






Surround table with a PanelCollection and add 2 buttons 'Add New' and 'Delete' on it.







Next we Add a popup dialog on the page and drop Employees1 as a query region on it.

Change the RowSelection for result table to 'multiple' & Note that the 'SelectedRowKeys' is empty while 'SelectionListener' has value #{bindings.Employees1.collectionModel.makeCurrent}







In order to open the popup, add showPopupListener on 'Add New' button and put popupId using 'Edit' dialog.
In order to delete, Grab Delete operation from MyEmployees1 data control and drop on Delete button.
Also add PartialTriggers of both buttons on the main table.

We can test our page at this point and it should display blank MyEmployees Table. Clicking on the Add New button will display popup and we can search employees. The selected employees however will not be added to MyEmployees. For that we need to add some code in managed bean to get selected employees and pass it to AM method that we created earlier. remember?







Go to page definition of addEmployees page. Add a new methodAction: addSelectedEmployees(Key[]) to bindings.





In the dialog listener property of af:dialog add a method #{EmployeeMgr.handleAddEmployee}. Create the managed bean EmployeeMgr if not present.

Add the following code to handleAddEmployee() method to get all the selected employees from the popup table.

    public void handleAddEmployee(DialogEvent dialogEvent) {
        // get all the selected attributes...
        if(dialogEvent.getOutcome().equals(DialogEvent.Outcome.ok)) {
            //Find the search results table and get all selected values
            RichTable table =  (RichTable)          

            findComponent(dialogEvent.getComponent(), "resId1");
            RowKeySet set = table.getSelectedRowKeys();
            System.out.println("Set of selected  
            "+set.getSize()+"  "+set);
            Iterator it = set.iterator();
            Key[] keyList = new Key[set.getSize()];
            int i = 0;
            //Add all the selected Keys to array
            while(it.hasNext()) {
                Key key = (Key)((List)it.next()).get(0);
                keyList[i++] = key;
            }
            
            //Pass the Keys as parameter to method 
            //addSelectedEmployees
            Map map = new HashMap();
            map.put("selectedEmp", keyList);
            executeMethodWithParams("addSelectedEmployees", map);

            //NOTE: following line refreshes the main page
            AdfFacesContext.getCurrentInstance()
            .addPartialTarget(findComponentInRoot("t1"));
        }
    }


Dont forget to drop the commit and rollback actions from DataControl onto the page to save the changes.

The final page will look like this:






I hope this is useful. I would surely appreciate your comments and issues in the project.

2 comments:

Hi HusainD,

I only used this :
In the MyEmployeesEOImpl add the following code to create() method
protected void create(AttributeList attributeList) {
super.create(attributeList);
SequenceImpl seq = new SequenceImpl("MY_EMPLOYEES_S", getDBTransaction());

setId(seq.getSequenceNumber());
setEmpId((Number)attributeList.getAttribute("EmpId"));
//setEmpId(new Number(1));
}

But that was enough to use the sequence.

Thanks!

Klaas

November 17, 2009 at 6:46:00 AM PST  

Hi Klaas,

Didnt completely follow your question. Did you mean the sequence was not populated properly?

November 17, 2009 at 7:14:00 AM PST  

Newer Post Home