Uncategorized

Create the Components programmatically

Create the components programmatically in a postAddToView event listener:

<h:form id="form">
<f:event type="postAddToView" listener="#{bean.populateForm}" />
</h:form>

With:

public void populateForm(ComponentSystemEvent event) {
    HtmlForm form = (HtmlForm) event.getComponent();
    for (Field field : fields) {
        switch (field.getType()) { // It's easiest if it's an enum.
            case TEXT:
                UIInput input = new HtmlInputText();
                input.setId(field.getName()); // Must be unique!
                input.setValueExpression("value", createValueExpression("#{bean.values['" + field.getName() + "']}", String.class));
                form.getChildren().add(input);
                break;
            case SECRET:
                UIInput input = new HtmlInputSecret();
                // etc...
        }
    }
}

(note: do NOT create the HtmlForm yourself! use the JSF-created one, this one is never null)

This guarantees that the tree is populated at exactly the right moment, and keeps getters free of business logic, and avoids potential “duplicate component ID” trouble when #{bean} is in a broader scope than the request scope (so you can safely use e.g. a view scoped bean here), and keeps the bean free of UIComponent properties which in turn avoids potential serialization trouble and memory leaking when the component is held as a property of a serializable bean.

If you’re still on JSF 1.x where <f:event> is not available, instead bind the form component to a request (not session!) scoped bean via binding

<h:form id="form" binding="#{bean.form}" />

And then lazily populate it in the getter of the form:

public HtmlForm getForm() {
    if (form == null) {
        form = new HtmlForm();
        // ... (continue with code as above)
    }
    return form;
}

When using binding, it’s very important to understand that UI components are basically request scoped and should absolutely not be assigned as a property of a bean in a broader scope. See also How does the ‘binding’ attribute work in JSF? When and how should it be used?

Tinggalkan Balasan

Alamat email Anda tidak akan dipublikasikan. Ruas yang wajib ditandai *