开发者

How do I create form controls dynamically with DHTML and deal all those with JSF?

开发者 https://www.devze.com 2023-03-10 05:16 出处:网络
Suppose this next situation: making a view where the form controls are rendered with DHTML (that is, each time the user press a button, a new row with fields is created and field identifiers are both

Suppose this next situation: making a view where the form controls are rendered with DHTML (that is, each time the user press a button, a new row with fields is created and field identifiers are both generated and asigned to the fields with the same DHTML as 'form1control1' and so on), but where that controls are not related yet to any UIComponent in the ViewRoot (as they are created dynamically by the client and so the server don't know they are in the form) How can I deal with a) finding that controls and b) using that names for validation and processing within JSF?

With a JSP approach, that controls names & values are coming with the HttpRequest and is easy to deal with those items by calling the request object and using an algorythm that search all the objects with a pattern, so where an object named 'form1control1' is there, I will find it by using i.e. request.getParameterNames() and request.getParameter("form"+N+"control"+M), for later dealing with making validations and convertions by using code for all the named parameters.

As I understand, with JSF I need to associate one control with one UIComponent by declaring the control within the JSP with one tag and therefore, to attach any either or both validator or converter to this control, so the RootView knows the control is there and has an associated name, and it will expect to manage that control, but I need not a JSP-declared control, but one created by the client dynamically with JavaScript, later sent to the server and treated as any other JSP-declared UIComponent, so I can relaunch my question as: How do I deal with controls not declared within any JSP and built dynamically by the client with DHTML, for validation, conversion and processing?

I suppose I can do it with AJAX by calling the ViewRoot any time I do a new row with new controls and updating it with adding any control programatically to the tree, but, I think that approach is very expensive as I need a) generate an AJAX request, b) to give work to the server anytime I do a开发者_如何学运维n action withing the form that implies using processing time and assigning memory resources; so, prefered, I would desire to avoid using AJAX for updating the ViewRoot with any new control created/deleted, Obviously I'm not closed if it is mandatory to use AJAX for updating the ViewRoot to reach that behavior. If I can avoid this last approach, it is too welcome.

Thanks so much for your feedback in advance.


This is possible, but you need to have a relatively good understanding of the JSF API as its not exactly trivial. The way to do it is to have a Java based custom component in the component tree that serves as a container for the dynamic HTML you will be creating on the client.

Via either UIComponent#decode or Renderer#decode (if you use a separate renderer) your Java custom component can inspect the request after a postback and populate itself with the raw values that the dynamically created components post to the server.

A good way to get an idea how this works is just to inspect existing renderers. E.g. a simplified example from the 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);

}

Inside the decode method you're handling all your 'virtual components' and JSF then sees everything as one component.

It's also more or less possible to dynamically create a server side representation of the components that have been dynamically created on the client. I say more or less since Mojarra (the JSF reference implementation) currently has some bugs that prevent this working well in all situations. See e.g. http://java.net/jira/browse/JAVASERVERFACES-1826 MyFaces seems to work correctly though.

You might be specifically interested in the work done by Richard for Metawidget: http://metawidget.org/

Furthermore, I've opened an issue to have this dynamic (server side) component creation added to the JSF spec. If you think this is important for your use case, please give it a vote at: http://java.net/jira/browse/JAVASERVERFACES_SPEC_PUBLIC-1007


I am not aware of any way to create components on the client that would then be automatically bound to viewstate when submitted back to the server. I think you would need ajax to accomplish that.

You can of course create input elements dynamically and still obtain the values entered by an end user directly from HttpServletRequest, but for JSF the whole paradigm revolves around maintaining viewstate.

0

精彩评论

暂无评论...
验证码 换一张
取 消