Xpages 如何在部分更新中反转求值顺序?
我遇到过这样的情况:当对设置了部分更新的字段使用onChange事件时,部分更新的执行是在实际事件上的SSJS代码之前执行的 有没有可能扭转这种局面 在我随附的示例中,我有三个字段,一个隐藏输入和一个计算值 用户在这三个字段中输入值,隐藏组件有一个公式来计算上述字段的总和。名义*价格+费用=付款金额。Xpages 如何在部分更新中反转求值顺序?,xpages,lotus,Xpages,Lotus,我遇到过这样的情况:当对设置了部分更新的字段使用onChange事件时,部分更新的执行是在实际事件上的SSJS代码之前执行的 有没有可能扭转这种局面 在我随附的示例中,我有三个字段,一个隐藏输入和一个计算值 用户在这三个字段中输入值,隐藏组件有一个公式来计算上述字段的总和。名义*价格+费用=付款金额。 现在,客户希望有一个预定义的费用值,该值在PaymentAmount之前计算;在我的示例中,我使用0.15%的硬编码值。 然后,公式为PaymentAmount=(名义*价格*feeDef)+(名
现在,客户希望有一个预定义的费用值,该值在PaymentAmount之前计算;在我的示例中,我使用0.15%的硬编码值。
然后,公式为PaymentAmount=(名义*价格*feeDef)+(名义*价格) 我们在一个表中设置了PaymentAmount,并将该行标记为PaymentAmountRow,以便能够更新其中的两个组件。
所有组件过去都有PaymentAmountRow的部分更新,但现在我需要组件价格来更新Fee1。我认为,如果我将部分更新更改为高于一切的组件,在本例中,周围名为dealInfo的面板将正常工作,但令我惊讶的是,部分组件的计算在计算费用的实际代码之前触发 我已经尝试了事件的所有可用参数,但没有一个有效
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
<xp:this.resources>
<xp:script
src="/CommonSSJS.jss"
clientSide="false"
>
</xp:script>
</xp:this.resources>
<xp:panel id="dealInfo">
<xp:this.data>
<xp:dominoDocument
var="document1"
formName="EquityTrade"
>
</xp:dominoDocument>
</xp:this.data>
<xp:label
value="Nominal"
id="label2"
>
</xp:label>
<xp:inputText
id="Nominal"
value="#{document1.Nominal}"
>
<xp:eventHandler
event="onchange"
submit="true"
refreshMode="partial"
refreshId="PaymentAmountRow"
>
<xp:this.action><![CDATA[#{javascript:print("Nominal onChange - partial PaymentAmount");}]]></xp:this.action>
</xp:eventHandler>
<xp:this.converter>
<xp:convertNumber type="number"></xp:convertNumber>
</xp:this.converter>
</xp:inputText>
<xp:br></xp:br>
<xp:label
value="Price"
id="label1"
>
</xp:label>
<xp:inputText
id="Price"
value="#{document1.Price}"
>
<xp:this.converter>
<xp:convertNumber type="number"></xp:convertNumber>
</xp:this.converter>
<xp:eventHandler
event="onchange"
submit="true"
refreshMode="partial"
refreshId="Fee1">
<xp:this.action><![CDATA[#{javascript:print("Price onChange - update")
var Fee1:com.ibm.xsp.component.xp.XspInputText = getComponent("Fee1");
var feeDef = 0.15;
var Nominal:com.ibm.xsp.component.xp.XspInputText = getComponent("Nominal");
var Price:com.ibm.xsp.component.xp.XspInputText = getComponent("Price");
var fee = Nominal.getValue()*Price.getValue()*feeDef
Fee1.setValue(fee);
}]]></xp:this.action>
</xp:eventHandler>
</xp:inputText>
<xp:br></xp:br>
<xp:label
value="Fee 1"
id="label3"
>
</xp:label>
<xp:inputText
id="Fee1"
value="#{document1.Fee1}"
>
<xp:this.converter>
<xp:convertNumber type="number"></xp:convertNumber>
</xp:this.converter>
<xp:this.valueChangeListener><![CDATA[#{javascript:print("Value changed");
}]]></xp:this.valueChangeListener>
<xp:eventHandler
event="onchange"
submit="true"
refreshMode="partial"
refreshId="PaymentAmountRow"
></xp:eventHandler>
</xp:inputText>
<xp:br></xp:br>
<xp:table>
<xp:tr id="PaymentAmountRow">
<xp:td>
<xp:inputHidden
id="PaymentAmount"
value="#{document1.PaymentAmount}"
>
<xp:this.converter>
<xp:customConverter getAsString="#{javascript:return value.toString();}">
<xp:this.getAsObject><![CDATA[#{javascript:try {
print("PaymentAmount calculation");
var Nominal:com.ibm.xsp.component.xp.XspInputText = getComponent("Nominal");
var Price:com.ibm.xsp.component.xp.XspInputText = getComponent("Price");
var Fee1:com.ibm.xsp.component.xp.XspInputText = getComponent("Fee1");
var nominal = Nominal.getValue();
var price = Price.getValue();
var fee1= Fee1.getValue();
var paymentAmount = nominal * price;
paymentAmount+=fee1;
return paymentAmount;
} catch(e){
dBar.info(e);
}}]]></xp:this.getAsObject>
</xp:customConverter>
</xp:this.converter>
</xp:inputHidden>
<xp:text
escape="true"
id="computedField14"
>
<xp:this.value><![CDATA[#{document1.PaymentAmount}]]></xp:this.value>
<xp:this.converter>
<xp:convertNumber type="number"></xp:convertNumber>
</xp:this.converter>
</xp:text>
</xp:td>
</xp:tr></xp:table>
</xp:panel>
</xp:view>
我不能100%确定我是否理解代码或是哪个部分导致了问题,但我认为是转换器的getAsObject()在eventHandler的应用程序逻辑之前运行,没有获得正确的值。下面是: XPages(和JSF)部分刷新生命周期分为六个阶段: 1) 还原视图重建组件树,以便我们可以将发送回的HTML映射回底层Java对象。 2) 应用请求值获取在HTML中输入的字符串值,并将其放入每个相关组件的submittedValue属性中。 3) 过程验证运行所有转换器和验证器,以确保submittedValue属性可以转换为基础数据类型,并通过服务器上定义的任何验证规则。 4) 更新模型值获取这些submittedValue(现在我们知道我们可以将它们应用到数据模型中,而不会把事情搞砸!),将字符串转换为相关的数据类型,将它们放在value属性中,并将submittedValue设置为null。(它可能在流程验证阶段转换了字符串并将其存储在内部变量中,因此在此阶段只需更新value和submittedValue,不确定。) 5) 调用应用程序运行eventHandler逻辑。 6) 呈现响应为浏览器生成更新的HTML 你不能改变顺序。因此,必须在更新模型值之前运行流程验证。否则,更新模型值可能会因为数据类型错误而中断,或者您存储了一个无效值,该值随后将写入基础文档 我认为问题在于您的转换器使用的是getComponent().getValue()。但在流程验证阶段,即转换器的getAsObject()方法正在运行时,不会设置该值 如果是这样,您实际需要的是:
- 要使用getComponent().getSubmittedValue(),请验证转换器中其他组件的值,并相应地抛出错误
- 只需使用一个基本的数字转换器,将设置付款金额的代码移动到eventHandler,与后端数据进行交互,从而获取document1.Price等并设置document1.paymentAmount
如果您使用后者,您应该能够避免使用INPUTHIDEN。Thx,我将尝试一下……我向SSJS资源添加了一个方法,使用该方法计算所有字段并设置PaymentAmount。然后,正如您所说,我在没有验证/转换的情况下将字段更改为“普通”文件。