将数据保存到compositeData.dataSource

时间:2014-10-16 13:44:09

标签: xpages xpages-ssjs

我在圈子里跑来跑去......

我将尝试解释我正在尝试做什么:我们在Notes数据库中为特定文档(所有Web)都有一个XPage。我们还在数据库中定义了自己的表单。在XPage中打开文档时,将检索表单并填充字段。这很有用,我很高兴地说。

然后,我们定义了某种子表单。我们的想法是子表单以不同的方式显示特定字段。可以有多个子表单附加到表单。所有这些元素都存储在自定义控件中,比如ccForm,ccSubform和ccField。

打开文档后,我得到了可以传递给ccForm的NotesXspDocument对象。自定义控件获取表单定义,并使用重复控件生成ccField和一些ccSubform控件。这些传递了许多参数,例如当前文档作为dataSource参数。当存在子表单时,数据将从主文档中复制并以不同方式存储在ccSubform中声明的临时文档中。子窗体打开并读取不同的表单定义,并使用另一个重复控件生成自己的ccField控件。

因此,NotesXspDocument在顶部创建,并使用DataSource参数传递给所有控件。但是,与子窗体相关的数据存储在临时NotesDocument中。

我的问题:

  • 单击“保存”按钮时,只触发主XPage的QuerySave事件,我无法找到如何为子窗体内的临时文档触发某种Save事件;我想将数据复制回主文档
  • 我可以使用其他一些事件将数据复制回主文档吗?
  • 我在afterRestoreView中有通常的compositeData问题;我怎么能绕过它?

等待你的回复......

谢谢!

更新

当前的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>

3 个答案:

答案 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数据源是在以上自定义控件的位置定义的(如果您在树中可视化组件,父母和子项)。您将无法在下拉列表中选择字段。
  • 如果设置的值不在主文档中,则可以在自定义控件上任何控件的defaultValue属性上计算。或者您可以在beforePageLoad / beforeRenderResponse等期间在主文档上设置相关字段。
  • 动态内容控制可用于以编程方式仅加载相关的自定义控件。

或者,如果您想要临时文档方法,我建议实际将那些带有某些键的文档保存回主文档。然后使用Save All Documents操作,让你将它们放在数据库中,并在主文档的postSaveDocument中检索它们(我个人在按钮中使用脚本)来检索文档,将值写回主文档并删除/标记,以便代理可以删除它们。 sessionAsSigner将在此处获得任何访问限制。

如果您有理由不想混淆数据库,请不要忘记XPages允许您编辑来自多个数据库的数据,这样您就可以随时拥有“临时存储”这些子-documents被创建,编辑和存储。可以计算数据库,因此它可以与环境无关 - 开发,测试,产品。如果需要,可以在该数据库上单独设置访问权限(例如,允许用户从该临时存储库中删除)。

答案 2 :(得分:0)

每个文档数据源都有自己的一组查询类型事件。您可以使用它们来获取数据,然后将其写回主文档。

霍华德