How to dynamically add JSF components
Asked Answered
L

3

33

Can I add JSF components dynamically? I need to have a form with a button which should add one <h:inputText> to the form. Is this possible?

I know this should be possible in JavaScript somehow. Do anybody know how to do this in JSF? I think the major problem is how do I get or set values of new inputs via #{value}.

Lefebvre answered 4/8, 2010 at 19:22 Comment(0)
E
36

Use an iterating component like <h:dataTable> or <ui:repeat> to display a dynamically sized List of entities. Make the bean @ViewScoped to ensure that the list is remembered across postbacks on the same view instead of recreated over and over.

Kickoff example with <h:dataTable> (when using <ui:repeat> simply replace <h:dataTable> by <ui:repeat>, and <h:column> by e.g. <li> or <div>):

<h:form>
    <h:dataTable value="#{bean.items}" var="item">
        <h:column><h:inputText value="#{item.value}" /></h:column>
        <h:column><h:commandButton value="remove" action="#{bean.remove(item)}" /></h:column>
    </h:dataTable>
    <h:commandButton value="add" action="#{bean.add}" />
    <h:commandButton value="save" action="#{bean.save}" />
</h:form>

Managed bean:

@Named
@ViewScoped
public class Bean {

    private List<Item> items;

    @PostConstruct
    public void init() {
        items = new ArrayList<>();
    }

    public void add() {
        items.add(new Item());
    }

    public void remove(Item item) {
        items.remove(item);
    }

    public void save() {
        System.out.println("items: " + items);
    }

    public List<Item> getItems() {
        return items;
    }

}

Model:

public class Item {

    private String value;

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

    public String toString() {
        return String.format("Item[value=%s]", value);
    }

}

See also:

Exculpate answered 4/8, 2010 at 20:22 Comment(10)
thanks, was thinking the same thing, only wondering if it was the best way to do it = DLefebvre
True. The only alternative would be creating components programmatically like new HtmlInputText() and so on, but that would only result in nasty and opaque code in managed bean.Exculpate
Hi, @BalusC, is it appropriate to add a field "name" to Item class? I need to save the items into DB and i must read them from DB too.Ticktack
I did just this approach. But when I enter a new value on the added input and hit submit, the list on the backing bean is not updated. What can be wrong? My items are a List<String>, could be it? It can't change the string on the List?Tussah
@JSeven: The String class is indeed immutable. Every Java developer should know this.Exculpate
I know that. I followed this answer stackoverflow.com/questions/3690317/… and since I don't know precisely the inner workings of JSF, I thought it could maybe replace the String on the list with the new one instead of changing it.Tussah
@JSeven: Awkward. I posted a comment over there to protect the future innocent.Exculpate
This is so much better than what Ive been doing thanksPolytrophic
Hi, @BalusC, if there are other inputs (beside the dynamic one) in the form with a set of validations or are marked as required then how to achieve the same thing? In my case, the action won't execute at all if there are validation errors.Pavilion
@Exculpate Thank you very much man! I am new in jsf and you saved my day! Actually i am using oracle adf and jdeveloper. Is there any way i can set the bean state through interface in jdeveloper.Luehrmann
I
1

It's should be like that

Bind a form tag to the bean property


<form binding="#{myBean.myform}">...</form>

@ManagedBean("myBean")
public class Bean{
   property HtmlForm myform;
}

on event, create a new instance of the input component

HtmlInputText input=new HtmlInputText();

and attach to the your form

myform.getChildren().add(input);
Illusage answered 29/3, 2012 at 11:24 Comment(1)
Please never create new component instances yourself. The prefered way is this: FacesContext.getCurrentInstance().getApplication().createComponent(HtmlInputText.COMPONENT_TYPE);Mythopoeia
R
0

Use h:dataTable to add elements dynamically... Have a list of any type you want to provide values for dataTable...

In h:dataTable... you can include the element tag to create inside <h:column>

It will be used to generate elements you want to create dynamically.

Raposa answered 24/1, 2013 at 5:45 Comment(1)
Welcome at Stack Overflow! This answer doesn't seem to add anything substantial on top of the already given answers so far. Stack Overflow is not a discussion forum where everyone repeats each other on agreement, but it is a question&answer site where everyone gives an upvote on agreement or a downvote on disagreement. If you earn 15 reputation, then you can cast upvotes.Exculpate

© 2022 - 2024 — McMap. All rights reserved.