这个问题困扰了我一段时间,我似乎无法解决它。所以我把它简化到最基本的层面。1.创建一个新的XPage并将其绑定到一个正在退出的表单2.创建了一个名为"displayPanel"的面板3.在面板内部创建一个comboBox,并为其提供几个值和任何有效值的默认值。4.设置对displayPanel进行部分刷新的onChange事件5.添加一个计算字段,该字段仅显示comboBox的值。6添加了一个按钮,用于部分刷新displayPanel onClick。
打开XPage,计算字段为空,进行更改,计算字段显示。
再次打开XPage,单击刷新按钮,计算字段显示
现在这是一个非常简单的例子,但我需要做的实际上更复杂,但comboBox的值(不需要是comboBox)在执行刷新之前是不可用的。这只是新文档首次获得默认值时的问题。
我添加了这个:
view.postScript("XSP.partialRefreshGet('#{id:displayPanel}')")
到每个页面事件,但它似乎不会像单击按钮或进行更改那样进行实际的页面刷新。
我不知道该怎么做。如果我能让这个简单的例子发挥作用,那么我所需要的其余部分就很容易了。
感谢
Fredrik走在了正确的轨道上——您应该在事件期间手动设置值——但我要添加两个注意事项:
- 调用
setValue
而不是replaceItemValue
(例如document1.setValue("myComboBox", "Default Value");
)。这种相对优势可能不适用于这种特定情况,但你应该习惯于总是调用setValue
而不是replaceItemValue
(以及getValue
而不是getItemValue
),这样,当你遇到真正不同的情况时,你就可以免费获得这种优势。。。在剩下的时间里,这些方法是等效的,所以您最好只使用需要较少键入的方法。:) - 您可能需要在
afterPageLoad
中执行此操作:在beforePageLoad
期间,数据源可能尚未准备好;根据您在页面其他地方引用默认值的原因,beforeRenderResponse
可能为时已晚;而CCD_ 11肯定太晚了
。。。这让我想到了为什么defaultValue
属性没有按照我们预期的方式运行,尤其是对于我们这些有开发Notes客户端应用程序经验的人来说。
XPages引擎将每个HTTP请求的处理划分为几个"阶段"。根据请求的类型(初始页面加载、部分刷新事件等)和其他因素,生命周期将由6个阶段和2个阶段组成。
本教程页面提供了对这些阶段的极好描述,但在这个问题的上下文中,以下内容特别令人感兴趣:
-
应用请求值
当事件针对已加载的页面运行时(例如,用户单击按钮,或从具有
onChange
事件的组合框中选择值等),发送到服务器以触发事件的HTTP请求包括表示所有可编辑组件值的POST数据。此阶段将这些值临时存储在任何受影响组件的submittedValue
属性中,但数据源还不"知道"新值是什么。 -
过程验证
这个阶段运行任何适用的验证器,如果失败,则直接跳到最后一个阶段(这意味着它永远不会运行触发事件的代码)。
-
更新模型值
如果没有验证失败(或者没有定义任何验证),则此阶段将获取提交的值,并将其实际存储在相应的数据源中。在此之前,数据源完全不知道存在任何用户交互。这是为了避免用户输入甚至可能无效而过早地污染任何后端数据。请记住,并非每个数据源都是一个"文档";可能是通过CCD_ 15改变的关系数据,即CCD_。。。这基本上就是这个阶段所做的:它获取
submittedValue
并在相应的数据源上调用setValue
(然后将submittedValue
设置为null
)。这种分离允许组件只是后端数据状态的视觉表示——用户与之交互的视觉表示;我们的代码应该始终通过数据源的抽象层与后端数据直接交互。 -
渲染响应
一旦所有其他阶段都已运行(或已跳过),此阶段就会向使用者发送响应。换句话说,它将HTML(或JSON、XML或PDF等)发送回浏览器。但在这个问题的上下文中,最突出的一点是,在初始页面加载时,之前的阶段总是被跳过。当用户第一次访问页面时,他们还没有机会输入任何数据,因此没有要应用的请求值。由于没有发布任何数据,因此没有什么可验证的。而且——最相关的是——没有什么可以推送到数据模型中。因此,组件树的表示(或其子集,在部分刷新事件的情况下)总是需要发送给用户,但在用户与该表示交互之前,数据源保持在呈现最近响应时的任何状态。。。这就是为什么,如果您希望数据源的特定属性在用户与其交互之前具有特定值,则代码需要手动设置该属性的值。
总之,组件是可视化的。数据源是抽象。如果组件属性被简单地称为defaultClientValue
而不是defaultValue
,那么这种行为可能会更加不言自明,因为它本质上就是这样:对用户的默认建议是将哪些数据发送回数据源。但在他们这样做之前,数据源还没有收到这个值。因此,如果在初始页面加载时,您需要一个数据源属性具有一个默认状态下没有的值,那么您应该手动调用setValue
为其提供所需的值。
p.S.具有讽刺意味的是,如果您调用partialRefreshPost
而不是partialRefreshGet
,您很可能已经获得了您想要的结果,因为前者发送所有表单数据,而后者只是要求重新呈现现有组件状态。但是,您会强制发送所有表单数据,只是为了更新一个数据源属性,所以最好简单地执行上面描述的操作。