XPages在视图中内联编辑文档,并在保存文档后关闭文档

XPages在视图中内联编辑文档,并在保存文档后关闭文档,xpages,xpages-ssjs,Xpages,Xpages Ssjs,我有一个repeat控件,它在特定视图中显示文档。对于每个文档(数据行),用户可以在线编辑和保存这些项目。我有一个额外的按钮,它将单个文档标记为默认文档,这仅在编辑模式下可见,在它将当前文档标记为默认文档之前,它将遍历所有其他文档并取消将它们标记为默认文档。此标记为默认值第一次起作用,但当我再次尝试(第二次)时,会产生复制冲突 编辑按钮只是将模式更改为编辑模式 Save执行以下操作(部分刷新): 我认为保存冲突的原因是因为您在内存(XPage上)和磁盘上处理相同的文档。内存中文档的时间戳在保存磁

我有一个repeat控件,它在特定视图中显示文档。对于每个文档(数据行),用户可以在线编辑和保存这些项目。我有一个额外的按钮,它将单个文档标记为默认文档,这仅在编辑模式下可见,在它将当前文档标记为默认文档之前,它将遍历所有其他文档并取消将它们标记为默认文档。此标记为默认值第一次起作用,但当我再次尝试(第二次)时,会产生复制冲突

编辑按钮只是将模式更改为编辑模式

Save执行以下操作(部分刷新):


我认为保存冲突的原因是因为您在内存(XPage上)和磁盘上处理相同的文档。内存中文档的时间戳在保存磁盘上文档之前,因此在保存内存中文档时存在保存冲突

如果不介意在没有冲突的情况下相互覆盖,可以在表单中设置一个属性,以防止保存冲突。在表单属性中,在第一个选项卡上:冲突处理-不要创建冲突

解决此问题而不设置属性的最简单方法是一次只能编辑一个文档。具有包含当前可编辑文档的unid的viewScope变量。设置基于此属性呈现的表单。使用文档中的默认值将字段绑定到requestScope。当用户单击保存时,通过unid/update从requestScope值查找文档。这样,您只需要处理磁盘上的文档

编辑-示例代码:

function markAsDefault(deliveryDoc) {
    try {
        var db:NotesDatabase = deliveryDoc.getParentDatabase();
        var vwDeliveryAddress:NotesView = db.getView("viewName");

        var dc:NotesDocumentCollection = vwDeliveryAddress.getAllDocumentsByKey(deliveryDoc.getItemValueString("fldID"), true);

        var strUniversalID:String;

        strUniversalID = deliveryDoc.getDocument().getUniversalID();

        if (dc.getCount() > 0) {
            var doc:NotesDocument = dc.getFirstDocument()
            var nextDoc:NotesDocument;

            // mark all other docs as not default
            while (doc != null) {
                nextDoc = dc.getNextDocument();

                if (doc.getUniversalID() != strUniversalID) {
                    doc.replaceItemValue("isDefault", "");
                    doc.save();

                    doc.recycle();
                }

                doc = nextDoc;
            }
        }

        deliveryDoc.replaceItemValue("isDefault", "Yes");
    } catch (e) {
        log.logError(e.toString(), SEVERITY_HIGH, e.toString(), null, "website.nsf", "markAsDefault()", null, null);
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
    <xp:this.data>
        <xp:dominoView var="peopleView" viewName="People"></xp:dominoView>
    </xp:this.data>
    <xp:table id="peopleTable">
        <xp:repeat id="peopleRepeat" rows="30" value="#{peopleView}" var="personRow">
            <xp:panel rendered="#{javascript:return ( viewScope.editableUnid === personRow.getUniversalID() );}"
                tagName="tr">
                <td>
                    <xp:inputText value="#{requestScope.firstName}" defaultValue="#{personRow.first_name}" />
                </td>
                <td>
                    <xp:inputText value="#{requestScope.lastName}" defaultValue="#{personRow.last_name}" />
                </td>
                <td>
                    <xp:button id="saveButton" value="Save">
                        <xp:eventHandler event="onclick" submit="true" refreshMode="partial" refreshId="peopleTable">
                            <xp:this.action><![CDATA[#{javascript:var doc = database.getDocumentByUNID( viewScope.editableUnid );
doc.replaceItemValue( 'first_name', requestScope.firstName );
doc.replaceItemValue( 'last_name', requestScope.lastName );
doc.save();
viewScope.editableUnid = null;}]]></xp:this.action>
                        </xp:eventHandler>
                    </xp:button>
                    <xp:button id="cancelButton" value="Cancel">
                        <xp:eventHandler event="onclick" submit="true" refreshMode="partial" refreshId="peopleTable">
                            <xp:this.action><![CDATA[#{javascript:viewScope.editableUnid = null;}]]></xp:this.action>
                        </xp:eventHandler>
                    </xp:button>
                </td>
            </xp:panel>
            <xp:panel rendered="#{javascript:return ( viewScope.editableUnid != personRow.getUniversalID() );}" tagName="tr">
                <td>
                    <xp:text value="#{personRow.first_name}" />
                </td>
                <td>
                    <xp:text value="#{personRow.last_name}" />
                </td>
                <td>
                    <xp:button id="editButton" value="Edit">
                        <xp:eventHandler event="onclick" submit="true" refreshMode="partial" refreshId="peopleTable">
                            <xp:this.action><![CDATA[#{javascript:viewScope.editableUnid = personRow.getUniversalID();}]]></xp:this.action>
                        </xp:eventHandler>
                    </xp:button>
                </td>
            </xp:panel>
        </xp:repeat>
    </xp:table>
</xp:view>


重复控制将如何工作?我是否必须显示一个对话框来修改每个文档,或者它是否会像现在一样在线工作?如果将repeat控件绑定到视图,请在计算字段中显示值。在repeat中有一个包含相同字段的表单。可以使用视图值作为表单字段的默认值。文档的unid可以从行变量中获取。这样,当从视图中读取值时,可以获得良好的性能/较小的内存使用。当“可编辑”unid与行相同时,隐藏计算字段+编辑控件,并显示表单字段+保存控件。是否可以使用使用重复控件(其中重复控件的数据源是按列值过滤的视图)使用相同的简单代码示例来更新答案我在repeat控件中有一个面板,它获取后端文档,并用作数据源。我尝试将该数据源的作用域设置为“查看作用域”,但没有帮助。我用我的意思的示例更新了我的答案。由于它纯粹用于演示,底层文档只有两个字段。名字和姓氏。repeat使用的视图有两列绑定到这些字段。请输入post markAsDefaut()代码。调用getDocument()可能会导致冲突。字符串比较对我来说似乎有点可疑。非常感谢您指出Frantisek,非常感谢。在我对字符串比较发表评论几分钟后,我意识到它是SSJS,所以按惯例字符串!=字符串应该可以工作。因此,如果没有帮助,我也不会感到惊讶:-(是吗?这还没有解决问题-我使用openpage并打开同一个页面来解决这个特定问题。
function markAsDefault(deliveryDoc) {
    try {
        var db:NotesDatabase = deliveryDoc.getParentDatabase();
        var vwDeliveryAddress:NotesView = db.getView("viewName");

        var dc:NotesDocumentCollection = vwDeliveryAddress.getAllDocumentsByKey(deliveryDoc.getItemValueString("fldID"), true);

        var strUniversalID:String;

        strUniversalID = deliveryDoc.getDocument().getUniversalID();

        if (dc.getCount() > 0) {
            var doc:NotesDocument = dc.getFirstDocument()
            var nextDoc:NotesDocument;

            // mark all other docs as not default
            while (doc != null) {
                nextDoc = dc.getNextDocument();

                if (doc.getUniversalID() != strUniversalID) {
                    doc.replaceItemValue("isDefault", "");
                    doc.save();

                    doc.recycle();
                }

                doc = nextDoc;
            }
        }

        deliveryDoc.replaceItemValue("isDefault", "Yes");
    } catch (e) {
        log.logError(e.toString(), SEVERITY_HIGH, e.toString(), null, "website.nsf", "markAsDefault()", null, null);
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
    <xp:this.data>
        <xp:dominoView var="peopleView" viewName="People"></xp:dominoView>
    </xp:this.data>
    <xp:table id="peopleTable">
        <xp:repeat id="peopleRepeat" rows="30" value="#{peopleView}" var="personRow">
            <xp:panel rendered="#{javascript:return ( viewScope.editableUnid === personRow.getUniversalID() );}"
                tagName="tr">
                <td>
                    <xp:inputText value="#{requestScope.firstName}" defaultValue="#{personRow.first_name}" />
                </td>
                <td>
                    <xp:inputText value="#{requestScope.lastName}" defaultValue="#{personRow.last_name}" />
                </td>
                <td>
                    <xp:button id="saveButton" value="Save">
                        <xp:eventHandler event="onclick" submit="true" refreshMode="partial" refreshId="peopleTable">
                            <xp:this.action><![CDATA[#{javascript:var doc = database.getDocumentByUNID( viewScope.editableUnid );
doc.replaceItemValue( 'first_name', requestScope.firstName );
doc.replaceItemValue( 'last_name', requestScope.lastName );
doc.save();
viewScope.editableUnid = null;}]]></xp:this.action>
                        </xp:eventHandler>
                    </xp:button>
                    <xp:button id="cancelButton" value="Cancel">
                        <xp:eventHandler event="onclick" submit="true" refreshMode="partial" refreshId="peopleTable">
                            <xp:this.action><![CDATA[#{javascript:viewScope.editableUnid = null;}]]></xp:this.action>
                        </xp:eventHandler>
                    </xp:button>
                </td>
            </xp:panel>
            <xp:panel rendered="#{javascript:return ( viewScope.editableUnid != personRow.getUniversalID() );}" tagName="tr">
                <td>
                    <xp:text value="#{personRow.first_name}" />
                </td>
                <td>
                    <xp:text value="#{personRow.last_name}" />
                </td>
                <td>
                    <xp:button id="editButton" value="Edit">
                        <xp:eventHandler event="onclick" submit="true" refreshMode="partial" refreshId="peopleTable">
                            <xp:this.action><![CDATA[#{javascript:viewScope.editableUnid = personRow.getUniversalID();}]]></xp:this.action>
                        </xp:eventHandler>
                    </xp:button>
                </td>
            </xp:panel>
        </xp:repeat>
    </xp:table>
</xp:view>