1

I have a screen with inputText, beside it there's a (+) button, when the user should press that button the form should add another extra inputText beside it (or below, whatever)

Here's the code:

<table>
  <tr>
    <td>
      <p:inputText value="#{controller.x}" />
      <img src="../images/ico_plus.png" />
    </td>
  </tr>
</table>

in Controller.java:

private String x;

public String getX(){return x}
public void setX(String val){x = val}

I need the page to be populated with multiple fields and the controller to have all the fields values' fetched

1 Answers1

3

This question was answered more than one time, basically you need to keep a List for all fields in the bean, and you remove or add to this List with your buttons. Note this is important to be in ViewScoped or SessionScoped ortherwise your List will be reset at every actions.

View :

<h:form>
    <h:dataTable id="tblFields" value="#{bean.fields}" var="field">
        <h:column>
            <h:inputText value="#{field.value}" />
        </h:column>

        <h:column>
            <h:commandButton value="Remove">
                <f:ajax listener="#{bean.onButtonRemoveFieldClick(field)}" immediate="true" render="@form" /> 
            </h:commandButton>
        </h:column>
    </h:dataTable>

    <h:commandButton value="Add">
        <f:ajax listener="#{bean.onButtonAddFieldClick}" execute="@form" render="tblFields" /> 
    </h:commandButton>
</h:form>

Helper class :

public class Field implements Serializable
{
    private String m_sName;

    public void setName(String p_sName)
    {
        m_sName = p_sName;
    }

    public String getName()
    {
        return m_sName;
    }
}

Bean :

@ManagedBean
@ViewScoped
public class Bean implements Serializable
{
    private List<Field> m_lFields;

    public Bean()
    {
        m_lFields = new ArrayList();

        m_lFields.add(new Field());
    }

    public void setFields(List<Field> p_lFields)
    {
        m_lFields = p_lFields;
    }

    public List<Field> getFields()
    {
        return m_lFields;
    }

    public void onButtonRemoveFieldClick(final Field p_oField)
    {
        m_lFields.remove(p_oField);
    }

    public void onButtonAddFieldClick(AjaxBehaviorEvent p_oEvent)
    {
        m_lFields.add(new Field());
    }
}
Alexandre Lavoie
  • 8,711
  • 3
  • 31
  • 72
  • 1+ Since he had primefaces in his example this is relevant http://www.primefaces.org/showcase/ui/collector.jsf – Karl Kildén May 26 '13 at 18:49
  • @KarlKildén the PrimeFaces example show dynamic add content to a table, not dynamic add fields to a table... – Alexandre Lavoie May 26 '13 at 19:00
  • 1
    Are you saying you can only use components as displayed in their respective examples? Or that the component displayed in this specific showcase cannot solve his functional requirement? – Karl Kildén May 26 '13 at 19:07
  • @KarlKildén no, `h:inputText` can be replaced by `p:inputText`, buttons can also be changed for `p:commandButton` with or without `p:ajax`, etc... but the PrimeFaces example does not the same function has the OP is asking. – Alexandre Lavoie May 26 '13 at 19:12
  • Again, are you talking about the example or the component? No idea why you focus talk about no relevant components. is a component constructed for working with lists. I fail to see why it would not work you are welcome to explain. Note that I did not answer his question, I wrote a comment. – Karl Kildén May 26 '13 at 19:17
  • @KarlKildén example only! :) – Alexandre Lavoie May 26 '13 at 19:20
  • Please read up on the difference between answers and comments then – Karl Kildén May 26 '13 at 19:21
  • @KarlKildén You can write an answer with `p:collector` if you find it interresting then, I'm not a fan of PrimeFaces that's the only reason I provided a fully JSF plain answer... but that doesn't say that it could not be better to do it so. – Alexandre Lavoie May 26 '13 at 19:34
  • It's not suitable as an answer I much prefer my comment but thanks for the suggestion. The showcase example is very easy to understand and adapt and is directly relevant to working with collections. My conclusion is there's a good chance someone reading this question will find that comment useful but it's not an answer, it's an comment (did you look up the difference?). The gist is I have no obligation to answer his question, I must only be relevant. – Karl Kildén May 26 '13 at 20:40
  • In your solution, you can add any number of entries by clicking the add commandbutton, but what if the user added some values to the field, and then pressed the add, this way the page forces the dataGrid to render and then all the fields will be cleared, as the list in the backend has no values, I also need the list to be filled bidirectional in every add command, if possible – Mohamed Wagdy Khorshid May 29 '13 at 11:56
  • @Smartdog Thank you for the comment, I've fixed issues in the example, but don't understand the _bidirectional filled list_... Maybe you can post a question on that! – Alexandre Lavoie May 29 '13 at 12:37
  • it still does not bind even after the execute attribute, please tell if any extra changes are done here – Mohamed Wagdy Khorshid May 29 '13 at 13:33
  • @Smartdog Note that I've changed `String` for a custom POJO (`Field`) without that it is not working. Of course this POJO is custom to your needs – Alexandre Lavoie May 29 '13 at 13:43
  • I tried it too and did not work, are you sure this is working ?? I'm even executing this code: for (UIComponent child : dataTable.getChildren().get(0).getChildren()) { if (child instanceof InputText) { InputText field = (InputText) child; String value = field.getValue(); previousNames.add(new Field(value)); } } and the value is always null – Mohamed Wagdy Khorshid May 29 '13 at 13:58
  • Forgot to change `` to ``, but yes it is working I tested it in NetBeans. – Alexandre Lavoie May 29 '13 at 14:02
  • I tried your example and it works, I'll trace my errors and tell if anything missing – Mohamed Wagdy Khorshid May 29 '13 at 14:08
  • I can't explain how greatful I am, thank you very very much, you made my day :) one last thing, you may execute only the datatable to avoid the rest of form submit and validation, and it's better to set immediate="true" – Mohamed Wagdy Khorshid May 29 '13 at 15:09