Javascript 如何使用DHTML动态创建表单控件,并使用JSF处理所有这些控件?

Javascript 如何使用DHTML动态创建表单控件,并使用JSF处理所有这些控件?,javascript,ajax,jsf,dhtml,web-controls,Javascript,Ajax,Jsf,Dhtml,Web Controls,假设下一种情况:创建一个视图,其中表单控件使用DHTML呈现(即,每次用户按下按钮时,都会创建一个包含字段的新行,并生成字段标识符,并将其分配给与“form1control1”具有相同DHTML的字段,依此类推),但是,如果该控件与ViewRoot中的任何UIComponent都不相关(因为它们是由客户端动态创建的,因此服务器不知道它们在表单中)我如何处理a)查找该控件和b)在JSF中使用该名称进行验证和处理? 通过JSP方法,控制名称和值的HttpRequest将随附,通过调用request对

假设下一种情况:创建一个视图,其中表单控件使用DHTML呈现(即,每次用户按下按钮时,都会创建一个包含字段的新行,并生成字段标识符,并将其分配给与“form1control1”具有相同DHTML的字段,依此类推),但是,如果该控件与ViewRoot中的任何UIComponent都不相关(因为它们是由客户端动态创建的,因此服务器不知道它们在表单中)我如何处理a)查找该控件和b)在JSF中使用该名称进行验证和处理?

通过JSP方法,控制名称和值的HttpRequest将随附,通过调用request对象并使用一种算法搜索所有具有模式的对象,可以轻松处理这些项,因此在有名为“form1control1”的对象的地方,我将使用例如request.getParameterNames()找到它和request.getParameter(“form”+N+“control”+M),以便稍后使用所有命名参数的代码进行验证和转换

据我所知,在JSF中,我需要通过在JSP中用一个标记声明控件来将一个控件与一个UIComponent相关联,因此,要将任何一个或两个验证器或转换器附加到此控件,以便RootView知道该控件在那里并具有关联的名称,它将期望管理该控件,但我不需要JSP声明的控件,而是由客户端使用JavaScript动态创建的控件,随后发送到服务器并作为任何其他JSP声明的UIComponent处理,因此我可以重新提出我的问题:如何处理未在任何JSP中声明并由客户端使用DHTML动态构建的控件,以进行验证,转换和处理?

我想我可以通过AJAX来实现这一点,只要我使用新控件创建新行,并通过编程方式向树中添加任何控件来更新它,就可以调用ViewRoot,但是,我认为这种方法非常昂贵,因为我需要a)生成AJAX请求,b)每当我使用表示使用处理时间和分配内存资源的表单执行操作时,向服务器提供工作;因此,我更倾向于避免使用AJAX来更新ViewRoot和创建/删除的任何新控件,显然,如果必须使用AJAX来更新ViewRoot以达到该行为,我不会关闭。如果我能避免最后一种方法,那就太受欢迎了


非常感谢您提前提供反馈。

我不知道在客户端上创建组件的任何方法,这些组件在提交回服务器时将自动绑定到viewstate。我认为您需要ajax来实现这一点


当然,您可以动态创建输入元素,并且仍然可以直接从HttpServletRequest获取最终用户输入的值,但是对于JSF来说,整个范例都围绕着维护viewstate展开。

这是可能的,但是您需要对JSF API有一个相对良好的理解,因为它并不简单。这样做的方法是在组件树中有一个基于Java的自定义组件,作为您将在客户端上创建的动态HTML的容器

通过
UIComponent#decode
Renderer#decode
(如果使用单独的渲染器),Java自定义组件可以在回发后检查请求,并使用动态创建的组件发布到服务器的原始值填充自身

了解其工作原理的一个好方法就是检查现有的渲染器。例如,CheckboxRenderer中的简化示例:

public void decode(FacesContext context, UIComponent component) {

    clientId = component.getClientId(context);

    // Convert the new value
    Map<String, String> requestParameterMap = context.getExternalContext().getRequestParameterMap();
    boolean isChecked = isChecked(requestParameterMap.get(clientId));
    setSubmittedValue(component, isChecked);
}

private static boolean isChecked(String value) {

    return "on".equalsIgnoreCase(value)
           || "yes".equalsIgnoreCase(value)
           || "true".equalsIgnoreCase(value);

}
public void解码(FacesContext上下文,UIComponent){
clientId=component.getClientId(上下文);
//转换新值
Map requestParameterMap=context.getExternalContext().getRequestParameterMap();
布尔值isChecked=isChecked(requestParameterMap.get(clientId));
设置SubmittedValue(组件,已检查);
}
私有静态布尔值已检查(字符串值){
返回“on”.equalsIgnoreCase(值)
||“是”。相等信号情况(值)
||“真”。相等信号情况(值);
}
在decode方法中,您处理所有的“虚拟组件”,然后JSF将所有内容视为一个组件

动态创建在客户端上动态创建的组件的服务器端表示也或多或少是可能的。我说的或多或少是因为Mojarra(JSF参考实现)目前有一些bug,这些bug阻止了它在所有情况下都能正常工作。看,例如MyFaces似乎工作正常

您可能对Richard为Metawidget所做的工作特别感兴趣:

此外,我还提出了一个问题,将动态(服务器端)组件创建添加到JSF规范中。如果您认为这对您的用例很重要,请在以下网站进行投票: