运行环境:JDeveloper 11.1.2.1.0 + Oracle Database 10g Express Edition 10.2.0.1。
实验介绍:用户使用CheckBox选择要删除的行,点击按钮一次删除多行。
(1)主页面
(2)点击全选CheckBox
(3)删除选中的行
(4)如果没有选中行,会提示请选择
重点步骤说明:
1. 为View Object添加一个Transient字段: IsChecked,用于保存每行的选择状态
2. 修改页面中的IsChecked列:添加“全选/全不选”列头,转换OutputText为selectBooleanCheckbox。
(1)修改后的IsChecked列内容如下:
<af:column sortProperty="#{bindings.JobsView1.hints.IsChecked.name}" filterable="false"
sortable="false" headerText="#{bindings.JobsView1.hints.IsChecked.label}" id="c1"
width="30" minimumWidth="30" align="center">
<af:selectBooleanCheckbox value="#{row.IsChecked}" id="sbc1"
label="#{row.bindings.IsChecked.label}"/>
<f:facet name="header">
<af:selectBooleanCheckbox id="selectAllCheckBox">
<af:clientListener method="clickOnSelectAllCheckBox" type="valueChange"/>
<af:serverListener type="SelectAllCheckBoxClickEvent"
method="#{backingBeanScope.myBackingBean.handleSelectAllCheckboxClick}"/>
</af:selectBooleanCheckbox>
</f:facet>
</af:column>
(2)clientListener调用的javascript函数
<af:resource type="javascript" source="js/table_function.js"/>
其中包含clickOnSelectAllCheckBox函数:
function clickOnSelectAllCheckBox(evt) {
var selectAllCheckBox = evt.getSource();
var isChecked = selectAllCheckBox.getValue();
AdfCustomEvent.queue(selectAllCheckBox, "SelectAllCheckBoxClickEvent", {params : isChecked},false);
}
(3)把Table绑定到Managed Bean中的一个属性
binding="#{backingBeanScope.myBackingBean.jobsTable}"
(1)(2)(3)组合在一起,实现了“全选/全不选”功能。原理如下:
当“全选/全不选”CheckBox上发生valueChange事件发生时,监听该事件的clientListener触发了javascript方法:clickOnSelectAllCheckBox,该方法向事件队列中同步地(true参数表示异步,false表示同步)压入一个事件:SelectAllCheckBoxClickEvent,监听该事件的serverListener触发了Managed Bean中的方法handleSelectAllCheckboxClick。
3. 为Table增加行号
在第一列之前,增加一列,作为行号。
<af:column id="c6" headerText="No." width="30" minimumWidth="30" align="center">
<af:outputText value="#{vs.index+1}" id="ot1"/>
</af:column>
4. Managed Bean完整代码
package view;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import oracle.adf.model.BindingContext;
import oracle.adf.model.binding.DCBindingContainer;
import oracle.adf.model.binding.DCIteratorBinding;
import oracle.adf.view.rich.component.rich.data.RichTable;
import oracle.adf.view.rich.event.DialogEvent;
import oracle.adf.view.rich.render.ClientEvent;
import oracle.binding.BindingContainer;
import oracle.binding.OperationBinding;
import oracle.jbo.Row;
import oracle.jbo.RowSetIterator;
import oracle.jbo.ViewObject;
import oracle.jbo.uicli.binding.JUCtrlHierNodeBinding;
import org.apache.myfaces.trinidad.render.ExtendedRenderKitService;
import org.apache.myfaces.trinidad.util.Service;
import view.util.ADFUtils;
public class MyBackingBean {
public MyBackingBean() {
super();
}
private RichTable jobsTable;
public void handleSelectAllCheckboxClick(ClientEvent clientEvent) {
boolean isSelectAllChecked = (Boolean)clientEvent.getParameters().get("params");
RichTable rt = this.getJobsTable();
for (int i = 0; i < rt.getRowCount(); i++) {
JUCtrlHierNodeBinding rowData = (JUCtrlHierNodeBinding)rt.getRowData(i);
Row row = rowData.getRow();
row.setAttribute("IsChecked", isSelectAllChecked);
}
}
public void deleteButton_actionListener(ActionEvent actionEvent) {
if (isMoreThanOneRowSelected()) {
FacesContext facesContext = FacesContext.getCurrentInstance();
ExtendedRenderKitService service =
Service.getRenderKitService(facesContext, ExtendedRenderKitService.class);
service.addScript(facesContext, "AdfPage.PAGE.findComponent('popupDelete').show();");
} else {
FacesContext facesContext = FacesContext.getCurrentInstance();
ExtendedRenderKitService service =
Service.getRenderKitService(facesContext, ExtendedRenderKitService.class);
service.addScript(facesContext, "AdfPage.PAGE.findComponent('popupNoRowSelected').show();");
}
}
public boolean isMoreThanOneRowSelected() {
boolean isMoreThanOne = false;
DCIteratorBinding dcIterator = ADFUtils.findIterator("JobsView1Iterator");
ViewObject vo = dcIterator.getViewObject();
for (int i = 0; i < vo.getEstimatedRowCount(); i++) {
Row row = dcIterator.getRowAtRangeIndex(i);
String isSelected = row.getAttribute("IsChecked").toString();
if ((isSelected != null) && Boolean.parseBoolean(isSelected)) {
isMoreThanOne = true;
break;
}
}
return isMoreThanOne;
}
public void deleteDialogListener(DialogEvent dialogEvent) {
if (dialogEvent.getOutcome().equals(DialogEvent.Outcome.ok)) {
doDelete();
}
}
private void doDelete() {
DCIteratorBinding dcIterator = ADFUtils.findIterator("JobsView1Iterator");
RowSetIterator rsi = dcIterator.getRowSetIterator().getRowSet().createRowSetIterator("deleteRowsRSI");
rsi.reset();
while (rsi.hasNext()) {
Row row = rsi.next();
String isSelected = row.getAttribute("IsChecked").toString();
if ((isSelected != null) && Boolean.parseBoolean(isSelected)) {
row.remove();
}
}
rsi.closeRowSetIterator();
OperationBinding operb = ADFUtils.findOperation("Commit");
operb.execute();
}
public void setJobsTable(RichTable jobsTable) {
this.jobsTable = jobsTable;
}
public RichTable getJobsTable() {
return jobsTable;
}
}
5. popupDelete和popupNoRowSelected是由程序控制弹出的
重要的属性说明如下:
contentDelivery="lazy",因为每次弹出的内容都相同,因此使用延迟装载,且使用Cache。
<af:popup id="popupDelete" autoCancel="disabled" childCreation="deferred" contentDelivery="lazy">
<af:dialog id="dialogDelete" title="Delete Confirm"
dialogListener="#{backingBeanScope.myBackingBean.deleteDialogListener}">
<af:outputText value="The record will be delete,are you sure ?" id="ot6"/>
</af:dialog>
</af:popup>
<af:popup id="popupNoRowSelected" autoCancel="disabled" childCreation="deferred" contentDelivery="lazy">
<af:dialog id="dialogNoRowSelected" type="ok" title="No Row Selected">
<af:outputText value="Please Select At Least One Row To Be Deleted." id="ot7"/>
</af:dialog>
</af:popup>