My page display list Category Name. i want to when user clicks category name , it will
display list product by category name. in this code, i want to passing CateogryId as value of h:inputHidden. it's same as <h:inputText value="#{produtBean.categoryId}"></h:inputText> .
Tkanks you for reading !
Code from xhtml
<ui:repeat value="#{productBean.listCategory}" var="c">
<h:form>
<h:inputHidden value="#{productBean.categoryId}" ></h:inputHidden>
<h:commandLink value="#{c.name}" action="#{productBean.listProductByCt}" ></h:commandLink>
</h:form>
</ui:repeat>
Code from ProductBean
public String listProductByCt()
{
if(categoryId==0)
{
return "index";
}
listProduct = new ProductsDB().listProducts(categoryId);
return "product";
}
The <h:inputHidden> doesn't work that way. The value you attempted to "pass" into it is also kind of weird. It's the same value for every item of the list. You should be using <f:param> instead. You probably also want to pass the #{c.id} or #{c.name} instead.
<h:commandLink value="#{c.name}" action="#{productBean.listProductByCt}">
<f:param name="categoryId" value="#{c.id}" />
</h:commandLink>
With
#ManagedProperty("#{param.categoryId}")
private Integer categoryId; // +setter
Alternatively, if you're already on Servlet 3.0 / EL 2.2, then you can just pass it as method argument.
<h:commandLink value="#{c.name}" action="#{productBean.listProductByCt(c.id)}">
with
public String listProductByCt(Integer categoryId) {
// ...
}
See also:
How can I pass selected row to commandLink inside dataTable?
Related
I am beginner in java server faces (JSF), I need to pass the content of text input to second page to display it, the same applies for the second page: I want to pass radio buttons values to a third page. I searched and tried a lot without success.
For example I tried
<h:commandButton value="Next" action="#{myBean.execute(input_id.value)}"/>
Execute method is:
public void execute(String value) {
// ...
try{
FacesContext.getCurrentInstance().getExternalContext().dispatch("/Quizy.xhtml?faces-redirect=true");
}
catch(Exception e){
System.out.println("err");
}
}
Any suggestions?
Here are 4 other ways to pass a parameter value from JSF page to other page JSF :
1- Method expression (JSF 2.0)
2- f:param
3- f:attribute
4- f:setPropertyActionListener
1. Method expression
Since JSF 2.0, you are allow to pass parameter value in the method expression like this #{bean.method(param)}.
JSF page
<h:commandButton action="#{user.editAction(delete)}" />
ManagedBean
#ManagedBean(name="user")
#SessionScoped
public class UserBean{
public String editAction(String id) {
//id = "delete"
}
}
2- f:param
Pass parameter value via f:param tag and get it back via request parameter in backing bean.
JSF page
<h:commandButton action="#{user.editAction}">
<f:param name="action" value="delete" />
</h:commandButton>
ManagedBean
#ManagedBean(name="user")
#SessionScoped
public class UserBean{
public String editAction() {
Map<String,String> params =
FacesContext.getExternalContext().getRequestParameterMap();
String action = params.get("action");
//...
}
}
3. f:atribute
Pass parameter value via f:atribute tag and get it back via action listener in backing bean.
JSF page
<h:commandButton action="#{user.editAction}" actionListener="#{user.attrListener}">
<f:attribute name="action" value="delete" />
</h:commandButton>
ManagedBean
#ManagedBean(name="user")
#SessionScoped
public class UserBean{
String action;
//action listener event
public void attrListener(ActionEvent event){
action = (String)event.getComponent().getAttributes().get("action");
}
public String editAction() {
//...
}
}
4. f:setPropertyActionListener
Pass parameter value via f:setPropertyActionListener tag, it will set the value directly into your backing bean property.
JSF page
<h:commandButton action="#{user.editAction}" >
<f:setPropertyActionListener target="#{user.action}" value="delete" />
</h:commandButton>
ManagedBean
#ManagedBean(name="user")
#SessionScoped
public class UserBean{
public String action;
public void setAction(String action) {
this.action = action;
}
public String editAction() {
//now action property contains "delete"
}
}
There are several ways for doing this, but here is one of them.
You will need to save the inputText value into a property of your bean and both your h:inputText and your h:commanButton should be in the same h:form element
Here is a sample code
In your view
<h:form>
...
<h:inputText value={myBean.someValue} />
....
<h:commandButton value="Next" action="#{myBean.execute()}"/>
</h:form>
Your managed bean should be at least session scoped if you want your property (someValue) to be available in different pages. The content of the managed bean should look like this also:
private String someValue;
// Getter and setter for `someValue`
public String execute() {
// ...
return "/Quizy.xhtml?faces-redirect=true";
}
In the second page if you want to retrieve that value, just use #{myBean.someValue}
to have this done, you just need to set the Value of Your component here inputText or radioButton to a Property of your Managed bean or Cdi bean called on the page of course you won't forget to have getter and setter method for ur property in ur bean. Finally be sure that the scope of Ur bean allow it to be alive (with all its properties' value) across the session. Then, from ur end page you may call ur Managed bean or Cdi bean proprety as value of page components
I have a primefaces datatable and i have a column with filter.i would like to apply filter on the column from the backing bean.
I followed this example and i am able to get the input given filter text box into my bean.
but when i use setFilter ,the values are being set in the HashMap but filter is not being applied on the datatable.
Example column
<p:column filterBy="#{var.value}" headerText="Example" footerText="contains" filterMatchMode="contains" />
Bean is session scoped and the following code is in a function which gets called on a button click.
Map<String,String> theFilterValues = new HashMap<String,String>();
theFilterValues.put("filterColumn","someValue");
myDataTable.setFilters(theFilterValues);
this sets the values ,but there is no change on datatable.
i tried this but it did not help.
All i need is to set a filter on the datatable column upon a button click.
Thanks in advance
The values in the inputs of the DataTable filter are sent in the FacesContext request parameter map, and obtained by the DataTableRenderer when it is rendering the DataTable (see the encodeFilter method for PF 3.5, PF 4.0, or PF 6.1)
So, if your button is in the same form of the DataTable, the values of the filter are sent in the request parameter map, and the renderer will show those values over whatever else you want.
You'll need the button to be in a separate form:
<h:form>
<p:commandButton action="#{someBean.action()}" update="#([id$=dataTable])" />
</h:form>
<h:form>
<p:dataTable id="dataTable" [...] >
<p:column filterBy="#{var.col}" filterValue="#{someBean.filterValue}">
<h:outputText value="#{var.col}">
</p:column>
</p:dataTable>
</h:form>
And then, you can change the filterValue in the bean:
#Named
#SessionScoped
public SomeBean implements Serializable {
private String filterValue;
[...]
public void action() {
filterValue = "new value";
}
[getters/setters]
}
You can use a Map for the filterValues if you are using many filters.
As an alternative, if you need to redirect the user to a new page, you can put the values in the URL, instead of using filterValue. Example:
https://example.com/app/pageOfTheTable.xhtml?form:dataTable:colum:filter=new%20value
The part form:dataTable:colum:filter is the ID of the filter input. You can get that by inspecting the element using your browser. The principle is the same: you are using the request parameter map.
It may be useful to update the value of the backing bean when the user types something. I've found a patch here.
It basically changes populateFilterParameterMap method, in FilterFeature class, so it sets the value of the filterValue. You can put the added lines at the end of the for loop.
for ( ... ){
[...]
+ ValueExpression filterValueVE = column.getValueExpression("filterValue");
+ if (filterValueVE == null) {
+ ((UIComponent)column).getAttributes().put("filterValue", filterValue);
+ } else {
+ filterValueVE.setValue(context.getELContext(), filterValue);
+ }
}
I want to process this form (valueChangueListener is not valid in real case).
This is the back bean:
public class TestBean extends PrivateBaseBean implements Serializable {
private List<String> strings;
#PostConstruct
public void init() {
strings = new ArrayList<String>();
strings.add("");
strings.add("");
strings.add("");
}
public void saveAction(ActionEvent event) {
StringBuilder textToShowInMessage = new StringBuilder();
for (String string : strings) {
textToShowInMessage.append(string);
textToShowInMessage.append("; ");
}
FacesMessage msg = new FacesMessage(super.getBundle().getString(
textToShowInMessage.toString()), "");
FacesContext.getCurrentInstance().addMessage(null, msg);
}
getters... setters...
An the view:
....
<h:form>
<ui:repeat var="string" value="#{testBean.strings}">
<h:inputText value="#{string}" />
<br />
</ui:repeat>
<p:commandButton value="#{msg.save}"
actionListener="#{testBean.saveAction}" icon="ui-icon-disk"
update="#form" />
</h:form>
...
When the form is processed in the back bean string list always is blank.
How to process form intput's inside iteration, without any value changue listener?
There are some screenshots:
The same problem occurs with action or actionListener on
Your problem is not connected with PrimeFaces <p:commandButton>'s behaviour, but rather with a scoping problem that is implicilty created when using the <ui:repeat> tag.
First of all, let's depart from your example. Basically, you've got
<ui:repeat value="#{bean.strings}" var="s">
<h:inputText value="#{s}"/>
</ui:repeat>
with the backing List<String> strings.
The culprit is here: value="#{s}". The exported by <ui:repeat> variable s is visible only within its loop and it is not bound to any managed bean's property, but instead only to a local variable. Put it differently, s is not bound/equal to bean.strings[index] as one would expect and has no knowledge, as we see, where it originated from. So basically, you're off with a unilateral relationship: value from the bean is printed in your input properly, but the reverse is not happening.
The workarounds
Workaround #1: wrapper classes / model objects
The situation can be overcome by using a wrapper object for your class. In case of a string it could be a 'simple mutable string', like below:
public class MString {
private String string;//getter+setter+constructor
}
In this case the iteration will be working as predicted:
<ui:repeat value="#{bean.mstrings}" var="ms">
<h:inputText value="#{ms.string}"/>
</ui:repeat>
with the backing List<MString> mstrings.
Note that if you have your model class, like User, and will change its properties within <ui:repeat> the class itself will be effectively a wrapper, so that the properties will be set appropriately.
Workaround #2: chained property access
Another workaround consists of accessing an element of your collection directly from within a <h:inputText> tag. This way, any such property will be set by accessing the bean, then collection, then setting the property at the desired index. Excessively long, but that's how it is. As to the how question, <ui:repeat> provides for an exported current iteration status variable, varStatus, that will be used to access the array/collection in the managed bean.
In this case the iteration will also be working as predicted:
<ui:repeat value="#{bean.strings}" var="s" varStatus="status">
<h:inputText value="#{bean.strings[status.index]}"/>
</ui:repeat>
with the ordinary backing List<String> strings.
My workaround solution take the value directly from the page:
<ui:repeat id="repeat" value="#{bean.strings}" var="s" varStatus="status">
<h:inputText id="x" value="#{s.field}"/>
<h:commandLink style="margin: .5em 0" styleClass="commandLink" actionListener="#{bean.save(status.index)}" value="#{bundle.Send}"/>
</ui:repeat>
The save method:
public void save(String rowid) {
String jsParam = Util.getJsParam("repeat:" + rowid + ":x");
System.out.println("jsParam: " + jsParam); //persist...
}
The getJsParam method:
public static String getJsParam(String paramName) {
javax.faces.context.FacesContext jsf = javax.faces.context.FacesContext.getCurrentInstance();
Map<String, String> requestParameterMap = jsf.getExternalContext().getRequestParameterMap();
String paramValue = requestParameterMap.get(paramName);
if (paramValue != null) {
paramValue = paramValue.trim();
if (paramValue.length() == 0) {
paramValue = null;
}
}
return paramValue;
}
I understand I cannot use <c:choose> within a component in a jsf page. I am trying to see if there is an alternative. I looked at the Tomahawk and that isn't what I really need. I am trying to validate negative and positive numbers in a column. I want to be able to choose between the 2 validator tags that I have created. I tried using the rendered attribute but it still doesn't work. Below is kind of what I am looking for but it is not working like I want it to. Does anyone have any suggestions??
Thanks in advance.
<c:choose>
<c:when test="#{entry.dataEntry.posValue}">
<f:validator validatorId="hits.positiveNumberValidator"/>
</c:when>
<c:otherwise test="#{entry.dataEntry.negValue}">
<f:validator validatorId="hits.negativeNumberValidator"/>
</c:otherwise>
</c:choose>
Wrap in another validator and add them as attributes.
<f:validator validatorId="hits.numberValidator"/>
<f:attribute name="posValue" value="#{entry.dataEntry.posValue}" />
<f:attribute name="negValue" value="#{entry.dataEntry.negValue}" />
And then in the NumberValidator:
Boolean negValue = component.getAttributes().get("negValue");
if (posValue != null && posValue) {
new PositiveNumberValidator().validate(context, component, value);
}
Boolean posValue = component.getAttributes().get("posValue");
if (negValue != null && negValue) {
new NegativeNumberValidator().validate(context, component, value);
}
Note that this doesn't work when #{entry} is actually an iterated item like as declared in var attribute of h:dataTable or ui:repeat, because the f:attribute is tied to the JSF component, not to its output. Since the variable name #{entry} hints less or more that this is actually the case, here's how you could do it.
Wrap the collection in a DataModel:
private DataModel entries;
public Bean() {
entries = new ListDataModel(someDAO.list());
}
// ...
Use it in h:dataTable or ui:repeat as follows:
<h:dataTable value="#{bean.entries}" var="entry">
<h:column>
<h:inputText validator="#{bean.numberValidator}" />
</h:column>
</h:dataTable>
And implement the validator in the Bean as follows:
public void numberValidator(FacesContext context, UIComponent component, Object value) throws ValidatorException) {
Entry entry = (Entry) entries.getRowData();
if (entry.isPosValue()) {
new PositiveNumberValidator().validate(context, component, value);
}
if (entry.isNegValue()) {
new NegativeNumberValidator().validate(context, component, value);
}
}
(you may want to make those validators an instance variable of the bean instead (only if they are threadsafe))
can some one help me with the following JSF dataTable? here I am getting data from database table and I used dataTable binding, but I don't know why it displays the rows 3 times in the screen, but if I remove the binding then it displays only one time.
<h:dataTable binding="#{threadController.dataTable}" var="category" value="#{threadController.queryCategories}" border="1" cellpadding="2" cellspacing="0">
<h:column>
<img src="../../images/directory.jpg" alt="Forum Icon" />
</h:column>
<h:column>
<h:form>
<h:commandLink value="#{category.cname}" action="#{threadController.categoryDateItem}" />
</h:form>
</h:column>
// defined globally
private HtmlDataTable dataTable;
private HtmlInputHidden dataItemId = new HtmlInputHidden();
public String categoryDateItem() {
category = (Category) dataTable.getRowData();
System.out.println("category action by select: "+category.getCname());
dataItemId.setValue(category.getId());
return "editItem"; // Navigation case.
}
#SuppressWarnings("unchecked")
public ArrayList<Category> getQueryCategories(){
return (ArrayList<Category>)HibernateUtil.getSession().createCriteria(Category.class).list();
}
output:
myText myText myText
The binding expression to bind this component to the bean value="#{threadController.queryCategories}".So value attribute is sufficient to retrieve data using dataTable tag.
Binding = component backing bean
Value= data model backing bean
So, you have the Value and Binding set correctly (at least, as far as I can see). Your problem may result from the fact that you're not caching the list you're getting back from the database in getQueryCategories().
You really can't have any idea how often getQueryCategories() will be called in the process of rendering that dataTable, so it's a good idea to do something like this:
// Somewhere near the top of the handler class.. create a cache variable:
private ArrayList<Category> qCategories = null;
// now for getQueryCategories
public ArrayList<Category> getQueryCategories(){
if ( qCategories == null ) { // qCategories should be a member of the handler
qCategories = (ArrayList<Category>)HibernateUtil.getSession().createCriteria(Category.class).list();
}
return qCategories
}
This kind of cache-ing is very helpful in JSF apps with handlers that are session of even request scoped, as again you can't really know how often JSF will evaluate your "value" expression in the dataTable.