【问题标题】:Navigate Component Tree inside a ui:repeat在 ui:repeat 中导航组件树
【发布时间】:2014-06-18 14:58:33
【问题描述】:

我们的 xhtml 中有以下结构:

<ui:repeat ...>
  ...
  <h:selectOneMenu ...>
  ...
    <p:ajax event="change" update="@parent:@parent" process="@parent:@parent" />
  </h:selectOneMenu>
</ui:repeat ...>

在事件处理程序中,我们可以访问代表 selectOneMenu 的 UiComponent。我们可以导航到父级,代表 ui:repeat。在查看孩子时,我希望在网页上看到所有可见的 selectOneMenu,但我只看到一个。触发更改事件的那个。

如何访问 ui:repeat 组件下的同级组件?

动机:

我们基本上创建了一个分组表。 IE。一个表,它被分组为具有属于一起的数据的部分。上面的代码创建了一个组。必须为组中的一个条目选择 selectOneMenu 中的某些值。因此,当一个值更改时,我们必须访问同一组中的所有条目以检查约束是否已完成,否则在违规字段上显示错误消息。

它在浏览器中的外观:

table: there is another outer repeat for creating the contents of this table
..group 1: content of each group is created by the ui:repeat
....row with selectOnMenu
....row with selectOnMenu
....row with selectOnMenu
....row with selectOnMenu
..group 2: content of each group is created by the ui:repeat
....row with selectOnMenu
....row with selectOnMenu
....row with selectOnMenu
....

带有 selectOnMenu 的行

它在事件处理程序中的样子:

UiRepeat --> SelectOneMenu(exactly one)

【问题讨论】:

  • 每个h:selectOneMenu 都需要绑定到一个服务器端模型,由其value 属性给出。您还没有足够的能力,或者您还需要专门获取 UIComponent 实例吗?你在 UIComponent 中寻找什么?
  • 我们需要 UIComponent,因为我们想将验证消息附加到它。我还想了解我们只看到一个组件是否正常,或者我们是否正在做一些特殊/错误的事情,只是为了更好地理解 JSF。
  • Ajax 请求能够发送不同的表单部分。这就是您在 f:ajax execute=""p:ajax process="" 属性中定义的内容。由于它们默认为 @this,因此只有当前组件 (h:selectOneMenu) 被发送到处理,因此将其切换到 @form 可能是解决您问题的关键。顺便说一句,您是否出于任何特定原因使用h:selectOneMenup:ajax?你应该使用 f:ajax 如果 vanilla JSF 或 p:selectOneMenu 如果想用 Prime 来做这一切。
  • @XtremeBiker process 属性应该涵盖我认为的所有 selectOneMenus。我更新了问题中的代码。混合 h: 和 p: 的原因不是很具体。 p:selectOneMenu 看起来真的很丑。
  • 然后使用f:ajax。这是 JSF 组件的标签。

标签: jsf-2 primefaces


【解决方案1】:

ui:repeath:dataTable 这样的组件使用一种称为stamping 的方法来处理子内容。这意味着无论value 中引用的集合中有多少项,子组件只存在一次。当组件被处理时,JSF 为集合中的每个项目重用这个组件(当您查看呈现的 HTML 时,您可以看到 ID 中的索引)。使用这种方法,如果您的集合中有一个或 1000 个项目,组件树的大小是相同的。

以上只是对您注意到的行为的解释。关于您的问题,可能有多种解决方案,具体取决于具体要求和数据的结构方式。

您可以在触发请求的p:ajax 标记上指定的侦听器中进行验证(假设您可以找到模型中当前组的数据)。此侦听器在生命周期的第 5 阶段执行。如果 ajax 请求提交当前组,则数据应该已经在模型中可用。

然后您可以为特定组件添加验证错误消息,如下所示:

FacesContext ctx = FacesContext.getCurrentInstance();
ctx.addMessage("clientId of Component",
               new FacesMessage(FacesMessage.SEVERITY_ERROR, "Your message", null));

获取已提交组件的客户端 ID 的一种方法是在您的 h:selectOneMenu 上为 preValidate 事件设置系统事件侦听器:

<f:event type="preValidate" listener="#{page.preValidate}"/>

在 listener 方法中你可以访问当前组件的客户端 ID(包括当前项的索引!):

public void preValidate(ComponentSystemEvent event) {
  String clientId = event.getComponent().getClientId();
}

然后为所有提交的组件调用此侦听器。此外,您必须以某种方式将此 clientId 映射到模型中的当前项(例如,获取父 ui:repeat 组件的索引)。

以上只是一些基本的想法。

【讨论】:

    【解决方案2】:

    根据您的行为和 Micha 的回答,您应该使用

    <c:forEach>
    

    代替

     <ui:repeat>
    

    。 ForEach 将生成您需要的所有组件。

    【讨论】:

      猜你喜欢
      • 2011-05-26
      • 2013-03-19
      • 2012-03-30
      • 1970-01-01
      • 1970-01-01
      • 2017-09-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多