Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jsf-2/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Jsf 2 如何将支持bean中的FacesMessage附加到ui中的特定字段:repeat?_Jsf 2_Facelets_Messages_Uirepeat_Backing Beans - Fatal编程技术网

Jsf 2 如何将支持bean中的FacesMessage附加到ui中的特定字段:repeat?

Jsf 2 如何将支持bean中的FacesMessage附加到ui中的特定字段:repeat?,jsf-2,facelets,messages,uirepeat,backing-beans,Jsf 2,Facelets,Messages,Uirepeat,Backing Beans,我有一个输入元素数量可变的表单,如下所示: <ui:repeat var="_lang" value="#{myBean.languages}"> <h:inputTextarea value="${_lang.title}" id="theTitle" /> <h:messages for="theTitle"/> </ui:repeat> 我在节点上调用它,它是ui:repeat周围h:panelGroup的绑定ui组件。(我

我有一个输入元素数量可变的表单,如下所示:

<ui:repeat var="_lang" value="#{myBean.languages}">
    <h:inputTextarea value="${_lang.title}" id="theTitle" />
    <h:messages for="theTitle"/>
</ui:repeat>
我在
节点上调用它,它是
ui:repeat
周围
h:panelGroup
的绑定
ui组件。(我使用递归是因为我的实时应用程序有一个稍微嵌套的结构)我认为这应该给我所有的“标题”文本区域,这样我就可以随意添加消息和读取属性。唉,该方法只返回一个“theTitle”组件,日志消息显示了原因:


在生成页面的DOM中,ID类似于“myform:myPanelGroup:0:theTitle”(包括
ui:repeat
的迭代计数器),而bean只看到getClientId()s,如
myform:myPanelGroup:theTitle
,并且只存在一次,最后一次(我想是吧?)迭代。

尝试将输入组件绑定到映射/数组失败,因为JSF组件树中没有多个组件,只有一个。
在生成JSF组件树的视图构建期间不会运行。相反,它在视图呈现时运行,生成HTML输出。换句话说,
的子组件在每次迭代生成HTML输出时都会被重用

抛出特定的异常“Target Unreachable”,“BracketSuffix”“returned null”,因为变量
{u lang}
在视图构建期间不可用,此时构建UI组件树并计算所有
id
绑定
属性。它仅在视图渲染期间可用

如果改用
,这些绑定尝试就会成功。它在视图构建期间运行,生成JSF组件树。然后,您将得到子组件的多个物理实例,这些实例依次生成各自的HTML输出,而无需重复使用多次

由于前面提到的原因,加入一个小组并试图找到所有的孩子显然是行不通的。
不会在组件树中实际生成多个JSF组件。相反,它重用同一组件多次生成HTML输出,具体取决于当前迭代轮的状态

替换应该有效。可能您正面临时间问题,因为它在视图构建期间运行,并且您正在准备模型,例如,
preRenderView
,而不是
@PostConstruct
等等

如果你仔细阅读,以上所有内容都更容易理解


至于您的具体功能需求,您通常会使用
验证器
进行工作。如果您在输入组件上注册它,那么它将在每一轮迭代中被调用。您将立即获得具有正确状态的正确输入组件作为
validate()
方法的第二个参数,并将提交/转换的值作为第三个参数

如果您确实需要在之后执行作业,例如,因为您需要了解所有输入,那么您应该自己以编程方式迭代
。您可以借助它来实现这一点,它允许您收集每个迭代轮的输入组件状态

例如

另见:

    • 还有另一种选择:自己更换整个面部信息。用21点。而且

      无论如何,基于与我们的讨论,我们选择了避免整个visitTree混乱,并建立我们自己的消息机制。这包括:

      1) 包含多重映射映射的ViewScope bean:

      private Map<Object, Multimap<String, String>> fieldValidationMessages = new HashMap<>();
      
      private Map fieldValidationMessages=new HashMap();
      
      这将
      对象
      作为字段标识符(可以是相应的bean本身、UI组件,甚至是运行时在
      UI:repeat
      中生成的
      字符串
      。然后,该标识符可以在另一个任意数量的子字段上具有任意数量的
      字符串
      消息。非常灵活

      bean还提供了方便的方法来获取和设置字段和子字段上的消息,以及检查是否存储了任何消息(即是否存在验证错误)

      2) 一个简单的xhtml include,用于显示给定字段的错误消息,并替换“
      h:messages for…”


      就这样。关键在于,它在生命周期的应用程序和呈现阶段而不是JSF自己的验证阶段运行。但是,由于我们的项目已经决定进行bean验证而不是生命周期验证,这不是一个问题。

      我觉得第一个或最后一个方法最接近。最后一个只能是一些奇怪的JSTL版本的东西。类似这样的东西工作得很好,只是在集合上迭代就不行了。第一个。。。要是那个奇怪的括号错误没有发生就好了……我在七年前找到了一个有问题的人,但他们也没有解决。谢谢你的扩展答案,这是一条新的、有价值的信息!非常非常有趣!因此visitTree()可以看到getChildren()不存在的东西。好。。。只要它起作用——而且确实如此。:)有一个奇怪的例外:当我从两个元素的列表生成网页时,DOM包含myform:0和myform:1,但visitTree声称也在访问myform:2,它看起来只是myform:1的克隆。这是出于设计吗?换句话说,我现在只得到三个“theTitle”(客户端id无效),而不是(使用我先前的getChildren()尝试)得到一个“theTitle”,最后一个迭代计数不存在。正确的数字应该是两个“标题”…不,模型仍然只包含两行。但我会在试验台上检查。。。明天在实际的项目代码中发生了太多的事情。哪个JSF impl/version?如果是莫哈拉,那就做吧
      final FacesContext facesContext = FacesContext.getCurrentInstance();
      UIComponent repeat = getItSomehow(); // findComponent, binding, etc.
      
      repeat.visitTree(VisitContext.createVisitContext(facesContext), new VisitCallback() {
          @Override
          public VisitResult visit(VisitContext context, UIComponent target) {
              if (target instanceof UIInput && target.getId().equals("theTitle")) {
                  String clientId = target.getClientId(facesContext);
                  Object value = ((UIInput) target).getValue();
                  // ...
                  facesContext.addMessage(clientId, message);                
              }
              return VisitResult.ACCEPT;
          }
      });
      
      private Map<Object, Multimap<String, String>> fieldValidationMessages = new HashMap<>();