How to edit data in Primefaces DataTable without in-cell editing? - jsf-2

I have 2 pages.
Add Page for add a new item
List Page for show all items
When I click on Edit icon on List Page, I want to show selected data on Add Page for editing and update its data if I click on save button. How to do this?

Pass the row identifier as a parameter to the button. For example, assuming that #{item} is the currently iterated item and has some Long id property which uniquely identifies the item.
<p:button icon="ui-icon-pencil" outcome="edit.xhtml">
<f:param name="id" value="#{item.id}" />
</p:button>
In the target page, edit.xhtml, you can use <f:viewParam> to convert, validate and set it as a bean property.
<f:metadata>
<f:viewParam name="id" value="#{bean.item}" required="true" converter="itemConverter" />
</f:metadata>
...
<p:inputText value="#{bean.item.name}" />
<p:inputText value="#{bean.item.shortName}" />
See also:
What can <f:metadata>, <f:viewParam> and <f:viewAction> be used for?
Communication in JSF 2.0 - Processing GET request parameters

Related

PrimeFaces CommandLink in dynamic datatable

I have a breadcrumb and datatable
Number of columns is dynamic. (ie: On clicking "Header7" in breadcrumb, 7 header column plus one "More-Info" column is to be rendered).
I created data-table using primefaces-datatable-columns
My xhtml file is :
<p:dataTable id="dataMain" var="car" value="#{orgUnitBean.rows}">
<p:columns value="#{orgUnitBean.columns}" var="column"
columnIndexVar="colIndex" sortBy="#{car[column.property]}" filterBy="#{car[column.property]}">
<f:facet name="header">
<h:outputText value="#{column.header}" />
</f:facet>
<h:outputText value="#{car[column.property]}" />
</p:columns>
</p:dataTable>
Question:
how to add commandLink in "More-Info" column. (currently I am just displaying "id" of last "Header" entity in it. In image attached: 3 is id of unitL3 and 13 is id of Lnitu3. I want to replace it with commandLink which will invoke bean method and pass these id as parameter to it).
Thanks
Use the rendered attribute of a commandLink in combination with the colIndex. Put this in the column like this
<p:commandLink rendered="#{colIndex == 5}" ... />
Where 5 is the index of the more-info column. You can also do a string compare on the colum header if you want.
(This is a very basic jsf pattern btw)

How to hide components by selecting a new value on h:selectOneMenu?

I have a page with a h:selectOneMenu, and I want to hide a dataTable when I choose a new value on the h:selectOneMenu while some bean attribute values update. I'm trying diferent things, and I'm able to hide the dataTable by reloading the page. I have tried this using some JavaScript code, on onsomething attributes. In that case, those bean attribute values disapear although I use t:saveState (and I also need the view scope for the bean).
Here is a little example to clarify this:
<h:selectOneMenu id="list" value="#{Bean.id}">
<f:selectItems value="#{Bean.List}" var="element" itemLabel="#{element.name}" itemValue="#{element.id}"/>
<t:saveState value="#{Bean.id}"/>
<f:ajax listener="#{Bean.populateBean}" render=":form:period" event="change"/>
</h:selectOneMenu>
<h:selectOneMenu id="period" value="#{Bean.period}">
<f:selectItems value="#{Bean.listaPeriod}" var="period" itemLabel="#{period[1]}" itemValue="#{period[0]}"/>
<t:saveState value="#{Bean.period}"/>
</h:selectOneMenu>
<h:commandButton id="search" action="#{Bean.doSearch}"></h:commandButton>
<t:dataTable id="data" value="#{Bean.configList}" rendered="#{Bean.search}"
<t:column>
...
</t:dataTable>
And Bean.doSearch changes Bean.search to true. How can I hide the dataTable when I choose a new value on h:selectOneMenu id="list"?
EDIT:
In short, the search button renders the table, and I would want to hide that table when I just choose a new value on the "list" dropdown without reloading the page. Now, the <f:ajax> is used only to rerender the "period" dropdown value.
Thanks in advance!
Your question is hardly understandable, but if you want to kick the datatable out of your view on ajax request triggered by your dropdown, you need to enclose it in a component that's always present in the view so that HSF would know what to rerender when ajax call successfully finishes:
<h:panelGroup id="rerender">
<t:dataTable rendered="#{bean.condition}" ...>
....
</t:dataTable>
<h:panelGroup>
Of course, to get it working you should specify id of the component to be rerendered:
<h:selectOneMenu ...>
...
<f:ajax listener="#{bean.populate}" render="rerender" />
</h:selectOneMenu>
Note that if both dropdown and datatable components belong to the same form, it's not necessary to specify absolute id of the latter's parent. Also note that specifying event is redundant, as it already defaults to the right one. Finally, as you're on JSF 2.x, using save state is not necessary, just bind the values of your form data to a view scoped bean.
The last thing to note is the fact that you fail to conform to the Java Naming Conventions, the thing you should correct as soon as possible.

primefaces p:commandLink in p:datatable doesn't work [duplicate]

This is the code:
<h:form id="articleForm" >
<p:commandButton value="Select tags" ajax="true" >
<f:ajax execute="#form" render="#form :articleForm:tags" />
</p:commandButton>
<p:pickList id="tags" value="#{articleController.dualListModelForTags}" var="tag" itemLabel="#{tag.tag}" itemValue="#{tag}" converter="distinctTagConverter">
<f:facet name="sourceCaption">Distinct tags</f:facet>
<f:facet name="targetCaption">Connected tags</f:facet>
</p:pickList>
</h:form>
When the commandbutton is clicked, the getDualListModelForTags() in the backing bean is called and executed. In getDualListModelForTags() I make some modifications so I want the picklist to be updated. But the picklist(id=tags) is not rendered again. Only when I refresh the page, are the modifications made to the picklist.
The PrimeFaces <p:commandButton> component doesn't work together with <f:ajax>. You need to use the button's own ajax-targeted attributes instead. Instead of the <f:ajax execute> you should use <p:commandButton process>. But this already defaults to #form, so you can omit it. Instead of the <f:ajax render> you should use <p:commandButton update>. Specifying client IDs which are already covered by #form is unnecessary, so just #form is sufficient. Also the ajax="true" attribute is unnecessary as that's the default already.
So just this should do:
<p:commandButton value="Select tags" update="#form" />
Unrelated to the concrete problem, you're doing the business job inside a getter method. This is a bad idea. Do it in the button's action method instead. You also seem to be using a session scoped bean for view scoped data. This is a bad idea. Put the bean in the view scope instead.

Passing view parameter through backing bean

I have an inputtext in a page page1.xhtml and I want to pass the value the user will enter into a second page page2.xhmtl as a view parameter using a get method. I use an h:button and put as outcome value from the backing bean but it when I navigate to the second page I the parameter is not passed. What's wrong? Is the value not passed to the backing bean before pressing the button and therefore value cannot be read? Is there another way to do it?
page1.xhtml
h:inputText id="q" value="#{QBean.q}"></h:inputText>
<h:button value="Done" outcome="page2?q=#{indexBean.q}">
page2.xhtml
<f:metadata>
<f:viewParam name="q" value="#{QBean.q}"/>
</f:metadata>
QBean
private String q;
//setter
//getter
Your sole functional requirement seems to be that you want a GET form instead of a POST form. In that case, use normal HTML elements, not JSF components.
<form action="page2.xhtml">
<input name="q" />
<input type="submit" value="Done" />
</form>
You could use the POST-REDIRECT-GET approach and take commandButton instead: <h:commandButton value="Done" action="page2?faces-redirect=true&includeViewParams=true"/>

How to navigate with request parameters?

I want to navigate from one page to another page, say from page1 with bean1 to page2 with bean2. I need to pass some parameters from bean1 to bean2.
I would like to understand how to use #ManagedProperty for parameters and <f:viewParam> in <f:metadata> portion of page2. Say, I have field1, field2 and field3 available in bean1 and bean2 with getters and setters. My understanding is that I will have to define view params in Metadata of page2:
Like
<f:metadata>
<f:viewParam name="field1" value="#{bean2.field1}"/>
<f:viewParam name="field2" value="#{bean2.field2}"/>
<f:viewParam name="field3" value="#{bean2.field3}"/>
</f:metadata>
I am not sure where I use annotations for #ManagedProperty to define the parameters field1, field2 and field3, in bean1 or bean2.
On page1 I can use "page2?faces-redirect=true&includeViewParams=true"
Can I use the same in one of my methods instead in page1, say on response to a submit of commandlink?
If I need to have those three fields in both page1 and page2, can I define those hidden fields?
You need to specify them as <f:param> in the <h:link> of page1.xhtml.
<h:link value="Go to page2" outcome="page2">
<f:param name="field1" value="#{bean1.field1}" />
<f:param name="field2" value="#{bean1.field2}" />
<f:param name="field3" value="#{bean1.field3}" />
</h:link>
You can then use <f:viewParam> (or #ManagedProperty, but this allows less fine grained validation) to set them in bean of page2.xhtml.
<f:metadata>
<f:viewParam name="field1" value="#{bean2.field1}" />
<f:viewParam name="field2" value="#{bean2.field2}" />
<f:viewParam name="field3" value="#{bean2.field3}" />
</f:metadata>
You do not need to send a POST request by <h:commandLink> with faces-redirect and includeViewParam here. Just a simple GET request by <h:link> is much simpler and SEO friendlier.
See also:
What can <f:metadata>, <f:viewParam> and <f:viewAction> be used for?
ViewParam vs #ManagedProperty(value = "#{param.id}")
When should I use h:outputLink instead of h:commandLink?
Communication in JSF 2.0 - Processing GET request parameters

Resources