问题描述
在采购订单模块中,我们需要根据采购订单的来源选择方法、竞争类型和总成本提出某些问题.这些问题可能会随着时间的推移以及数据库的不同实例之间发生变化.
In a purchase order module, we need to ask certain questions depending on the source selection method, competition type and total cost of the PO. These questions are likely to change over time and in between different instances of the database.
所以我有一个包含问题的视图,这样我就可以将问题动态添加到 XPage 中,而无需更改代码.每个问题的答案将存储在一个字段中.因此,包含问题的文档有一个名为 FieldName 的字段,用于提供将使用的字段名称.不幸的是,我无法将这些动态字段绑定到文档.
So I have a view containing the questions, so that I can add questions dynamically to my XPage without needing to change the code. The answer to each question will be stored in a field. So, the document that contains the question has a field called FieldName that is used to supply the field name that will be used. Unfortunately, I am having no luck binding these dynamic fields to the document.
<xp:this.data>
<xp:dominoView var="competitionQuestionView"
viewName="CompetitionQuestions">
</xp:dominoView>
</xp:this.data>
<xp:repeat id="repeat2" rows="30" var="rowData" style="width:700px"
value="#{competitionQuestionView}">
<xp:label id="label1">
<xp:this.value><![CDATA[#{javascript:rowData.getColumnValue("Question");}]]></xp:this.value>
</xp:label>
<xp:inputText id="inputText1">
<xp:this.rendered><![CDATA[#{javascript:rowData.getColumnValue("FieldType") == "Text Box"; }]]></xp:this.rendered>
<xp:this.value><![CDATA[#{javascript:poDoc[rowData.getColumnValue ("FieldName")];}]]></xp:this.value>
</xp:inputText>
</xp:repeat>
我尝试了各种方法来做到这一点,包括制作一个 dynamicInputText 自定义控件来传递字段名称,但没有运气.我得到的最接近的是当我使用它时:
I've tried various ways to do this, including making a dynamicInputText custom control to pass in the field name, but without luck. The closest I got was when I used this:
<xp:this.value>
<![CDATA[#{javascript:tmp = rowData.getColumnValue ("FieldName");'#{poDoc.'+tmp+'}';}]]>
</xp:this.value>
这给了我类似 #{poDoc.justification} 的东西,这是我想传递给绑定"的东西,但它最终显示为文本值.
That gave me something like #{poDoc.justification}, which was what I wanted to pass to the 'binding', but it ended up displaying as the text value.
我确实尝试使用 $ 来计算加载时的值,但我猜测它不起作用,因为我的(和 rowData)视图在加载时不可用.当我想使用部分刷新时,最终会出现一个问题,因为我想要显示的字段的标准有所更新.
I did try using $ to compute the value on load, but I am guessing that it didn't work because my (and the rowData) view is not available on load. That would eventually present a problem when I wanted to use partial refreshes due to updates on the criteria for which fields I want to display anyway.
其他问题的一些答案看起来很有希望,但没有提供代码,所以我无法弄清楚.
Some of the answers to other questions looked promising, but no code was provided, so I couldn't figure it out.
推荐答案
在幕后,所有数据源都使用 getValue
和 setValue
方法(分别)读取和写数据.对于 Domino 文档数据源,表达式 #{currentDocument.fieldName}
在运行时被转换为 currentDocument.getValue('fieldName')
或 currentDocument.setValue('fieldName',postedValue)
,取决于当前操作是读还是写.
Behind the scenes, all data sources use the methods getValue
and setValue
to (respectively) read and write data. In the case of a Domino document data source, the expression #{currentDocument.fieldName}
gets translated at runtime to either currentDocument.getValue('fieldName')
or currentDocument.setValue('fieldName', postedValue)
, depending on whether the current operation is a read or a write.
如果您将其他可编辑组件的 value 属性设置为 SSJS 值绑定,则它无法执行此自动翻译...因此它只会将每个操作视为读取.
If you set the value attribute of an otherwise editable component to a SSJS value binding, then it can't do this auto-translation... so it just treats every operation as a read.
换句话说,要使读/写工作,它必须是无前缀"表达式.
In other words, for read/write to work, it has to be a "prefixless" expression.
有几种方法可以解决这个问题,但最简单的方法是使用数据上下文将 SSJS 表达式映射到单个变量.数据上下文可以附加到视图根或面板,因此在您的示例中,您希望将重复内容包装在面板中:
There are several ways to handle this, but the easiest is to use a data context to map a SSJS expression to a single variable. Data contexts can be attached to the view root or to a panel, so in your example, you'd want to wrap your repeat contents in a panel:
<xp:repeat id="repeat2" rows="30" var="rowData" style="width:700px"
value="#{competitionQuestionView}">
<xp:panel>
<xp:this.dataContexts>
<xp:dataContext var="fieldName">
<xp:this.value><![CDATA[#{javascript:rowData.getColumnValue ("FieldName");}]]></xp:this.value>
</xp:dataContext>
</xp:this.dataContexts>
<xp:label id="label1">
<xp:this.value><![CDATA[#{javascript:rowData.getColumnValue("Question");}]]> </xp:this.value>
</xp:label>
<xp:inputText id="inputText1" value="#{poDoc[fieldName]}">
<xp:this.rendered><![CDATA[#{javascript:rowData.getColumnValue("FieldType") == "Text Box"; }]]></xp:this.rendered>
</xp:inputText>
</xp:panel>
</xp:repeat>
因此对于重复的每个成员,变量 fieldName
成为该行的列值.然后在输入组件的 value 属性中,使用数组语法(而不是通常的点语法),因为我们想使用变量来指定字段名称,而不是硬编码名称.
So for each member of the repeat, the variable fieldName
becomes the column value for that row. Then in the value attribute of the input component, the array syntax is used (instead of the usual dot syntax) since we want to use a variable to specify the field name instead of hardcoding the name.
然而,理论上,您应该能够完全跳过数据上下文,只需将以下内容设置为字段的值表达式:
In theory, however, you should be able to skip the data context entirely, and just set the following to be the value expression for the field:
#{poDoc[rowData.FieldName]}
在默认(无前缀")EL 解析器的上下文中,rowData.FieldName
应返回与 rowData.getColumnValue("FieldName")
返回的值完全相同的值在 SSJS 表达式的上下文中.
In the context of the default ("prefixless") EL resolver, rowData.FieldName
should return precisely the same value that rowData.getColumnValue("FieldName")
returns in the context of a SSJS expression.
最后,我建议阅读这个表达式语言教程熟悉您可以在核心 EL 中完成的所有事情,而无需求助于 SSJS.
Finally, I would recommend reading this Expression Language tutorial to become familiar with all of the things that you can do in core EL without resorting to SSJS.
这篇关于重复控件中的动态绑定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!