ADF UncommittedDataWarning工作原理及autoSubmit元素的解决办法

ADF的UncommittedDataWarning机能使用两个标志来决定当前页面是否是编辑过的(即为脏的):

_hasLocalUncommitted用来标示客户端是否为脏状态,

_dataDirty是用来标示服务端是否为脏的状态。

 

1. 当用户在页面上编辑一个非autoSubmit的控件时,ADF框架会将_hasLocalUncommitted设置为true,因此当用户离开离开页面时,就会弹出下面的提示窗口

ADF UncommittedDataWarning工作原理及autoSubmit元素的解决办法

当用户试图关闭页面时,就会弹出下面的提示窗口。

ADF UncommittedDataWarning工作原理及autoSubmit元素的解决办法

 

2. 当用户在页面上编辑一个autoSubmit的控件时,ADF会提交一个PPR请求,请求的Response会包含下面的内容:

<script>AdfPage.PAGE.setDataDirty(false);</script>
<script>AdfPage.PAGE.setProcessedRoots("d2");</script>

其中的第一个javascript脚本会将_dataDirty设置为false,表明服务端不是脏的状态;第二个javascript脚本会将_hasLocalUncommitted设置为false,表明客户端不是脏的状态(前提是页面上无验证错误,当页面上有验证错误时,此处的脚本不会重置客户端的状态,因此客户端仍然为脏的状态)。所以当用户试图离开或者关闭页面时,就不会提示上面的提示窗口。

 

3. 当服务端的状态为脏时(当应用程序在请求页面时,修改了页面上绑定的数据源的值的时候,比如页面AB使用了同样的VO作为Model层绑定到了Page Definition文件中,当从页面A跳转到页面B的时候,在页面A的按的ActionListener当中修改了VO的行记录),那么在请求的页面的Response中会包含下面的内容:

<script type="text/javascript">
AdfBootstrap._extendedScripts=[function({AdfPage.PAGE.setDataDirty(true);}];
</script>

上面的javascript脚本会设置_dataDirty设置为true,表明服务端是脏的状态,因此当用户试图离开或者关闭页面时,就是提示上面的提示消息。

 

4. 当页面上有验证错误时,若用户操作了非autoSubmit的控件,那么客户端仍然保持脏的状态,若用户操了autoSubmit的控件,但是因为页面有验证错误,客户端的状态不会被重置,所以仍然为脏。因此当用户试图离开或者关闭页面时,就是提示上面的提示消息。

 

 

实际情况是,当用户在页面上进行了编辑操作后,无论他操作的是否为autoSubmit的控件,当他试图离开或者关闭页面时,都应该提示消息给用户。但是ADF提供的功能在用户操作autoSubmit的控件时,不起作用。那么该如何实现上述需求呢?

思路1

1.1. 添加一个dirty filed在页面上;

1.2. 给页面上的所有autoSubmit控件添加一个valueChange listener用来标示dirty filed

1.3. 给页面的definition文件文件设置一个状态监听器(controllerClass=PPRHookListener),当PPR请求完毕后,添加一段javascript脚本,用来检查dirty field。当dirty field不为空时,调用AdfPage.PAGE.setDataDirty方法,将当前页面设置为脏状态。

 

1.3步的java代码如下:

public class PPRHookListener implements PhaseListener {
	public void afterPhase(PagePhaseEvent pagePhaseEvent) {
	    FacesPageLifecycleContext ctx = 
		    (FacesPageLifecycleContext)pagePhaseEvent.getLifecycleContext();
	    if (pagePhaseEvent.getPhaseId() != Lifecycle.PREPARE_RENDER_ID) {
		    return;
		}
		
		if(AdfFacesContext.getCurrentInstance().isPostback() )
            FacesContext context = FacesContext.getCurrentInstance();
            ExtendedRenderKitService service = 
			    (ExtendedRenderKitService)Service.getRenderKitService
				(context, ExtendedRenderKitService.class);
			service.addScript(context, " markDirtyIfNeeded('dirtyFiledId');");
		}
	}
}

但是因为ADF框架会在上面添加的javascript之后,添加下面的重置状态的javascript脚本,导致上面添加的javascript又被覆盖了,因此此思路行不通。

<script>markDirtyIfNeeded('dirtyFiledId');</script>
<script>AdfPage.PAGE.setDataDirty(false);</script>
<script>AdfPage.PAGE.setProcessedRoots("d2");</script>

 

思路2

1.1. 添加一个dirty filed在页面上;

1.2. 给页面上的所有autoSubmit控件添加一个valueChange listener用来标示dirty filed

1.3. 重写当前页面的setDataDirty方法,检查dirty filed是否为空,当不为空时,则将当前页面设置为脏状态。

 

涉及到的代码如下:

// Use this method as page's load listener.
function overrideSetDataDirtyForPage(dirtyFieldId) {
    AdfPage.PAGE.setDataDirty = function(value) {
        AdfDhtmlPage.prototype.setDataDirty(value);
        
        var txtDirty = AdfPage.PAGE.findComponentByAbsoluteId(dirtyFieldId);
        if (txtDirty == null) {
            return;
        }
        
        var dirtyFlag = txtDirty.getValue();
        if (dirtyFlag == null || dirtyFlag == '') {
            return;
        }
        
        AdfDhtmlPage.prototype.setDataDirty(true);
    }
}

//Use this method as control's value change listener
function markDirty(dirtyFieldId) {  
    return function(evt) {  
        var txtDirty = AdfPage.PAGE.findComponentByAbsoluteId(dirtyFieldId);  
        if (txtDirty != null) {  
                txtDirty.setValue("dirty");  
        }  
    }  
}  

 

页面使用的代码如下:

<!-- Register load listener for the page -->
<af:clientListener method= overrideSetDataDirtyForPage('txtLocalDirtyFlg')" type="load"/>

<!-- Register value change listener for the autoSubmittted control-->
<af:selectOneChoice label="List"
    id="soc1"
    autoSubmit="true" 
    ....>
     <f:selectItems value="#{pageFlowScope.list}" id="si3"/>
     <af:clientListener type="valueChange" method="markDirty('txtLocalDirtyFlg')"/>
</af:selectOneChoice>

 此思路有效的避免了ADF框架的默认行为,可以解决上述问题。

 

 

 

 

你可能感兴趣的:(submit)