0

I have written the following code so that I can have a single textfield followed by a add button and a save button at the bottom.

I want the first textfield and add button to be fixed, but whenever a user cicks on add button, a text field gets added below the present textfield and the add button and save button goes down.

I have the following piece of code, but it doesnt seem to working.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"    
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:c="http://java.sun.com/jstl/core"
      xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>Dashboard | BlueWhale Admin</title>
    <link rel="stylesheet" type="text/css" href="../css/reset.css" media="screen" />
    <link rel="stylesheet" type="text/css" href="../css/text.css" media="screen" />
    <link rel="stylesheet" type="text/css" href="../css/grid.css" media="screen" />
    <link rel="stylesheet" type="text/css" href="../css/layout.css" media="screen" />
    <link rel="stylesheet" type="text/css" href="../css/nav.css" media="screen" />

</h:head>
<body>
<h:form>

        <hr/>
        <h:dataTable id="newsinputs" value="#{newsAlerts.values}" var="item" cellspacing="10">
        <h:column>
             <h:outputLabel value="#{item.label}" /> &nbsp;&nbsp;&nbsp;
        </h:column>
        <h:column>
             <h:inputText value="#{item.news}" size="100" /><br/>
        </h:column>
        </h:dataTable>

        <h:commandButton styleClass="btn btn-blue" action="#{newsAlerts.add()}" value="Add"></h:commandButton>
        <hr/>
        <h:commandButton styleClass="btn btn-blue" action="#{newsAlerts.submit}" value="Save" />

</h:form>
</body>
</html>

The bean class is as follows

package com.kc.aop.bean;

import java.util.ArrayList;
import java.util.List;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;

import com.kc.aop.VO.NewsVO;

@ManagedBean(name = "newsAlerts")
@ViewScoped
public class News
{
        private List<NewsVO> values;

        public News()
        {
            this.values = new ArrayList<NewsVO>();
            NewsVO newsVO = new NewsVO();
            newsVO.setLabel("News "+ this.values.size()+1);
            getValues().add(newsVO);
        }

        public String submit() {

            for(NewsVO newsVO : this.values)
            {
                System.out.println(newsVO.getNews());
                System.out.println(newsVO.getLabel());
            }
            return null;
            // save values in database
        }


        public List<NewsVO> getValues() {
            return values;
        }

        public void setValues(List<NewsVO> values) {
            this.values = values;
        }


        public String add()
        {
            NewsVO newsVO = new NewsVO();
            newsVO.setLabel("News "+ this.values.size()+1);
            this.values.add(newsVO);
            return "success";
        }


}
Jitesh
  • 1,384
  • 10
  • 20
ItachiUchiha
  • 36,135
  • 10
  • 122
  • 176
  • Check out this post http://stackoverflow.com/questions/16623563/creating-dynamic-inputs-in-jsf2/16623713#16623713 – Jitesh May 19 '13 at 10:35

2 Answers2

0

You're returning non-null/void from action method:

public String add() {
    // ...

    return "success";
}

A non-null/void outcome creates a new view scope. You need to return null or void instead to keep the same view.

public String add() {
    // ...

    return null;
}

or

public void add() {
    // ...
}

There's absolutely no need to change it by an action listener as suggested by the other answer. It serves a completely different purpose.

See also:

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
-1

You need to use actionListener or at least modify action to return void or null in your <h:commandButton /> since you stay in the same view. By using action with a return value, the ViewScope is broken and recreated.

View code :

<h:commandButton styleClass="btn btn-blue" actionListener="#{newsAlerts.add}" value="Add" />
<hr/>
<h:commandButton styleClass="btn btn-blue" actionListener="#{newsAlerts.submit}" value="Save" />

Bean code :

public void add(ActionEvent event)
{
    NewsVO newsVO = new NewsVO();
    newsVO.setLabel("News "+ this.values.size()+1);
    this.values.add(newsVO);
}

public void submit(ActionEvent event)
{
    for(NewsVO newsVO : this.values)
    {
        System.out.println(newsVO.getNews());
        System.out.println(newsVO.getLabel());
    }
}

More info :

Action vs ActionListener

Community
  • 1
  • 1
Alexandre Lavoie
  • 8,711
  • 3
  • 31
  • 72
  • hey alex thanks for the answer, but how do I keep 1 textfield before adding others coz I am getting the "values" value as "null" inside add(), where I have initialized it inside my constructor. – ItachiUchiha May 19 '13 at 11:46
  • Is your view getting at least one input shown when you just load the page? Have you changed to actionListener? – Alexandre Lavoie May 19 '13 at 18:40
  • yes I have changed to actionListener, and the add button is working perfectly, but what i still dont get is how to keep a textField while loading the page and add other textField on click of ADD button. There is one more issue, currently the Add button comes below the textfield. I want to show the button beside the textfield. – ItachiUchiha May 20 '13 at 10:47
  • Your first textfield is supposed to be created at the view creation (`News()` get called). When you are clicking on Add, the web page should be reloaded with 2 textfields, etc. If it is not working, there is something wrong elsewhere. Of course if you go to another page and come back, the list will be reset to one textfield. – Alexandre Lavoie May 20 '13 at 19:29