I have a page with a data table. I want some of the items in the tables to be linked to a corresponding view page.
For example, right now I have a table with no links:
<h:dataTable var="bean" value="#{beanServiceImpl.beans}" border="1">
<h:column>#{bean.id}</h:column>
</h:dataTable>
I want to add hyperlinks to some entries and have them go to a view page showing them more info based on their id:
<h:dataTable var="bean" value="#{beanServiceImpl.beans}" border="1">
<h:column>
#{bean.id}
</h:column>
</h:dataTable>
ViewBean.xhtml will contain something like this:
ViewBean.xhtml
<ul>
<li>ID: #{bean.id}</li>
<li>Field 1: #{bean.field1}</li>
<li>Field 2: #{bean.field2}</li>
</ul>
How do I accomplish something like this in JSF? I know that I'll have to write a controller to query the id for the other fields. But how do I make viewBean.xhtml run the business logic to get the other fields and render it?
The BalusC's answer is almost good, but will not work (edit: it works now).
You already know, how to add the value to the params. BTW, if I were you, I would not use <a href>, but instead:
<h:link outcome='viewBean'>
<f:param name='id' value='#{bean.id}' />
</h:link>
Now you have to choices when it comes to catching the value. The simplest would be to add annotation above your id property:
#ManagedProperty("#{param.id}") // this will inject id from param into id
private Long id;
// (getters and setters are obligatory)
#PostConstruct // this will execute init() after id is injected
public void init() {
}
And the last thing: having a variable named "bean" has no more sense than calling it "variable" (or having a dog named Dog and cat named Cat). It carries no information and worse, it makes all the beans in your application indistinguishable (unless you build a legumes manager).
I'll assume JSF 2.x. Add this to your Bean
#ManagedProperty(value="#{param.id}")
private Long id;
(this does basically a bean.setId(request.getParameter("id")) whenever the view loads)
It'll be available in #PostConstruct method of Bean.
#PostConstruct
public void init() {
// Fill model based on id.
}
This is what I did.
<h:form>
<h:commandLink action="#{bean.populateBean}" value="#{bean.id}">
<f:setPropertyActionListener target="#{bean.id}" value="#{bean.id}" />
</h:commandLink>
</h:form>
In my Bean.java class, I added the action controller:
public String populateBean(){
Bean bean = BeanServiceImpl.getBean(id); //id was injected by the commandLink
this.field1 = tenure.getField1();
this.field2 = tenure.getField2();
return("viewBean");
}
My ViewBean.xhtml is the same:
<ul>
<li>ID: #{bean.id}</li>
<li>Field 1: #{bean.field1}</li>
<li>Field 2: #{bean.field2}</li>
</ul>
Related
I'm using Primefaces in a JSF 2 application. I have a <p:dataTable>, and instead of selecting rows, I want the user to be able to directly execute various actions on individual rows. For that, I have several <p:commandLink>s in the last column.
My problem: how can I pass a row ID to the action started by the command link so that I know which row to act on? I tried using an <f:attribute>:
<p:dataTable value="#{bean.items}" var="item">
...
<p:column>
<p:commandLink actionListener="#{bean.insert}" value="insert">
<f:attribute name="id" value="#{item.id}" />
</p:commandLink>
</p:column>
</p:dataTable>
But it always yields 0 - apparently the row variable f is not available when the attribute is rendered (it works when I use a fixed value).
Anyone has an alternative solution?
As to the cause, the <f:attribute> is specific to the component itself (populated during view build time), not to the iterated row (populated during view render time).
There are several ways to achieve the requirement.
If your servletcontainer supports a minimum of Servlet 3.0 / EL 2.2, then just pass it as an argument of action/listener method of UICommand component or AjaxBehavior tag. E.g.
<h:commandLink action="#{bean.insert(item.id)}" value="insert" />
In combination with:
public void insert(Long id) {
// ...
}
This only requires that the datamodel is preserved for the form submit request. Best is to put the bean in the view scope by #ViewScoped.
You can even pass the entire item object:
<h:commandLink action="#{bean.insert(item)}" value="insert" />
with:
public void insert(Item item) {
// ...
}
On Servlet 2.5 containers, this is also possible if you supply an EL implementation which supports this, like as JBoss EL. For configuration detail, see this answer.
Use <f:param> in UICommand component. It adds a request parameter.
<h:commandLink action="#{bean.insert}" value="insert">
<f:param name="id" value="#{item.id}" />
</h:commandLink>
If your bean is request scoped, let JSF set it by #ManagedProperty
#ManagedProperty(value="#{param.id}")
private Long id; // +setter
Or if your bean has a broader scope or if you want more fine grained validation/conversion, use <f:viewParam> on the target view, see also f:viewParam vs #ManagedProperty:
<f:viewParam name="id" value="#{bean.id}" required="true" />
Either way, this has the advantage that the datamodel doesn't necessarily need to be preserved for the form submit (for the case that your bean is request scoped).
Use <f:setPropertyActionListener> in UICommand component. The advantage is that this removes the need for accessing the request parameter map when the bean has a broader scope than the request scope.
<h:commandLink action="#{bean.insert}" value="insert">
<f:setPropertyActionListener target="#{bean.id}" value="#{item.id}" />
</h:commandLink>
In combination with
private Long id; // +setter
It'll be just available by property id in action method. This only requires that the datamodel is preserved for the form submit request. Best is to put the bean in the view scope by #ViewScoped.
Bind the datatable value to DataModel<E> instead which in turn wraps the items.
<h:dataTable value="#{bean.model}" var="item">
with
private transient DataModel<Item> model;
public DataModel<Item> getModel() {
if (model == null) {
model = new ListDataModel<Item>(items);
}
return model;
}
(making it transient and lazily instantiating it in the getter is mandatory when you're using this on a view or session scoped bean since DataModel doesn't implement Serializable)
Then you'll be able to access the current row by DataModel#getRowData() without passing anything around (JSF determines the row based on the request parameter name of the clicked command link/button).
public void insert() {
Item item = model.getRowData();
Long id = item.getId();
// ...
}
This also requires that the datamodel is preserved for the form submit request. Best is to put the bean in the view scope by #ViewScoped.
Use Application#evaluateExpressionGet() to programmatically evaluate the current #{item}.
public void insert() {
FacesContext context = FacesContext.getCurrentInstance();
Item item = context.getApplication().evaluateExpressionGet(context, "#{item}", Item.class);
Long id = item.getId();
// ...
}
Which way to choose depends on the functional requirements and whether the one or the other offers more advantages for other purposes. I personally would go ahead with #1 or, when you'd like to support servlet 2.5 containers as well, with #2.
In JSF 1.2 this was done by <f:setPropertyActionListener> (within the command component). In JSF 2.0 (EL 2.2 to be precise, thanks to BalusC) it's possible to do it like this: action="${filterList.insert(f.id)}
In my view page:
<p:dataTable ...>
<p:column>
<p:commandLink actionListener="#{inquirySOController.viewDetail}"
process="#this" update=":mainform:dialog_content"
oncomplete="dlg2.show()">
<h:graphicImage library="images" name="view.png"/>
<f:param name="trxNo" value="#{item.map['trxNo']}"/>
</p:commandLink>
</p:column>
</p:dataTable>
backing bean
public void viewDetail(ActionEvent e) {
String trxNo = getFacesContext().getRequestParameterMap().get("trxNo");
for (DTO item : list) {
if (item.get("trxNo").toString().equals(trxNo)) {
System.out.println(trxNo);
setSelectedItem(item);
break;
}
}
}
Thanks to this site by Mkyong, the only solution that actually worked for us to pass a parameter was this
<h:commandLink action="#{user.editAction}">
<f:param name="myId" value="#{param.id}" />
</h:commandLink>
with
public String editAction() {
Map<String,String> params =
FacesContext.getExternalContext().getRequestParameterMap();
String idString = params.get("myId");
long id = Long.parseLong(idString);
...
}
Technically, that you cannot pass to the method itself directly, but to the JSF request parameter map.
I'm using Primefaces in a JSF 2 application. I have a <p:dataTable>, and instead of selecting rows, I want the user to be able to directly execute various actions on individual rows. For that, I have several <p:commandLink>s in the last column.
My problem: how can I pass a row ID to the action started by the command link so that I know which row to act on? I tried using an <f:attribute>:
<p:dataTable value="#{bean.items}" var="item">
...
<p:column>
<p:commandLink actionListener="#{bean.insert}" value="insert">
<f:attribute name="id" value="#{item.id}" />
</p:commandLink>
</p:column>
</p:dataTable>
But it always yields 0 - apparently the row variable f is not available when the attribute is rendered (it works when I use a fixed value).
Anyone has an alternative solution?
As to the cause, the <f:attribute> is specific to the component itself (populated during view build time), not to the iterated row (populated during view render time).
There are several ways to achieve the requirement.
If your servletcontainer supports a minimum of Servlet 3.0 / EL 2.2, then just pass it as an argument of action/listener method of UICommand component or AjaxBehavior tag. E.g.
<h:commandLink action="#{bean.insert(item.id)}" value="insert" />
In combination with:
public void insert(Long id) {
// ...
}
This only requires that the datamodel is preserved for the form submit request. Best is to put the bean in the view scope by #ViewScoped.
You can even pass the entire item object:
<h:commandLink action="#{bean.insert(item)}" value="insert" />
with:
public void insert(Item item) {
// ...
}
On Servlet 2.5 containers, this is also possible if you supply an EL implementation which supports this, like as JBoss EL. For configuration detail, see this answer.
Use <f:param> in UICommand component. It adds a request parameter.
<h:commandLink action="#{bean.insert}" value="insert">
<f:param name="id" value="#{item.id}" />
</h:commandLink>
If your bean is request scoped, let JSF set it by #ManagedProperty
#ManagedProperty(value="#{param.id}")
private Long id; // +setter
Or if your bean has a broader scope or if you want more fine grained validation/conversion, use <f:viewParam> on the target view, see also f:viewParam vs #ManagedProperty:
<f:viewParam name="id" value="#{bean.id}" required="true" />
Either way, this has the advantage that the datamodel doesn't necessarily need to be preserved for the form submit (for the case that your bean is request scoped).
Use <f:setPropertyActionListener> in UICommand component. The advantage is that this removes the need for accessing the request parameter map when the bean has a broader scope than the request scope.
<h:commandLink action="#{bean.insert}" value="insert">
<f:setPropertyActionListener target="#{bean.id}" value="#{item.id}" />
</h:commandLink>
In combination with
private Long id; // +setter
It'll be just available by property id in action method. This only requires that the datamodel is preserved for the form submit request. Best is to put the bean in the view scope by #ViewScoped.
Bind the datatable value to DataModel<E> instead which in turn wraps the items.
<h:dataTable value="#{bean.model}" var="item">
with
private transient DataModel<Item> model;
public DataModel<Item> getModel() {
if (model == null) {
model = new ListDataModel<Item>(items);
}
return model;
}
(making it transient and lazily instantiating it in the getter is mandatory when you're using this on a view or session scoped bean since DataModel doesn't implement Serializable)
Then you'll be able to access the current row by DataModel#getRowData() without passing anything around (JSF determines the row based on the request parameter name of the clicked command link/button).
public void insert() {
Item item = model.getRowData();
Long id = item.getId();
// ...
}
This also requires that the datamodel is preserved for the form submit request. Best is to put the bean in the view scope by #ViewScoped.
Use Application#evaluateExpressionGet() to programmatically evaluate the current #{item}.
public void insert() {
FacesContext context = FacesContext.getCurrentInstance();
Item item = context.getApplication().evaluateExpressionGet(context, "#{item}", Item.class);
Long id = item.getId();
// ...
}
Which way to choose depends on the functional requirements and whether the one or the other offers more advantages for other purposes. I personally would go ahead with #1 or, when you'd like to support servlet 2.5 containers as well, with #2.
In JSF 1.2 this was done by <f:setPropertyActionListener> (within the command component). In JSF 2.0 (EL 2.2 to be precise, thanks to BalusC) it's possible to do it like this: action="${filterList.insert(f.id)}
In my view page:
<p:dataTable ...>
<p:column>
<p:commandLink actionListener="#{inquirySOController.viewDetail}"
process="#this" update=":mainform:dialog_content"
oncomplete="dlg2.show()">
<h:graphicImage library="images" name="view.png"/>
<f:param name="trxNo" value="#{item.map['trxNo']}"/>
</p:commandLink>
</p:column>
</p:dataTable>
backing bean
public void viewDetail(ActionEvent e) {
String trxNo = getFacesContext().getRequestParameterMap().get("trxNo");
for (DTO item : list) {
if (item.get("trxNo").toString().equals(trxNo)) {
System.out.println(trxNo);
setSelectedItem(item);
break;
}
}
}
Thanks to this site by Mkyong, the only solution that actually worked for us to pass a parameter was this
<h:commandLink action="#{user.editAction}">
<f:param name="myId" value="#{param.id}" />
</h:commandLink>
with
public String editAction() {
Map<String,String> params =
FacesContext.getExternalContext().getRequestParameterMap();
String idString = params.get("myId");
long id = Long.parseLong(idString);
...
}
Technically, that you cannot pass to the method itself directly, but to the JSF request parameter map.
I'm using Primefaces in a JSF 2 application. I have a <p:dataTable>, and instead of selecting rows, I want the user to be able to directly execute various actions on individual rows. For that, I have several <p:commandLink>s in the last column.
My problem: how can I pass a row ID to the action started by the command link so that I know which row to act on? I tried using an <f:attribute>:
<p:dataTable value="#{bean.items}" var="item">
...
<p:column>
<p:commandLink actionListener="#{bean.insert}" value="insert">
<f:attribute name="id" value="#{item.id}" />
</p:commandLink>
</p:column>
</p:dataTable>
But it always yields 0 - apparently the row variable f is not available when the attribute is rendered (it works when I use a fixed value).
Anyone has an alternative solution?
As to the cause, the <f:attribute> is specific to the component itself (populated during view build time), not to the iterated row (populated during view render time).
There are several ways to achieve the requirement.
If your servletcontainer supports a minimum of Servlet 3.0 / EL 2.2, then just pass it as an argument of action/listener method of UICommand component or AjaxBehavior tag. E.g.
<h:commandLink action="#{bean.insert(item.id)}" value="insert" />
In combination with:
public void insert(Long id) {
// ...
}
This only requires that the datamodel is preserved for the form submit request. Best is to put the bean in the view scope by #ViewScoped.
You can even pass the entire item object:
<h:commandLink action="#{bean.insert(item)}" value="insert" />
with:
public void insert(Item item) {
// ...
}
On Servlet 2.5 containers, this is also possible if you supply an EL implementation which supports this, like as JBoss EL. For configuration detail, see this answer.
Use <f:param> in UICommand component. It adds a request parameter.
<h:commandLink action="#{bean.insert}" value="insert">
<f:param name="id" value="#{item.id}" />
</h:commandLink>
If your bean is request scoped, let JSF set it by #ManagedProperty
#ManagedProperty(value="#{param.id}")
private Long id; // +setter
Or if your bean has a broader scope or if you want more fine grained validation/conversion, use <f:viewParam> on the target view, see also f:viewParam vs #ManagedProperty:
<f:viewParam name="id" value="#{bean.id}" required="true" />
Either way, this has the advantage that the datamodel doesn't necessarily need to be preserved for the form submit (for the case that your bean is request scoped).
Use <f:setPropertyActionListener> in UICommand component. The advantage is that this removes the need for accessing the request parameter map when the bean has a broader scope than the request scope.
<h:commandLink action="#{bean.insert}" value="insert">
<f:setPropertyActionListener target="#{bean.id}" value="#{item.id}" />
</h:commandLink>
In combination with
private Long id; // +setter
It'll be just available by property id in action method. This only requires that the datamodel is preserved for the form submit request. Best is to put the bean in the view scope by #ViewScoped.
Bind the datatable value to DataModel<E> instead which in turn wraps the items.
<h:dataTable value="#{bean.model}" var="item">
with
private transient DataModel<Item> model;
public DataModel<Item> getModel() {
if (model == null) {
model = new ListDataModel<Item>(items);
}
return model;
}
(making it transient and lazily instantiating it in the getter is mandatory when you're using this on a view or session scoped bean since DataModel doesn't implement Serializable)
Then you'll be able to access the current row by DataModel#getRowData() without passing anything around (JSF determines the row based on the request parameter name of the clicked command link/button).
public void insert() {
Item item = model.getRowData();
Long id = item.getId();
// ...
}
This also requires that the datamodel is preserved for the form submit request. Best is to put the bean in the view scope by #ViewScoped.
Use Application#evaluateExpressionGet() to programmatically evaluate the current #{item}.
public void insert() {
FacesContext context = FacesContext.getCurrentInstance();
Item item = context.getApplication().evaluateExpressionGet(context, "#{item}", Item.class);
Long id = item.getId();
// ...
}
Which way to choose depends on the functional requirements and whether the one or the other offers more advantages for other purposes. I personally would go ahead with #1 or, when you'd like to support servlet 2.5 containers as well, with #2.
In JSF 1.2 this was done by <f:setPropertyActionListener> (within the command component). In JSF 2.0 (EL 2.2 to be precise, thanks to BalusC) it's possible to do it like this: action="${filterList.insert(f.id)}
In my view page:
<p:dataTable ...>
<p:column>
<p:commandLink actionListener="#{inquirySOController.viewDetail}"
process="#this" update=":mainform:dialog_content"
oncomplete="dlg2.show()">
<h:graphicImage library="images" name="view.png"/>
<f:param name="trxNo" value="#{item.map['trxNo']}"/>
</p:commandLink>
</p:column>
</p:dataTable>
backing bean
public void viewDetail(ActionEvent e) {
String trxNo = getFacesContext().getRequestParameterMap().get("trxNo");
for (DTO item : list) {
if (item.get("trxNo").toString().equals(trxNo)) {
System.out.println(trxNo);
setSelectedItem(item);
break;
}
}
}
Thanks to this site by Mkyong, the only solution that actually worked for us to pass a parameter was this
<h:commandLink action="#{user.editAction}">
<f:param name="myId" value="#{param.id}" />
</h:commandLink>
with
public String editAction() {
Map<String,String> params =
FacesContext.getExternalContext().getRequestParameterMap();
String idString = params.get("myId");
long id = Long.parseLong(idString);
...
}
Technically, that you cannot pass to the method itself directly, but to the JSF request parameter map.
I'm having a little trouble with immediate="true" (JSF 1.2). My form is about a car accident: the user fills in some ubication information and then he can add as many affected items as he wishes (trees, fences, other cars, etc.)
Backing bean
private String location;
private List<T> items;
private HtmlDataTable itemsUI;
public void remove(ActionEvent e) {
String id = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("id");
items.remove(Integer.parseInt(id));
}
public void add(ActionEvent e) throws InstantiationException, IllegalAccessException {
items.add(element.newInstance());
}
JSPX
<h:inputText
required="true"
value="#{ACC01.location}"/>
<h:dataTable
binding="#{ACC01.itemsUI }"
value="#{ACC01.items}"
var="item">
<h:column>
<h:selectOneMenu
value="#{item.id}>
<f:selectItems
value="#{ACC01.possibleElements}" />
</h:selectOneMenu>
<h:commandLink
actionListener="#{ACC01.remove }"
value="Remove" >
<f:param
name="id"
value="#{ACC01.itemsUI.rowIndex }"/>
</h:commandLink>
</h:column>
</h:dataTable>
<h:commandLink
actionListener="#{ACC01.add}"
value="Add" />
The problem
If I set immediate="true" for the affected elements in the dataTable, when the user adds a new element the other elements return to their default values (e.g. if you had {'tree', 'car', 'fence'} they become {'default', 'default', 'default', new element})
If I don't use immediate, the affected elements keep the right values, but the user is forced to fill in the 'location' field before he can add or remove affected elements.
What I want is to be able to keep the affected elements' values and allow the user to add or remove them without having to fill the 'location' field first.
The workaround
After reading many posts about this topic, it seems that the only way to go is to avoid automatic validation and make it manually when the user submits the form.
Check for nulls on required fields, and programatically appending the error messages to facescontext. I really do not want to do that because i think it is ugly.
Can you please suggest better ways to achieve the behavior i need?
Thanks in advance
One of the previous developers at my current job came up with the following solution
JSPX
<h:inputText required="#{ACC01.saving}" value="#{ACC01.location}"/>
Backing Bean
private UICommand btn;
public boolean isSaving()
{
Map<?,?> params = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();
return (params.containsKey(btn.getClientId(ctx)));
}
It might not be totally correct in your situation, but basically he created a binding from the button on screen to the 'btn' variable in the backing bean. Then inputText would only see the location text being required when the btn was clicked. In your case it's a command link so it might be a little different but I thought it might help.
I'm using Primefaces in a JSF 2 application. I have a <p:dataTable>, and instead of selecting rows, I want the user to be able to directly execute various actions on individual rows. For that, I have several <p:commandLink>s in the last column.
My problem: how can I pass a row ID to the action started by the command link so that I know which row to act on? I tried using an <f:attribute>:
<p:dataTable value="#{bean.items}" var="item">
...
<p:column>
<p:commandLink actionListener="#{bean.insert}" value="insert">
<f:attribute name="id" value="#{item.id}" />
</p:commandLink>
</p:column>
</p:dataTable>
But it always yields 0 - apparently the row variable f is not available when the attribute is rendered (it works when I use a fixed value).
Anyone has an alternative solution?
As to the cause, the <f:attribute> is specific to the component itself (populated during view build time), not to the iterated row (populated during view render time).
There are several ways to achieve the requirement.
If your servletcontainer supports a minimum of Servlet 3.0 / EL 2.2, then just pass it as an argument of action/listener method of UICommand component or AjaxBehavior tag. E.g.
<h:commandLink action="#{bean.insert(item.id)}" value="insert" />
In combination with:
public void insert(Long id) {
// ...
}
This only requires that the datamodel is preserved for the form submit request. Best is to put the bean in the view scope by #ViewScoped.
You can even pass the entire item object:
<h:commandLink action="#{bean.insert(item)}" value="insert" />
with:
public void insert(Item item) {
// ...
}
On Servlet 2.5 containers, this is also possible if you supply an EL implementation which supports this, like as JBoss EL. For configuration detail, see this answer.
Use <f:param> in UICommand component. It adds a request parameter.
<h:commandLink action="#{bean.insert}" value="insert">
<f:param name="id" value="#{item.id}" />
</h:commandLink>
If your bean is request scoped, let JSF set it by #ManagedProperty
#ManagedProperty(value="#{param.id}")
private Long id; // +setter
Or if your bean has a broader scope or if you want more fine grained validation/conversion, use <f:viewParam> on the target view, see also f:viewParam vs #ManagedProperty:
<f:viewParam name="id" value="#{bean.id}" required="true" />
Either way, this has the advantage that the datamodel doesn't necessarily need to be preserved for the form submit (for the case that your bean is request scoped).
Use <f:setPropertyActionListener> in UICommand component. The advantage is that this removes the need for accessing the request parameter map when the bean has a broader scope than the request scope.
<h:commandLink action="#{bean.insert}" value="insert">
<f:setPropertyActionListener target="#{bean.id}" value="#{item.id}" />
</h:commandLink>
In combination with
private Long id; // +setter
It'll be just available by property id in action method. This only requires that the datamodel is preserved for the form submit request. Best is to put the bean in the view scope by #ViewScoped.
Bind the datatable value to DataModel<E> instead which in turn wraps the items.
<h:dataTable value="#{bean.model}" var="item">
with
private transient DataModel<Item> model;
public DataModel<Item> getModel() {
if (model == null) {
model = new ListDataModel<Item>(items);
}
return model;
}
(making it transient and lazily instantiating it in the getter is mandatory when you're using this on a view or session scoped bean since DataModel doesn't implement Serializable)
Then you'll be able to access the current row by DataModel#getRowData() without passing anything around (JSF determines the row based on the request parameter name of the clicked command link/button).
public void insert() {
Item item = model.getRowData();
Long id = item.getId();
// ...
}
This also requires that the datamodel is preserved for the form submit request. Best is to put the bean in the view scope by #ViewScoped.
Use Application#evaluateExpressionGet() to programmatically evaluate the current #{item}.
public void insert() {
FacesContext context = FacesContext.getCurrentInstance();
Item item = context.getApplication().evaluateExpressionGet(context, "#{item}", Item.class);
Long id = item.getId();
// ...
}
Which way to choose depends on the functional requirements and whether the one or the other offers more advantages for other purposes. I personally would go ahead with #1 or, when you'd like to support servlet 2.5 containers as well, with #2.
In JSF 1.2 this was done by <f:setPropertyActionListener> (within the command component). In JSF 2.0 (EL 2.2 to be precise, thanks to BalusC) it's possible to do it like this: action="${filterList.insert(f.id)}
In my view page:
<p:dataTable ...>
<p:column>
<p:commandLink actionListener="#{inquirySOController.viewDetail}"
process="#this" update=":mainform:dialog_content"
oncomplete="dlg2.show()">
<h:graphicImage library="images" name="view.png"/>
<f:param name="trxNo" value="#{item.map['trxNo']}"/>
</p:commandLink>
</p:column>
</p:dataTable>
backing bean
public void viewDetail(ActionEvent e) {
String trxNo = getFacesContext().getRequestParameterMap().get("trxNo");
for (DTO item : list) {
if (item.get("trxNo").toString().equals(trxNo)) {
System.out.println(trxNo);
setSelectedItem(item);
break;
}
}
}
Thanks to this site by Mkyong, the only solution that actually worked for us to pass a parameter was this
<h:commandLink action="#{user.editAction}">
<f:param name="myId" value="#{param.id}" />
</h:commandLink>
with
public String editAction() {
Map<String,String> params =
FacesContext.getExternalContext().getRequestParameterMap();
String idString = params.get("myId");
long id = Long.parseLong(idString);
...
}
Technically, that you cannot pass to the method itself directly, but to the JSF request parameter map.