I am using the following piece of code in my JSF 2.0 with RichFaces 4.0. I have a managed bean that has an enum. Now i want to assign the value of the enum via an ActionParam. How can I do this? Here is the code:
<a4j:commandLink id="pendingTransactions"
action="#{tellerBean.getPendingTransactions}" value="Show Pending"
styleClass="button category-btn">
<a4j:actionparam name="first" value=""
assignTo="" />
</a4j:commandLink>
and my managed bean:
#ManagedBean
#SessionScoped
public class TellerBean implements Serializable{
public enum TransactionType {
PENDING,PROCESSED,ALL
}
private static final long serialVersionUID = -321111;
private String recipientID;
private String recipientName;
private String transactionAmount;
private TransactionType transactionType;
public String getRecipientID() {
return recipientID;
}
public void setRecipientID(String recipientID) {
this.recipientID = recipientID;
}
public String getRecipientName() {
return recipientName;
}
public void setRecipientName(String recipientName) {
this.recipientName = recipientName;
}
public String getTransactionAmount() {
return transactionAmount;
}
public void setTransactionAmount(String transactionAmount) {
this.transactionAmount = transactionAmount;
}
public void searchTransactions() {}
public TransactionType getTransactionType() {
return transactionType;
}
public void setTransactionType(TransactionType transactionType) {
this.transactionType = transactionType;
}
public void getTransactions() {}
}
Now I want to assign the value of the transactionType variable to an Enum value. How can I do this?
I don't know what you want to do with the variable or how you want to display it, so here's a generic example.
First of all, the JSF page must be able to 'iterate' over the enum to discover the possible values. I'm using h:selectOneMenu as an example which is filled using f:selectItems. f:selectItems expects a List<> as input so we need to create a method in the TellerBean:
public List<TransactionType> getTransactionTypes()
{
List<TransactionTypes> tt = new ArrayList<TransactionType>();
for (TransactionType t : TransactionType.values())
{
tt.add(new TransactionType(t, t.toString()))
}
return tt;
}
Then for an example JSF page:
<h:form>
<h:selectOneMenu value="#{tellerBean.transactionType}">
<f:selectItems value="#{tellerBean.transactionTypes}"/>
</h:selectOneMenu>
<h:commandButton value="Submit" action="#{tellerBean.someMethod}"/>
</h:form>
The JSF page should display a drop-down list with the values of the enum. When clicking the button labeled "Submit" it executes someMethod() in TellerBean. Of course this doesn't work because the method doesn't exist, but it's just an example. ;-)
Related
I would like to know if it possible to push a value from inside a <ui:repeat> to a map, a set or a list?
I would like to pass the value of the <h:inputtext> to a set.
Code:
<ui:repeat var="_par" value="#{cmsFilterParameterHandler.normaleSuchParameter()}">
<p:outputLabel value="#{_par.bezeichnung}" />
<p:spacer width="5px" />
<p:inputText id="me" value="#{??? push me to a set ???}"/>
<br /><br />
</ui:repeat>
With a Set, it is not possible as it doesn't allow referencing items by index or key. It's however possible with a List and a Map by just specifying the list index and map key in the input value.
With a List:
private List<String> list; // +getter (no setter necessary)
#PostConstruct
public void init() {
list = createAndFillItSomehow();
}
<ui:repeat value="#{bean.list}" varStatus="loop">
<h:inputText value="#{bean.list[loop.index]}" />
</ui:repeat>
With a Map (only if your environment supports EL 2.2 or JBoss EL):
private Map<String, String> map; // +getter (no setter necessary)
#PostConstruct
public void init() {
map = createAndFillItSomehow();
}
<ui:repeat value="#{bean.map.entrySet().toArray()}" var="entry">
<h:inputText value="#{bean.map[entry.key]}" />
</ui:repeat>
Noted should be that the canonical approach is to use a List of fullworthy javabeans. Let's assume a Javabean class named Par with properties id and value which maps exactly to a par table in DB with columns id and value:
private List<Par> pars; // +getter (no setter necessary)
#PostConstruct
public void init() {
pars = createAndFillItSomehow();
}
<ui:repeat value="#{bean.pars}" var="par">
<h:inputText value="#{par.value}" />
</ui:repeat>
Either way, it works as good when using <p:inputText>, it's in no way related to PrimeFaces, it's in the context of this question merely a jQuery based JSF UI component library. Just replace h: by p: to turn it on.
I'm not sure, if I understood your requirements correctly.
I suppose the following: You need a List of Strings in some backend and an ui:repeat tag to iterate over those strings with input-fields to edit them. Maybe there are some syntax-issues, but my idea should be clear:
public class Backend {
private List<String> myStrings;
public MyStringWrapper getMyStringWrapper(int index) {
return new MyStringWrapper(index);
}
public class MyStringWrapper {
private final int index;
public MyStringWrapper(int index) { this.index = index; }
public String getContent() { return myStrings.get(index); }
public void setContent(String newContent) { myStrings.add(index, newContent); }
}
}
In the frontend you use as follows:
<ui:repeat var="_index" value="#{backend.getIndexSequence()}">
<p:inputText value="#{backend.getMyStringWrapper(_index).content}"/>
</ui:repeat>
Of course, you have to provide a getIndexSequence-method which produces a list of ints ranging from 0 to the size of the strings.
Do you mean like this?
<p:inputText id="me" value="#{_par.input}"/>
in BackBean:
public class Par implements Serializable {
private String inputText;
private String bezeichnung;
public Par()
{
}
public void setInput(String input)
{
this.inputText = input;
}
public String getInput()
{
return this.inputText
}
public void setBezeichnung(String bezeichnung)
{
this.bezeichnung = bezeichnung;
}
public String getBezeichnung()
{
return this.bezeichnung
}
}
I am studying a PrimeFaces AutoComplete demo. I shortenied it from the full showcase demo. http://www.primefaces.org/showcase/ui/input/autoComplete.xhtml
AutoCompleteBean.java
#ManagedBean
public class AutoCompleteBean {
private Query query;
private List<Query> queries = new ArrayList<Query>();
#PostConstruct
public void init() {
queries.add(new Query(0, "Afterdark", "afterdark"));
queries.add(new Query(1, "Afternoon", "afternoon"));
queries.add(new Query(2, "Afterwork", "afterwork"));
queries.add(new Query(3, "Aristo", "aristo"));
}
public List<Query> completeQuery(String query) {
List<Query> filteredQueries = new ArrayList<Query>();
for (int i = 0; i < queries.size(); i++) {
Query skin = queries.get(i);
if(skin.getName().toLowerCase().contains(query)) {
filteredQueries.add(skin);
}
}
return filteredQueries;
}
public void onItemSelect(SelectEvent event) {
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Item Selected", event.getObject().toString()));
}
public Query getQuery() {
return query;
}
public void setQuery(Query query) {
this.query = query;
}
}
Query.java
public class Query {
private int id;
private String displayName;
private String name;
public Query() {}
public Query(int id, String displayName, String name) {
this.id = id;
this.displayName = displayName;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getDisplayName() {
return displayName;
}
public void setDisplayName(String displayName) {
this.displayName = displayName;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Override
public String toString() {
return name;
}
}
I omitted a Convert class, which I think is not that relevant.
search.xhtml
<h:form>
<p:growl id="msgs" showDetail="true" />
<h:panelGrid columns="2" cellpadding="5">
<p:autoComplete id="queryPojo" value="#{autoCompleteView.query}"
completeMethod="#{autoCompleteView.completeQuery}" var="query"
itemLabel="#{query.displayName}" itemValue="#{query}"
converter="queryConverter" forceSelection="true" />
<p:commandButton value="search" oncomplete="PF('dlg').show()"/>
</h:panelGrid>
</h:form>
I have three questions for this:
1) completeMethod="#{autoCompleteView.completeQuery}": completeQuery method is called without passing a parameter, but it's defined as completeQuery(String query). How does this work?
2) value="#{autoCompleteView.query}". Query is an object defined in AutoCompleteBean. How can this Query object take user input string as its value? Usually InputText's value is good for taking user's input, which is a String value.
3) Can I still add an attribute "action=..." to the p:autoComplete componenet?
The converter class that you omitted here plays the real game.... Lets see your questions
As you see converter class overrides 2 methods
getAsString and getAsObject
1)the value
completeMethod="#{autoCompleteView.completeQuery}
gets refactred to
autoCompleteView.completeQuery(autoCompleteView.query);
as you can find to string method in Query class.
2).as converter is defined for autocomplete it calls getAsString method to render on screen. when selected getAsObject method is called to convert string value to object(Query).
3)you can use ajax select event
<p:ajax event="select" listener="#{autoCompleteView.someMethod}">
or call a remoteCommand by onSelect attribute in p:autoComplete
<p:autoComplete id="queryPojo" value="#{autoCompleteView.query}" onSelect="someRemoteCommand();"
completeMethod="#{autoCompleteView.completeQuery}" var="query"
itemLabel="#{query.displayName}" itemValue="#{query}"
converter="queryConverter" forceSelection="true" />
<p:remoteCommand name="someRemoteCommand" update="queryPojo" actionListener="#{autoCompleteView.execute}" />
I'm trying to create a custom component for displaying an Entity with a certain form. So I've created my #FacesComponent and he's working but only when he is not inside a loop like <ui:repeat>. When I'm using the following code, my component is displaying null values for price and photo but not for name. Do you have an explaination ?
XHTML code :
<ui:define name="content">
<f:view>
<h:form>
<ui:repeat value="#{dataManagedBean.listNewestCocktails}" var="item" varStatus="status">
<h:outputText value="#{item.price}"/> <!--working very well-->
<t:cocktailVignette idPrefix="newCocktails" name="foo" price="#{item.price}" urlPhoto="#{item.photoURI}"/> <!-- not working the getPrice here -->
</ui:repeat>
<!--<t:cocktailVignette idPrefix="allCocktails" name="OSEF" price="20" urlPhoto="osefdelurl" ></t:cocktailVignette> -->
</h:form>
</f:view>
My component code :
package component;
import java.io.IOException;
import javax.faces.context.FacesContext;
import javax.faces.component.FacesComponent;
import javax.faces.component.UIComponentBase;
import javax.faces.context.ResponseWriter;
#FacesComponent(value = "CocktailVignette")
public class CocktailVignette extends UIComponentBase {
private String idPrefix;
private String name;
private String price;
private String urlPhoto;
public String getIdPrefix() {
return idPrefix;
}
public void setIdPrefix(String idPrefix) {
this.idPrefix = idPrefix;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
public String getUrlPhoto() {
return urlPhoto;
}
public void setUrlPhoto(String urlPhoto) {
this.urlPhoto = urlPhoto;
}
#Override
public String getFamily() {
return "CocktailVignette";
}
#Override
public void encodeBegin(FacesContext context) throws IOException {
ResponseWriter writer = context.getResponseWriter();
writer.write("<div id=\""+idPrefix+name+"\" class=\"cocktail-vignette\">");
writer.write("<h2>"+name+"</h2>");
writer.write("<h3>"+price+"</h3>");
writer.write("</div>");
}
}
Thanks a lot :) I'm trying but nothing is working ...
All of component's attributes which are sensitive to changes in state (e.g. the value being dependent on <ui:repeat var>, at least those which is not known during view build time but during view render time only), must delegate the storage of attribute value to the state helper as available by inherited getStateHelper() method.
Kickoff example:
public String getPrice() {
return (String) getStateHelper().eval("price");
}
public void setPrice(String price) {
getStateHelper().put("price", price);
}
Apply the same for all other attributes and get rid of the instance variable declarations. Important note is that the state helper key ("price" in above example) must be exactly the same as attribute name.
See also:
How to save state when extending UIComponentBase
I would like to know if it possible to push a value from inside a <ui:repeat> to a map, a set or a list?
I would like to pass the value of the <h:inputtext> to a set.
Code:
<ui:repeat var="_par" value="#{cmsFilterParameterHandler.normaleSuchParameter()}">
<p:outputLabel value="#{_par.bezeichnung}" />
<p:spacer width="5px" />
<p:inputText id="me" value="#{??? push me to a set ???}"/>
<br /><br />
</ui:repeat>
With a Set, it is not possible as it doesn't allow referencing items by index or key. It's however possible with a List and a Map by just specifying the list index and map key in the input value.
With a List:
private List<String> list; // +getter (no setter necessary)
#PostConstruct
public void init() {
list = createAndFillItSomehow();
}
<ui:repeat value="#{bean.list}" varStatus="loop">
<h:inputText value="#{bean.list[loop.index]}" />
</ui:repeat>
With a Map (only if your environment supports EL 2.2 or JBoss EL):
private Map<String, String> map; // +getter (no setter necessary)
#PostConstruct
public void init() {
map = createAndFillItSomehow();
}
<ui:repeat value="#{bean.map.entrySet().toArray()}" var="entry">
<h:inputText value="#{bean.map[entry.key]}" />
</ui:repeat>
Noted should be that the canonical approach is to use a List of fullworthy javabeans. Let's assume a Javabean class named Par with properties id and value which maps exactly to a par table in DB with columns id and value:
private List<Par> pars; // +getter (no setter necessary)
#PostConstruct
public void init() {
pars = createAndFillItSomehow();
}
<ui:repeat value="#{bean.pars}" var="par">
<h:inputText value="#{par.value}" />
</ui:repeat>
Either way, it works as good when using <p:inputText>, it's in no way related to PrimeFaces, it's in the context of this question merely a jQuery based JSF UI component library. Just replace h: by p: to turn it on.
I'm not sure, if I understood your requirements correctly.
I suppose the following: You need a List of Strings in some backend and an ui:repeat tag to iterate over those strings with input-fields to edit them. Maybe there are some syntax-issues, but my idea should be clear:
public class Backend {
private List<String> myStrings;
public MyStringWrapper getMyStringWrapper(int index) {
return new MyStringWrapper(index);
}
public class MyStringWrapper {
private final int index;
public MyStringWrapper(int index) { this.index = index; }
public String getContent() { return myStrings.get(index); }
public void setContent(String newContent) { myStrings.add(index, newContent); }
}
}
In the frontend you use as follows:
<ui:repeat var="_index" value="#{backend.getIndexSequence()}">
<p:inputText value="#{backend.getMyStringWrapper(_index).content}"/>
</ui:repeat>
Of course, you have to provide a getIndexSequence-method which produces a list of ints ranging from 0 to the size of the strings.
Do you mean like this?
<p:inputText id="me" value="#{_par.input}"/>
in BackBean:
public class Par implements Serializable {
private String inputText;
private String bezeichnung;
public Par()
{
}
public void setInput(String input)
{
this.inputText = input;
}
public String getInput()
{
return this.inputText
}
public void setBezeichnung(String bezeichnung)
{
this.bezeichnung = bezeichnung;
}
public String getBezeichnung()
{
return this.bezeichnung
}
}
I need to set 2 different ManagedProperty on the same bean. So i tried :
#ManagedBean(name="selector")
#RequestScoped
public class Selector {
#ManagedProperty(value="#{param.page}")
#ManagedProperty(value="#{param.profile_page}")
private String page;
private String profile_page;
public String getProfile_page() {
if(profile_page==null || profile_page.trim().isEmpty()) {
this.profile_page="main";
}
return profile_page;
}
public void setProfile_page(String profile_page) { this.profile_page = profile_page; }
public String getPage() {
if(page==null || page.trim().isEmpty()) {
this.page="homepage";
}
return page;
}
public void setPage(String page) { this.page=page; }
}
but unfortunatly i can't write 2 different #ManagedProperty : it says duplicate annotations. How can I fix it?
Another : when i return this value, its a String, and i need to confrontate. This syntax :
<h:panelGroup rendered="#{selector.profile_page.compareTo("main")}">
<ui:include src="/profile/profile_main.xhtml" />
</h:panelGroup>
will work?
Cheers
The annotations have to be declared directly before the class, method or field of interest.
So:
#ManagedProperty(value="#{param.page}")
private String page;
#ManagedProperty(value="#{param.profile_page}")
private String profile_page;