运行环境:JDeveloper 11.1.2.1.0 + Oracle Database 10g Express Edition 10.2.0.1。
1. 采用弹出窗口的方式来实现增加和修改功能
个人比较喜欢这种方式,感觉比较自然。
(1)页面效果
(2)增加功能
在当前行的上一行增加一条记录。
(3)修改功能
修改当前行记录。
(4)删除功能
删除当前行,删除前有提示。
2. 增加和修改功能实现说明
(1)点击增加或修改按钮都是弹出一个窗口,即popup组件
<af:commandButton text="CreateInsert" id="cbInsert">
<af:showPopupBehavior popupId="::popupEditOrInsert" triggerType="action" align="endAfter"/>
</af:commandButton>
<af:commandButton text="Edit" id="cbEdit">
<af:showPopupBehavior popupId="::popupEditOrInsert" triggerType="action" align="endAfter"/>
</af:commandButton>
说明:在按钮上添加了showPopupBehavior操作后,将屏蔽按钮上的action或actionListener事件,也就是说不会再触发action或actionListener事件。
如果想要触发并执行完按钮上的action或actionListener方法,然后再弹出popup窗口,只能在action或actionListener方法中用代码弹出popup窗口。比如:
FacesContext facesContext = FacesContext.getCurrentInstance();
ExtendedRenderKitService service =
Service.getRenderKitService(facesContext, ExtendedRenderKitService.class);
service.addScript(facesContext, "AdfPage.PAGE.findComponent('popupDelete').show();");
(2)popup组件的代码
重要的属性说明如下:
contentDelivery="lazyUncached",因为每次弹出的内容都不同,因此不要Cache。
popupFetchListener,是popup组件窗口弹出时调用的方法。
popupCanceledListener,是关闭popup组件窗口时调用的方法,比如点击右上角的X关闭窗口。
dialogListener,负责监听用户点击了OK/Cancel按钮。
Form中绑定的Data Control和Table中绑定的Data Control一样。
<af:popup id="popupEditOrInsert" contentDelivery="lazyUncached" childCreation="deferred"
autoCancel="disabled"
popupFetchListener="#{backingBeanScope.myBackingBean.editOrInsertPopupFetchListener}"
popupCanceledListener="#{backingBeanScope.myBackingBean.editOrInsertPopupCancelListener}">
<af:dialog id="dialogEditOrInsert" title="Edit or Insert" type="okCancel"
dialogListener="#{backingBeanScope.myBackingBean.editOrInsertDialogListener}">
<f:facet name="buttonBar"/>
<af:panelFormLayout id="pfl1">
<af:inputText value="#{bindings.JobId.inputValue}" label="#{bindings.JobId.hints.label}"
required="#{bindings.JobId.hints.mandatory}"
columns="#{bindings.JobId.hints.displayWidth}"
maximumLength="#{bindings.JobId.hints.precision}"
shortDesc="#{bindings.JobId.hints.tooltip}" id="it1">
<f:validator binding="#{bindings.JobId.validator}"/>
</af:inputText>
......
</af:panelFormLayout>
</af:dialog>
</af:popup>
(3)还有很重要的一点是,为panelCollection设置partialTriggers,指向popup组件id和dialog组件id。
这样无论是确定还是取消操作,都会局部刷新panelCollection,进而刷新Table。
<af:panelCollection id="pc1" partialTriggers="::popupEditOrInsert ::dialogEditOrInsert">
3. 双击某行,弹出修改窗口
双击弹出修改窗口,是一个比较常见的功能,在这里我使用af:clientListener + af:serverListener 方式实现。
(1)clientListener
<af:clientListener method="doubleClickOnTable" type="dblClick"/>
(2)serverListener
<af:serverListener type="TableDoubleClickEvent"
method="#{backingBeanScope.myBackingBean.handleTableDoubleClick}"/>
(3)clientListener调用的javascript函数
<af:resource type="javascript" source="js/table_function.js"/>
其中包含doubleClickOnTable函数:
function doubleClickOnTable(evt) {
var table = evt.getSource();
AdfCustomEvent.queue(table, "TableDoubleClickEvent", {},true);
evt.cancel();
}
(1)(2)(3)组合在一起,实现了双击弹出修改窗口功能,原理如下:
当双击事件(dblClick)发生时,监听该事件的clientListener触发了javascript方法:doubleClickOnTable,该方法向事件队列中异步地(true参数表示异步,false表示同步)压入一个事件:TableDoubleClickEvent,监听该事件的serverListener触发了Managed Bean中的方法handleTableDoubleClick。
4. 删除功能实现说明
详细说明请参考《 使用ADF实现基于Form的CRUD (2)
》。
<af:commandButton text="Delete" disabled="#{!bindings.Delete.enabled}" id="cbDelete">
<af:showPopupBehavior popupId="popupDelete" triggerType="action" align="endAfter"/>
</af:commandButton>
<af:popup childCreation="deferred" autoCancel="disabled" id="popupDelete">
<af:dialog id="dialogDelete" title="Confirm Delete"
dialogListener="#{backingBeanScope.myBackingBean.deleteDialogListener}">
<f:facet name="buttonBar"/>
<af:outputText value="The record will be deleted, are you sure?" id="ot5"/>
</af:dialog>
</af:popup>
5. Managed Bean完整代码
package view;
import javax.faces.context.FacesContext;
import oracle.adf.model.BindingContext;
import oracle.adf.view.rich.event.DialogEvent;
import oracle.adf.view.rich.event.PopupCanceledEvent;
import oracle.adf.view.rich.event.PopupFetchEvent;
import oracle.adf.view.rich.render.ClientEvent;
import oracle.binding.BindingContainer;
import oracle.binding.OperationBinding;
import org.apache.myfaces.trinidad.render.ExtendedRenderKitService;
import org.apache.myfaces.trinidad.util.Service;
import view.util.ADFUtils;
public class MyBackingBean {
public MyBackingBean() {
super();
}
public void editOrInsertDialogListener(DialogEvent dialogEvent) {
if (dialogEvent.getOutcome().equals(DialogEvent.Outcome.ok)) {
OperationBinding operb = ADFUtils.findOperation("Commit");
operb.execute();
} else {
OperationBinding operb = ADFUtils.findOperation("Rollback");
operb.execute();
}
}
public void editOrInsertPopupFetchListener(PopupFetchEvent popupFetchEvent) {
if (popupFetchEvent.getLaunchSourceClientId() != null) {
if (popupFetchEvent.getLaunchSourceClientId().contains("cbInsert")) {
OperationBinding operb = ADFUtils.findOperation("CreateInsert");
operb.execute();
}
}
}
public void editOrInsertPopupCancelListener(PopupCanceledEvent popupCanceledEvent) {
OperationBinding operb = ADFUtils.findOperation("Rollback");
operb.execute();
}
public void deleteDialogListener(DialogEvent dialogEvent) {
if (dialogEvent.getOutcome().equals(DialogEvent.Outcome.ok)) {
doDelete();
}
}
private void doDelete() {
OperationBinding operb = ADFUtils.findOperation("Delete");
Object result = operb.execute();
if (operb.getErrors().isEmpty()) {
operb = ADFUtils.findOperation("Commit");
operb.execute();
}
}
public void handleTableDoubleClick(ClientEvent clientEvent) {
FacesContext facesContext = FacesContext.getCurrentInstance();
ExtendedRenderKitService service = Service.getRenderKitService(facesContext, ExtendedRenderKitService.class);
service.addScript(facesContext, "AdfPage.PAGE.findComponent('popupEditOrInsert').show();");
}
}