我的一个聪明的想法看起来不像我想象的那么明亮。
背景 - 我需要在其中一列中使用DBLookups对视图执行经典的重复控制解决方案。我需要有列的总数,所以我决定使用viewScope变量来保存小计,并在重复控件的行中计算它们时添加值。
理论上听起来不错,但出于某种原因,如果我在重复控件中使用Computed Field,则计算值(并附加到小计)两次。我已经使用以下代码中的代码建立了这个,使用计算字段和编辑框,在重复内部使用相同的代码:
<xp:text escape="true" id="computedField9">
<xp:this.value><![CDATA[#{javascript:
//some calculations, nothing to see here*
var subTotal = viewScope.get("valueColumnTotal");
viewScope.put("valueColumnTotal", subTotal + sumVals);
sessionScope.put("Testing", sessionScope.get("Testing") + "~" + sumVals);
return sumVals;
}]]></xp:this.value>
//converters and stuff, nothing to see here
</xp:text>
<xp:inputText id="inputText1">
<xp:this.value><![CDATA[#{javascript:
//Same as the computed field above
</xp:this.value>
</xp:inputText>
对于1,2和3的值,我的sessionScope变量显示0~1~1~1~2~2~2~3~3~3,小计结果为18 如果我删除文本框,我得到0~1~1~2~2~3~3,小计为12
换句话说,我得到计算字段的双精度值和编辑框的单个值。我也在那里得到零,我无法解释,但我认为这只是一个初始值而不用担心。
我认为这可能是一个重复被某种东西刷新的情况,但是我希望1~2~3~1~2~3。
我猜我只是不明白计算计算字段的基本原理,但我很难过。我想我可以切换到编辑框,但我认为计算字段在这里更合适。
有人可以对这一点有所了解吗?
答案 0 :(得分:1)
JSF Lifecycle揭示了你所面临的挑战。您使用的公式按Per指出的多个阶段执行。确保只计算一次它们的最简单方法是使用以下代码:
if (view.isRenderingPhase() {
var subTotal = viewScope.get("valueColumnTotal");
viewScope.put("valueColumnTotal", subTotal + sumVals);
sessionScope.put("Testing", sessionScope.get("Testing") + "~" + sumVals);
return sumVals;
}
您只需确保在适当的时间重置该值(例如beforeRenderResponse
)
独立于循环的另一个选项(即使你不渲染页面,你可能想要计算一个值)是使用一个小的Java类:
public class SumItUp {
private HashMap<String, Integer> totals = new HashMap<String,Integer>();
public void add(String key, int value) {
Integer i = new Integer(value);
this.totals.put(key,i);
}
public int getTotal() {
int result = 0;
for (Map.Entry<String, Integer> me : this.totals.entrySet()) {
result += me.getValue().toInt(); // <-- check that one - off my memory
}
}
将其用作数据上下文或在SSJS中初始化它。无论调用计算的频率如何。当您提交给Hashmap时,不会有重复的值。使用clientid(不是id,对于重复中的所有控件都是相同的)或文档的UNID作为键 - 它们是唯一的
答案 1 :(得分:0)
如果我正确阅读了要求,则要求显示列的总计。 如果视图已对列进行了分类,则此处是我使用的解决方案,基于Notes In 9 – 019 – Xpages: Getting Column Totals From a View
datacontext用于从视图中提取列总数: {**这行代码 if(entry == null){return false} else {return entry} 如果没有键值类别,则返回零}
用于在重复控件中使用行显示值的表中总计的显示是使用xp:facet完成的,下面的代码为总行:
整个方面看起来像: {**第4列,第5列结束,在视图中显示类别总计}
切割N-Paste以下{**仅供专业Cut-n-Paste'ers使用}
<xp:dataContext var="contractCategory">
<xp:this.value>
<![CDATA[#{javascript:
try{
var nav:NotesViewNavigator = contractView.createViewNav();
var query = new java.util.Vector();
query.addElement(sGrantId);
var entry:NotesViewEntry = contractView.getEntryByKey(query);
var entry = nav.getPrev(entry);
if (entry==null) {return false}else{return entry}
}catch(e){
return false;
}
}]]>
</xp:this.value>
</xp:dataContext>
<xp:this.facets>
<xp:panel xp:key="footer" id="TotalDisplayArea">
<xp:tr style="background-color:#c9c9c9">
<xp:this.rendered>
<![CDATA[#{javascript:getComponent("repeat1").getRowCount();}]]>
</xp:this.rendered>
<xp:td colspan="2" styleClass="budget_grid_body lotusBold" style="text-align:left">
Totals:</xp:td>
<xp:td styleClass="budget_grid_body" style="text-align:right"> </xp:td>
<xp:td styleClass="budget_grid_body" style="text-align:center;">
<xp:div style="text-align:left;float:left;padding-left:20px;">
<xp:span>$</xp:span>
</xp:div>
<xp:div style="float:right;padding-right:5px;">
<xp:text escape="true" id="totalCostDisp">
<xp:this.converter>
<xp:convertNumber pattern="#,##0.00"></xp:convertNumber>
</xp:this.converter>
<xp:this.value>
<![CDATA[#{javascript:
(operatingCategory)?
operatingCategory.getColumnValues()[4]:
"CodeError:4:2"}]]>
</xp:this.value>
</xp:text>
</xp:div>
</xp:td>
<xp:td style="background-color:#ffffff"></xp:td>
</xp:tr>
</xp:panel>
</xp:this.facets>