Sunday, December 13, 2009

Use Checkbox For Selecting Multiple Rows From af:table

One of the feature which existed in JDeveloper 10g but not found in JDeveloper 11g is using checkbox for selecting multiple rows from af:table.
This is my workaround for achieving this feature in JDeveloper 11g. Follow this steps:

1- Make a new ADF fusion web Application.
2- choose your database connection. (assume we are using HR Schema)
3- Make one viewObject based on entity (assume Employees viewObject based on Employees Entity)
4- Open your Employees ViewObject and make a new transient attribute with type boolean and make it always updatable (assume the transient Attribute name is 'TransientAttr').


5- Make a new page and drag your employee view as a table and don't check on Row Selection checkbox.
6- In your Structure Palette goto your inputText Transient attribute and right click and choose Convert to.






7- From opening dialog choose Select Boolean Checkbox ---> Ok ----> Ok.

8- Make the selectBooleanCheckbox component AutoSubmit with true and put its Id in the table partialTrigger and clear its lable and text.
9-
Select all columns and goto Style Property and inlineStyle write
this #{(row.TransientAttr)?"background-color: #ffaaaa":""};
where #ffaaaaa is the color of the selected row (you can change this color as you want).
10-Now any row has its transient Attribute with true value, this row will be selected row.

25 comments:

  1. Hello Sameh,
    Great post and very nice simple idea

    regards
    Karim

    ReplyDelete
  2. Good idea, but how do you identify which row has been selected in code?

    ReplyDelete
  3. Hi Samson,

    as I said in point 10 "any row has its transient Attribute with true value, this row will be selected row", so you can loop in the iterator and check the value of the transient attribute:
    BindingContainer bindings = getBindings();
    DCIteratorBinding dciter =(DCIteratorBinding) bindings.get("YourView1Iterator");
    for (int i=0 ;i<dciter.getViewObject().getEstimatedRowCount ;i++ ) {
    Row r=dciter.getRowAtRangeIndex(i);
    r.getAttribute("TransientAttr");// if it is true then this is a selected row
    }

    ReplyDelete
  4. Hi, Sameh please provide your email... thanks
    masood_pk_lhr@yahoo.com

    ReplyDelete
  5. Hi,Sameh Thank you very much for sharing real world experience.very useful for me.

    Regards
    KT

    ReplyDelete
  6. Hi Sameh,
    Thank you for this post.
    Please take into consideration to improve this solution by preventing the transaction state to be set to modified status.
    This happens even when the user doesn't make any selection, f.e. when the user navigates to another page (see oracle.adf.model.binding.DCDataControl.setTransactionModified()).

    Regards,
    Virgil

    ReplyDelete
    Replies
    1. Thanks Virgil
      but,
      There is no modification here I just read the selected rows I don't modify anything. It is just transient attribute.

      Delete
    2. Hi Sameh,

      From the DB transaction point of view you're right. Please enable uncommitted data warning on the page containing the af:table with multiple selection (by setting uncommittedDataWarning="on" on af:document).
      Then try to go to another page and you'll see a warning popup. Set a breakpoint in method DCDataControl.setTransactionModified() on line containing mTxnModified = true; and the execution will stop there when you want to navigate to another page.

      Regards,
      Virgil

      Delete
    3. Hi Virgil,
      Thanks again. You are right because uncommittedDataWarning will fire if any change happen in the page even if changes happen in transient attribute or changes in non-database viewobject.

      Regards,

      Delete
  7. Hi sameh,

    Instead of explicitly iterating the the table binding and then updating the selected/checked rows in db;any other way to do it with execute method of the datacontrol ?

    ReplyDelete
    Replies
    1. Hi vijayalakshmi,

      The checked rows not affect in database because the check box attribute is a Transient attribute not a database attribute.

      Delete
  8. Hi sameh,

    How can I add to the first header column a checkbox that will automaticaly check/uncheck all the table records field?

    Thanks

    ReplyDelete
    Replies
    1. Hello,

      Inside af:column add a header facet and inside header facet you can add af:selectBooleanCheckBox and from selectBooleanCheckBox valueChangeListener you can check/uncheck all the table records field.

      Delete
  9. Hi Sameesh,

    In the bean class to find out the rows selected, one has to iterate entire VO and find, which is taking too much time to complete
    BindingContainer bindings = getBindings();
    DCIteratorBinding dciter =(DCIteratorBinding) bindings.get("YourView1Iterator");
    for (int i=0 ;i<dciter.getViewObject().getEstimatedRowCount ;i++ ) {
    Row r=dciter.getRowAtRangeIndex(i);
    r.getAttribute("TransientAttr");// if it is true then this is a selected row
    }

    Is actually slow if the number of records are very high in number say 5 thousand rows.

    Whereas, the standard built-in approach (CTROL+CLICK) and table.getSelectedKeyRows is very fast.
    Any performance improvement can be made in this work-around approach? thanks

    ReplyDelete
    Replies
    1. Hi Antony,
      1- Some customer not prefer to use Ctrl + Click to select multiple rows.

      2-If the table has very high numbers say 5 thousand rows as you said this mean that it will be difficult to select multiple records at all. The customer need this feature if he has a table hold not large number of the records.

      Regards,

      Delete
    2. Hi Samesh,
      While it is preferred to use CTRL+CLICK in many scenarios, the check-box is the only way for the following scenario

      In our case, user has to select a value from the drop-down from the table rows, and he will do that for many such rows before click on submit.

      In this case, it is not possible to do CTRL+CLICK and edit the rows. Just think about this how difficult it would be pressing CTRL+CLICK and change the value of drop-down for multiple rows.. simply impossible.

      Regards,
      Antony.

      Delete
  10. Hi Sameh,

    Thank you for great post I followed all the step as you mentioned but when I run the JSF page I got _ char nested of checkbook and I can't select more than row, so could you have any solving for this problem?

    Regards,

    ReplyDelete
    Replies
    1. Be sure that the transient attribute is always updatable and the table editingMode="editAll". If it is still not work try to change the transient attribute type from boolean to String and test again

      Delete
    2. Thank you Sameh for the fast valuable response!

      The problem has been solved :)
      Best Regards,

      Yazan Mohammad

      Delete
  11. Hi Sameh, I have a select Boolean checkbox prsent in the facet of column through which I can select the checkboxes of all rows in the table. But when I do that only the rows which are visible those are only getting selected. But the moment I scroll down the table then the subsequent row checkboxes are not selected. can u help me out on this?

    ReplyDelete
    Replies
    1. From pageDef. Try to set iterator RangeSize="-1" and see

      Delete
    2. Thanks Sameh that's a very small change and it worked. But one more problem here is that when I select the selectAll checkbox for the 1st time it didn't select all the rows. But the moment I deselect it and select the selectAll checkbox then it did work. So, in short it's not happening for the 1st time. What could be the reason?

      Delete