在页面级别计算和存储数据以用于自定义控件

时间:2014-04-08 13:11:51

标签: xpages

我必须做一些我需要控制的计算,我只想在每次请求时执行一次并存储它。 (例如beforeRenderResponse)

我无法找到一种在自定义控件中实现这一目标的简洁方法。

我不想使用dataContext,因为我读了一些关于它的性能的令人毛骨悚然的文章(在单个JSF循环上进行多次计算)。
请参阅:http://hasselba.ch/blog/?p=1112

所以我去了objectData,只是为了弄清楚,它与compositeData有同样的问题 - 它在任何自定义控件事件中都不可用,但在beforePageLoad和afterPageLoad之前。
请参阅:http://hasselba.ch/blog/?p=1099

当前解决方案

我遇到了两个(不满意的)解决方案。

我用<! - Solutions - >标记了解决方案。在下面的标记中。

解决方案#1:  滥用财产"价值"一个xp:text来更新objectData。

解决方案#2:  需要手动调用update()方法。

试验设置

的XPage

<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core" xmlns:xc="http://www.ibm.com/xsp/custom">
    <xc:dataControl />
</xp:view>

Custom-Control(dataControl)

<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core" xmlns:xe="http://www.ibm.com/xsp/coreex" xmlns:xc="http://www.ibm.com/xsp/custom"
    beforePageLoad="#{javascript:object1.sayHello('beforePageLoad')}" 
    afterPageLoad="#{javascript:object1.sayHello('afterPageLoad')}"
    afterRestoreView="#{javascript:object1.sayHello('afterRestoreView')}" 
    beforeRenderResponse="#{javascript:object1.sayHello('beforeRenderResponse')}"
    afterRenderResponse="#{javascript:object1.sayHello('afterRenderResponse')}">
    <xp:this.data>
        <xe:objectData var="object1">
            <xe:this.createObject><![CDATA[#{javascript://
                print("object1 is created");
                return new ds.DataTest();   }]]>
            </xe:this.createObject>
        </xe:objectData>
    </xp:this.data>

    <!-- Solutions -->

    <!-- Solution #1 -->    
    <xp:text id="computedField1" value="#{javascript: object1.update(); return ''; }" />

    <!-- Solution #2  -->
    <xp:button value="dataObject update" id="updateButton">
        <xp:eventHandler event="onclick" submit="true" refreshMode="complete">
            <xp:this.action><![CDATA[#{javascript:object1.update()}]]></xp:this.action>
        </xp:eventHandler>
    </xp:button>

    <!-- /Solutions -->

    <div>
        Object1 current value:
        <xp:text escape="true" id="output" value="#{object1.value}" />
    </div>

    <xp:button value="Update" id="updateButton2">
        <xp:eventHandler event="onclick" submit="true" refreshMode="complete" />
    </xp:button>
</xp:view>

Java-class(ds.DataTest)

package ds;

import java.io.Serializable;

public class DataTest implements Serializable {
    private static final long serialVersionUID = 1L;
    private String value = "";

    public DataTest() { /* Constructor */ }

    public void sayHello(String text){
        System.out.println("Hello from: " + text);
    }

    public void update() {
        value = Double.toString( Math.random() );
    }

    public void setValue(String value) {
        this.value = value;
    }
    public String getValue() {
        return value;       
    }

}


我想做的是

<xp:view beforeRenderResponse="#{javascript:object1.update()}">

但这似乎不可能,看看sayHello()调用会发生什么。

第一个请求 Pageload

跟进请求 followup

我感谢每一个想法或暗示:)

1 个答案:

答案 0 :(得分:1)

任何自定义控件的一个重要设计原则是封装。如果将它拖到画布上(page,customControl),它应该可以在不依赖于现有条件的情况下工作。

控件使用的参数应该是参数。在控件定义中将它们定义为自定义参数。

然后你有两个选择:使用你在viewScope中保存的SsJS对象或在viewScope中使用托管bean。

让我们说你的控件需要一个名为color的参数,然后控件将被调用如下:

  <xc:myControl color="#{pageBean.color}"></xc:myControl>

在你的bean中,你可以在构造函数中进行所有计算,每个页面只调用一次(你想要的不是什么?)或者在需要时加载延迟:

    public synchronized String getColor() {
            if(this.color==null) {
                  this.initColor();
            }
            return this.color;
    }

如果值不相互依赖,则延迟加载才有意义。

让我们知道它是怎么回事。