Added String to ArrayList not shown / not updated [duplicate] - jsf

This question already has answers here:
How to send form input values and invoke a method in JSF bean
(1 answer)
Pass an input value directly as action method argument
(1 answer)
Using <ui:repeat><h:inputText> on a List<String> doesn't update model values
(1 answer)
Closed 5 years ago.
...So i've got my #ApplicationScoped Bean "Application"..:
#ManagedBean(name = "Application")
#ApplicationScoped
public class Application implements Serializable {
private boolean isRunning = false;
private ArrayList<Feed> sentNotifications = new ArrayList<>();
private ArrayList<String> emails = new ArrayList<>(
Arrays.asList("f00#b4r.com", "test#test.com")
);
private LinkedList<String> words = new LinkedList<>(
Arrays.asList("vuln","banana","pizza","bonanza")
);
private LinkedList<String> feeds = new LinkedList<>(
Arrays.asList("http://www.kb.cert.org/vulfeed",
"https://ics-cert.us-cert.gov/advisories/advisories.xml",
"https://ics-cert.us-cert.gov/alerts/alerts.xml")
);
...and want to add a String to ArrayList<String> emails using the method:
public String addEmail(String email) {
emails.add(email);
return null;
}
The Facelet goes as follows:
<!-- EMAILS -->
<h3>Configured Emails</h3>
<h:form>
<h:inputText value="Email" var="email"/>
<h:commandButton value="Add Email" action="#{Application.addEmail(email)}"/>
</h:form>
<h:form>
<ui:repeat var="email" value="#{Application.emails}">
<tr>
<td>#{email}</td>
<td>
<f:facet name="header">Action</f:facet>
<h:commandLink value="Delete" action="#{Application.rmEmail(email)}"/>
</td>
</tr>
<br></br>
</ui:repeat>
</h:form>
...so when i try to add "blabla#bla.com", this is the Result:
There is a delete-button shown, but not the String itself?!
Is the String correctly added - and JSF doesnt rerender the view..?
..Or is the String not added correctly?
please help!
thanks.

I fixed it, finally!
Thanks to User #Kukeltje, who hinted me at basic things that i got wrong - and User #Wietlol who motivated me in the chat through moral support and 'believes in me' :)
The solution:
..in Application.java:
public List<Feed> sentNotifications = new ArrayList<>();
public List<String> emails = new ArrayList<>();
public List<String> words = new LinkedList<>(Arrays.asList("vuln", "banana", "pizza", "bonanza"));
public List<String> feeds = new LinkedList<>(
Arrays.asList("http://www.kb.cert.org/vulfeed",
"https://ics-cert.us-cert.gov/advisories/advisories.xml",
"https://ics-cert.us-cert.gov/alerts/alerts.xml")
);
private String currentEmail;
private String currentFeed;
private String currentWord;
[...]
public void addEmail() {
emails.add(currentEmail);
}
..and gui.xhmtl:
<!-- EMAILS -->
<h3>Configured Emails</h3>
<h:form>
<h:inputText value="#{Application.currentEmail}" var="email"/>
<h:commandButton value="Add Email" action="#{Application.addEmail}"/>
</h:form>
<h:form>
<ui:repeat var="email" value="#{Application.emails}">
<tr>
<td>#{email}</td>
<td>
<f:facet name="header">Action</f:facet>
<h:commandLink value="Delete" action="#{Application.rmEmail(email)}"/>
</td>
</tr>
<br></br>
</ui:repeat>
</h:form>
Notice how action="#{Application.addEmail}" does not make use of arguments- rather the parameter is handed to the method via value="#{Application.currentEmail}".
If you, reader, have the same problem please consider these points:
getter/setter for each Field in the bean
primitive fields!
argument-less methods to 'delegate' the primitive Fields, e.g. my addEmail method
Hope this answer is usefull to ppl having the same issue!
Greetings,
Gewure

Related

Generate h:panelGrid from Java list [duplicate]

I am wondering how to display a List<T> as obtained below in a Facelet:
public List<T> searchByString(String string) {
return getEntityManager().createNamedQuery("Userdetails.findByUsername").setParameter("username", "%" + string + "%").getResultList();
}
Would a <h:dataTable> be a suitable way?
You're going need to iterate over it. JSF 2 offers three iteration components out the box. Provided that the User entity look like below,
#Entity
public class User {
private #Id Long id;
private String username;
private String email;
private LocalDate birthdate;
// Add/generate getters+setters.
}
and that the search results are assigned as a List<User> users property of a bean which is available as #{bean},
#Named #RequestScoped
public class Bean {
private List<User> users;
// Add/generate postconstruct+getter.
}
here are some examples based on it:
<h:dataTable>, an UI component which generates a HTML <table>.
<h:dataTable value="#{bean.users}" var="user">
<h:column>#{user.id}</h:column>
<h:column>#{user.username}</h:column>
<h:column>#{user.email}</h:column>
<h:column>#{user.birthdate}</h:column>
</h:dataTable>
<ui:repeat>, an UI component which generates no HTML markup (so, you'd have to write all that HTML in the desired fashion yourself, which could easily be changed to e.g. <ul><li>, or <dl><dt><dd>, or <div><span>, etc):
<table>
<ui:repeat value="#{bean.users}" var="user">
<tr>
<td>#{user.id}</td>
<td>#{user.username}</td>
<td>#{user.email}</td>
<td>#{user.birthdate}</td>
</td>
</ui:repeat>
</table>
<c:forEach>, a tag handler which runs during view build time instead of view render time (background explanation here: JSTL in JSF2 Facelets... makes sense?), it also doesn't produce any HTML markup:
<table>
<c:forEach items="#{bean.users}" var="user">
<tr>
<td>#{user.id}</td>
<td>#{user.username}</td>
<td>#{user.email}</td>
<td>#{user.birthdate}</td>
</td>
</c:forEach>
</table>
See also:
Java EE 6 tutorial - Adding components to a page - using <h:dataTable>
How and when should I load the model from database for h:dataTable
You can save your List in a class variable, give it a getter and (maybe) a setter. Declare searchByString method as void and call it with let's say a (provided you are using PrimeFaces):
<p:commandLink update="#form" process="#this" action="#{myBean.searchByString}">
myBean:
public void searchByString(String string) {
userList = getEntityManager().createNamedQuery("Userdetails.findByUsername").setParameter("username", "%" + string + "%").getResultList();
}
provided your table sits in a form that you just updated you could display the List in it.
<p:dataTable var="user" value="#{myBean.userList}">
<p:column headerText="Name">
<h:outputText value="#{user.name}" />
</p:column>
</p:dataTable>

Simple setting from form input to object attribute

<h:inputText value="#{myController.myString}" id="stg" />
<h:inputText value="#{myController.document.title}" id="title" />
<h:inputTextarea value="#{myController.document.subtitle}" id="subtitle" />
I can recover myString correctly, but document is always null. It has a default constructor. If I do a Document document = new Document() in myController then it is not null but title and subtitle are. Am I missing something?
EDIT
I thought my problem might not need additional information, but here it is:
.xhtml
<h:form id="ExampleForm" styleClass="myClass">
<h:inputText value="#{myController.myString}" id="stg" />
<h:inputText value="#{myController.document.title}" id="title" />
<h:inputTextarea value="#{myController.document.subtitle}" id="subtitle" />
<h:commandButton action="#{myController.readData()}" type="submit" value="Read"/>
</h:form>
Then I complete all the inputs in the form and click the button...
Controller
#Named(value = "myController")
#ViewScoped
public class MyController implements Serializable {
private String myString;
private Document document;
// getters and setters
public void readData() {
System.out.println("String: " + myString); // prints well
System.out.println("Doc: " + document); // prints null
// System.out.println("Doc title: " + document.getTitle()); // prints null when I declare private Document document = new Document();
}
}
Document is a Serializable simple bean with String title and subtitle and the respective getters/setters.
EDIT
The problem seems to be solved thanks to BalusC pointer.
There have been different things that mixed up and made my code work incorrectly. First, I solve the problem with:
#PostConstruct
public void init() {
document = new Document();
}
#PreDestroy
public void cleanup() {
document = null;
}
Another mistake I had while researching the issue (and that's why some other things created errors) was I didn't specify title and subtitle in the execute:
<h:commandButton action="#{myController.readData()}" type="submit" value="Read">
<f:ajax execute="#this title subtitle" />
</h:commandButton>

Why doesn't panelgroup update after clicking? [duplicate]

This question already has answers here:
How to ajax-refresh dynamic include content by navigation menu? (JSF SPA)
(3 answers)
Closed 6 years ago.
I try to update component panelgroup after clicking on commandLink, but it doesn't succeed. I have already tryed many ways but nothing helps. Please, say me, what should I do that to update panelgroup?
<h:panelGroup layout="block" id="content">
<h:panelGroup layout="block" id="nav">
<h:form id="itemsMenu">
<h:commandLink value="View" update="workplace" actionListener="#{main.determineAction}">
<f:param name="link" value="Viewing telephone book"/>
</h:commandLink>
</h:form>
</h:panelGroup>
<h:panelGroup id="workplace">
<h:panelGroup layout="block" rendered="#{main.responseRendered}">
<ui:include src="#{main.linkPage}"/>
</h:panelGroup>
</h:panelGroup>
</h:panelGroup>
Bean code:
#ManagedBean(name = "main")
#ViewScoped public class MainBean implements Serializable {
private static final long serialVersionUID = 1L;
private List<String> listItemsMenu;
private String linkPage;
private boolean responseRendered = false;
public boolean isResponseRendered() {
return responseRendered;
}
public void setResponseRendered(final boolean responseRendered) {
this.responseRendered = responseRendered;
}
public String getLinkPage() {
return linkPage;
}
public void setLinkPage(final String linkPage) {
this.linkPage = linkPage;
}
public void determineAction(final ActionEvent event) {
final Locale currentLocale = SessionBean.getCurrentLocale();
final MessageManager messageManager = new MessageManager(currentLocale);
final Map<String, String> mapParameters = FacesContext.getCurrentInstance()
.getExternalContext().getRequestParameterMap();
final String linkType = mapParameters.get(Constants.ATTRIBUTE_LINK_TYPE);
if (linkType.equals(messageManager.getProperty(Constants.MESSAGE_MENU_VIEWING))) {
linkPage = Constants.PAGE_VIEW;
}
...
responseRendered = true;
}
}
Ok well command link doesn't have an attribute update, so that should have thrown an error here:
<h:commandLink value="View" update="workplace">
I'm assuming you want an ajax solution it would be:
<h:commandLink value="View">
<f:param name="link" value="Viewing telephone book"/>
<f:ajax render="workplace" listener="#{main.determineAction}" />
</h:commandLink>

Adding values from multiple inputs to the arraylist

I' have a simple problem with adding values from inputs to the ArrayList.
I have a POJO like this:
public class Person {
private String firstName;
private String lastName;
private List<String> friends=new ArrayList<>();
//getters and setters
then Backing bean:
public class backingBean{
Person p=new Person();
public void addPerson(){
for(String friend:p.getFriends)
System.out.println(friend);
}
}
and the view
<h:form>
<fieldset>
<h:panelGrid columns="2">
<h:outputText value="Name" />
<h:inputText value="{backingBean.person.firstName}"/>
<h:outputText value="LastName" />
<h:inputText value="#{backingBean.person.lastName}"/>
<h:outputText value="Friends" />
<h:inputText value="#{backingBean.person.friends}" />
<h:inputText value="#{backingBean.person.friends}" />
</h:panelGrid>
<h:commandButton value="Add"
action="#{backingBean.addPerson}" />
</fieldset>
</h:form>
When I try to addPerson I get this error:
summary=(Conversion Error setting value...
I don't understand why convert String to String?
You can't bind value of h:inputText to ArrayList (without converter). When you submit form (by clicking button) JSF tries to call setFriends(String) and this is where this Exception occurs. Try to figure out what you are trying to achieve with these two h:inputText elements.
if you want to add 2 friends, just create only 2 different variables in backing bean as :
private String friend1;
private String friend2;
and then add them in addPerson like this:
List<String> friends=new ArrayList<String>();
friends.add(friend1);
friends.add(friend2);
p.setFriends(friends);
Not tested can be some bugs.
EDIT:
And if this not satisfies you, you can look at this #BalusC ANSWER

How do I display a list of strings in JSF which also needs to be editable?

I have a backing bean which has a property called List cites where Cite has a string property called "value" .. In the init method I am fetching the values stored as a comma separated string, splitting them into individual strings constructing a list and displaying the list of cites. But I also want to give the users ability to add more cites on top of existing ones/edit existing cite content. How can I do that ? The code below is the jsf in xhtml but it doesn't work for me ..
<div style="margin-top: 10px; padding: 3px 3px;">
<fieldset>
<legend>Cites Affected</legend>
<h:dataTable value="#{dataEntry.cites}" var="citeAffected">
<h:column>
<f:facet name="header" >
<h:outputText value="Cite"/>
</f:facet>
<h:inputText value="#{citeAffected.value}"/>
</h:column>
</h:dataTable>
<h:commandButton value="Add cite" process="#this" action="#{dataEntry.addCite}"/>
</fieldset>
</div>
In the backing bean .. this is what I have
DataEntry
{
private List<CiteAffected> cites = new ArrayList<CiteAffected>();
public void addCite()
{
cites.add(new CiteAffected());
}
public void editMetadata()
{
//update the db object
}
private void init()
{
// get the value from database as a comma separated string
for(String citeAffected : Arrays.asList(sourceManualLoadProperties.getCitesAffected().split(",")))
{
CiteAffected cite = new CiteAffected();
cite.setValue(citeAffected);
this.cites.add(cite);
} }
}
The error I am getting is .. As soon as I click on the command button "add cite" all the existing values disappear when I want it to simply add another text box but display the existing values as well ..
public class CiteAffected
{
private String value;
/**
*
* #return the cite affected
*/
public String getValue()
{
return value;
}
/**
*
* #param value the cite affected
*/
public void setValue(final String value)
{
this.value = value;
}
}
Just remove the process="#this" from <h:commandButton> and have your managed bean in #ViewScoped at least.
JSF code:
<h:form>
<h:dataTable id="dtCites" value="#{dataEntry.cites}" var="citeAffected">
<!-- content... -->
</h:dataTable>
<h:commandButton value="Add cite" action="#{dataEntry.addCite}">
<f:ajax render="dtCites" />
</h:commandButton>
</h:form>
Managed bean:
#ManagedBean
#ViewScoped
public class DataEntry {
//...
}

Resources