我必须做一些我需要控制的计算,我只想在每次请求时执行一次并存储它。 (例如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()调用会发生什么。
第一个请求
跟进请求
我感谢每一个想法或暗示:)
答案 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;
}
如果值不相互依赖,则延迟加载才有意义。
让我们知道它是怎么回事。