【问题标题】:Computed field inside repeat control - computing twice (and ruining sub-total!)重复控制内的计算字段 - 计算两次(并破坏小计!)
【发布时间】:2013-07-17 01:51:24
【问题描述】:

我的一个好主意看起来没有我最初想象的那么聪明。

背景 - 我需要在其中一列中使用 DBLookups 对视图执行经典的重复控制解决方案。我需要对列进行总计,因此我决定使用 viewScope 变量来保存小计,并在计算重复控件的行时添加这些值。

理论上听起来不错,但由于某种原因,如果我在重复控件内使用计算字段,则该值将被计算(并附加到小计)两次。我已经使用以下代码建立了这一点,在重复中使用了计算字段和编辑框,其中包含相同的代码:

<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。

我猜我只是不了解何时计算计算字段的基本知识,但我很难过。我想我可以切换到编辑框,但我认为计算字段在这里更合适。

有人能解释一下吗?

标签: xpages


【解决方案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 作为键 - 它们是唯一的

【讨论】:

  • 谢谢斯蒂芬,但这对我不起作用。我仍然从 Computed Field 和 Edit Box 获得两次迭代。我(诚然有限)对 JSF 生命周期的理解是,所有控件都将在每个步骤中计算,我假设这意味着行将在第一步中按顺序完成,然后在第二步中再次按顺序完成计算它们的步骤。但是,我的 sessionScope 检查值显示为 1~1~2~2~3~3,这告诉我在重复的下一行完成之前,各个计算框正在计算两次。
  • HashMaps 完成了这项工作,谢谢!我尝试了很多方法来尝试找出计算域被计算两次的原因,但最终最好使用一个优雅的解决方案,该解决方案可以工作并接受 XPages 中有时会在幕后发生的事情。
【解决方案2】:

如果我正确阅读了要求,则要求是显示列的总计。 如果视图有分类列,这是我使用的解决方案,基于Notes In 9 – 019 – Xpages: Getting Column Totals From a View

datacontext 用于从视图中提取列总计: {** 这行代码 if (entry==null) {return false}else{return entry} 如果键值没有类别,则返回零}

用于在重复控件中使用一行显示值的表格中的总计显示是使用 xp:facet 完成的,下面的代码作为总计行:

整个方面看起来像: {** 第 4 列,第 5 列结束,在视图中是显示类别总数的列}

Cut-N-Paste below {**仅供专业的 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">&#160;</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>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-10-11
    • 1970-01-01
    • 2022-08-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多