I’m designing a form maker in which the users can add multiple options to their questions. So there’s an add new option button and a remove button to every option.
I want to use a dataTable in my Facelets page and bind it with an HtmlDataTable in my managed bean in order to add/delete options dynamically because we don’t know how many options they’d like to add.
So what I did is that the value of my dataTable is a List of Strings. My input texts (options) are added and deleted and when they add the whole question they are stored correctly in my DB. But every time the add or delete button is pressed my options are all empty so the user has to enter them again.
My code is a bit lengthy so I’ll provide you with a simplified version of them.
On my Facelets page I have:
<h:dataTable value="#{questionMaker.selectOneOptionList}" var="option" binding="#{questionMaker.table}">
<h:column>
<h:inputText value="#{option}"/>
<h:commandLink value="remove option" action="#{questionMaker.removeRadioButtonOption}"/>
</h:commandLink>
</h:column>
</h:dataTable>
And in my managed bean the above variables are:
private HtmlDataTable table;
private List<String> selectOneOptionList;
they have getters and setters too of course.
and this is my add method:
public void addRadioButtonOption() {
String option = new String();
selectOneOptionList.add(option);
}
There are several (potential) problems in this approach:
In order to get this construct to work, the bean must be view scoped (not request nor session scope). In request scope, the
selectOneOptionListwould be freshly recreated on every single request. You don’t want to have that. In session scope, the bean would be shared among all browser windows/tabs. You also don’t want to have that.The
bindingattribute runs during view build time. So if the#{questionMaker}is view scoped, then it becomes implicitly request scoped due to JSF issue 790.As being an immutable object, the
Stringdoesn’t have a setter method. The<h:inputText value="#{option}"/>will never be able to set the entered value.So, to solve your problem, you have to:
@ViewScoped.bindingattribute point to a view scoped bean property.Stringby a fullworthy javabean, or access the list items by index instead.So, this should do (assuming that you still want to stick to
List<String>for some reason):with
See also: