我在圈子里跑来跑去......
我将尝试解释我正在尝试做什么:我们在Notes数据库中为特定文档(所有Web)都有一个XPage。我们还在数据库中定义了自己的表单。在XPage中打开文档时,将检索表单并填充字段。这很有用,我很高兴地说。
然后,我们定义了某种子表单。我们的想法是子表单以不同的方式显示特定字段。可以有多个子表单附加到表单。所有这些元素都存储在自定义控件中,比如ccForm,ccSubform和ccField。
打开文档后,我得到了可以传递给ccForm的NotesXspDocument对象。自定义控件获取表单定义,并使用重复控件生成ccField和一些ccSubform控件。这些传递了许多参数,例如当前文档作为dataSource参数。当存在子表单时,数据将从主文档中复制并以不同方式存储在ccSubform中声明的临时文档中。子窗体打开并读取不同的表单定义,并使用另一个重复控件生成自己的ccField控件。
因此,NotesXspDocument在顶部创建,并使用DataSource参数传递给所有控件。但是,与子窗体相关的数据存储在临时NotesDocument中。
我的问题:
等待你的回复......
谢谢!
更新
当前的ccSubform,有一些调试:
<?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"
xmlns:xe="http://www.ibm.com/xsp/coreex" enableModifiedFlag="true" id="ccSubForm">
<xp:this.data>
<xp:dominoDocument var="docTemp" ignoreRequestParams="true">
<xp:this.querySaveDocument><![CDATA[#{javascript:dprint("subform qSD")}]]></xp:this.querySaveDocument>
<xp:this.postNewDocument><![CDATA[#{javascript:var sf= new ccAnyForm(docTemp,compositeData.formName);
viewScope.put(compositeData.formName, sf);}]]></xp:this.postNewDocument>
</xp:dominoDocument>
</xp:this.data>
<xp:this.afterRestoreView><![CDATA[#{javascript:try {
dprint("aRV: " + getClientId("ccSubForm"))
var sf= viewScope.get(compositeData.formName);
dprint("sf= " + sf);
if(!sf)
return;
var mdoc:NotesXspDocument= compositeData.dataSource;
var fields= sf.getFields();
for(var fi in fields) {
var fieldName= fields[fi].name;
var values= [];
for(var i= 0; i<rows.size(); i++) {
var tmp= docTemp.getItemValue(fieldName+"$"+i);
values.push(tmp);
dprint(fieldName + "[" + i + "]= " + tmp);
}
mdoc.replaceItemValue(fieldName, values)
}
}catch(e) {
dprint(e);
}}]]></xp:this.afterRestoreView>
<xp:this.beforePageLoad><![CDATA[#{javascript:dprint("bPL: " + getClientId("ccSubForm"))
}]]></xp:this.beforePageLoad>
<xp:tr>
<xp:td styleClass="label">
<xp:text escape="true" value="#{javascript:compositeData.label}"></xp:text>
</xp:td>
<xp:td>
<xp:panel styleClass="subform">
<xp:table style="width:100%" cellspacing="1" cellpadding="0">
<xp:tr>
<xp:repeat var="thisfield" indexVar="coli">
<xp:this.value><![CDATA[#{javascript:var sf= viewScope.get(compositeData.formName);
if(!sf)
return;
var mdoc:NotesXspDocument= compositeData.dataSource;
var fields= sf.getFields();
fields}]]></xp:this.value>
<xp:td styleClass="label">
<xp:text escape="true" value="#{javascript:thisfield.label}"></xp:text>
</xp:td>
</xp:repeat>
</xp:tr>
<xp:repeat rows="#{javascript:compositeData.rows}" disableTheme="true" var="row" indexVar="rowi">
<xp:this.value><![CDATA[#{javascript:var sf= viewScope.get(compositeData.formName);
if(!sf)
return;
var rows= [];
var fields= sf.getFields();
for(var fi in fields) {
var fieldName= fields[fi].name
var values:java.util.Vector= mdoc.getItemValue(fieldName);
if(values) {
for(var i= 0; i<values.size(); i++) {
rows[i]= i+1;
docTemp.replaceItemValue(fieldName+"$"+i, values[i])
}
}
}
return rows;}]]></xp:this.value>
<xp:tr>
<xp:repeat var="currfield" indexVar="coli">
<xp:this.value><![CDATA[#{javascript:var sf= viewScope.get(compositeData.formName);
if(!sf)
return;
var rows= [];
var fields= sf.getFields();
return fields}]]></xp:this.value>
<xp:td>
<xp:this.styleClass><![CDATA[#{javascript:compositeData.dataSource && compositeData.dataSource.isEditable && compositeData.dataSource.isEditable() && !compositeData.isEditable? "data readonly": "data"}]]></xp:this.styleClass>
<xc:ccfieldType="#{javascript:currfield.type}"
fieldLabel="#{javascript:currfield.label}" fieldTitle="#{javascript:currfield.title}"
fieldValue="#{javascript:currfield.value}" fieldIcon="#{javascript:currfield.icon}"
dataSource="#{javascript:docTemp}" formSource="#{javascript:compositeData.formSource}"
<xc:this.rendered><![CDATA[#{javascript:try {
return af? true: false;
} catch(e) {
return false;
}}]]></xc:this.rendered>
<xc:this.fieldName><![CDATA[#{javascript:currfield.name + "$" + rowi}]]></xc:this.fieldName>
<xc:this.fieldIdName><![CDATA[#{javascript:'id'+currfield.name+"$"+rowi}]]></xc:this.fieldIdName>
<xc:this.fieldUniqueName><![CDATA[#{javascript:'unique'+currfield.name+"$"+rowi}]]></xc:this.fieldUniqueName>
</xc:ccDynamicField>
</xp:td>
</xp:repeat>
</xp:tr>
</xp:repeat>
</xp:table>
</xp:panel>
</xp:td>
</xp:tr>
</xp:view>
答案 0 :(得分:2)
您需要退后一步并重新审视该方法。 XPages并不限制您将文档作为数据源。它允许绑定到Java bean ....并且指向解决方案。
第1步:针对每个特殊处理&#39;自定义控件使一个bean能够为您提供所需的产品。
步骤2:设计一个bean作为主窗体中的对象数据源。可以设计对象数据源,以便加载文档。不要尝试存储文档,只存储字段值和unid,以便稍后将其保存回来
步骤3:在该对象数据源中设计返回步骤1中的bean的属性
步骤4:设计自定义控件以将bean作为参数。具体使用数据类型。您可以使用#{objDatasource.propname}来提供参数。在自定义控件内部使用标准EL来绑定bean。
现在,当您保存数据源时,您拥有主bean中的所有数据以及非常干净的布局。
这对你有用吗?
答案 1 :(得分:1)
我很难看到创建临时文档,复制数据,然后写回其他数据而不保存文档的原因。我认为你不需要那么复杂,因为:
currentDocument
变量获取最近的dominoDocument数据源,导航回组件树。或者,如果您的主数据源始终称为document1
,则可以使用它。您需要确保的是,相关的dominoDocument数据源是在以上自定义控件的位置定义的(如果您在树中可视化组件,父母和子项)。您将无法在下拉列表中选择字段。或者,如果您想要临时文档方法,我建议实际将那些带有某些键的文档保存回主文档。然后使用Save All Documents操作,让你将它们放在数据库中,并在主文档的postSaveDocument中检索它们(我个人在按钮中使用脚本)来检索文档,将值写回主文档并删除/标记,以便代理可以删除它们。 sessionAsSigner将在此处获得任何访问限制。
如果您有理由不想混淆数据库,请不要忘记XPages允许您编辑来自多个数据库的数据,这样您就可以随时拥有“临时存储”这些子-documents被创建,编辑和存储。可以计算数据库,因此它可以与环境无关 - 开发,测试,产品。如果需要,可以在该数据库上单独设置访问权限(例如,允许用户从该临时存储库中删除)。
答案 2 :(得分:0)
每个文档数据源都有自己的一组查询类型事件。您可以使用它们来获取数据,然后将其写回主文档。
霍华德