Primefaces Data Table actionListener for inline cell editing - jsf

How do I execute code when the user clicks a cell in a data table? Similarly to listener and actionListener on a p:commandButton.
For example
<p:commandButton oncomplete="PF('editProductDialog').show()"
actionListener="#{bean.doStuffToGetASelectOneMenuReadyforTheEditProductDialog()}" />
public void doStuffToGetDialogReady() {
//query databases to get select item list
}
The database is only queried when/if the user clicks the commandButton
But for p:dataTable inline cell editing how to I call code that would query database to get select items only when they click the data table cell to make an edit?
<p:cellEditor>
<f:facet name="output"/>
<f:facet name="input">
<p:selectOneMenu>
<f:selectItems value="#{bean.someListSpecificToThisUser}" />
</p:selectOneMenu>
</f:facet>
</p:cellEditor>
I've been populating the someListSpecificToThisUser selectItems list in the #PostConstruct init() method
#PostConstruct
public void init() {
//code specific to the page and datatable
someListSpecificToThisUser = service.queryValuesForUser(user);
}
but if the user never clicks the cell to edit the selectOneMenu value then I hit the database and stored the list in memory for no reason. Or should I not worry about the overhead?

In case of cell editing of a p:dataTable there are a few events you can use:
Event
Fired
cellEdit
When a cell is edited.
cellEditCancel
When a cell edit is cancelled e.g. with escape key
cellEditInit
When a cell edit begins.
All taking a org.primefaces.event.CellEditEvent as the listener parameter.
You could use the cellEditInit method to populate the list when it is still null. Downside is that this requires an Ajax call on each edit init.
An other option you have is to store the list in a SessionScoped user bean, which will cost you some memory.
The option to pick depends on the size of the list, how much time it takes to fetch the list and how many edits you expect. If you don't expect much edits, use an Ajax listener to populate the list. If the list is long and takes some time to load, I would switch to a p:autoComplete field.
See also:
https://primefaces.github.io/primefaces/10_0_0/#/components/datatable?id=ajax-behavior-events
How to choose the right bean scope?
https://www.primefaces.org/showcase/ui/input/autoComplete.xhtml

Related

PrimeFaces paginator selection

I have a PrimeFaces (5) DataTable and like to store the page size selection in the view, so that the user sees the same number of rows when he returns to the view.
But all I see from documentation is that there is a page event which can be captured, but which won't give me the currently selected page size. The closest I got was getting the event's source (the DataTable) and get the rows attribute, but it only contains the number of rows before applying the new value.
Here on SO, I found a solution here, but it seems to me not the best way to implement it having to use some inline JQuery stuff.
It seems to me a not-so-exotic feature to persist the page size selection within the session, so there must be a good solution for it, I assume?
As you already noticed, the page event is being fired before the selected number of rows has been applied to the table. At the moment, there is no event being fired after changing the number of rows.
However, there is a possible workaround:
bind your datatable to the backing bean
Use AJAX page-event without any listener. Instead, call a <p:remoteCommand> after ajax request is complete.
Add your actionListener method to the <p:remoteCommand>.
Within this method, check the datatable's number of rows. It's the new value.
Keep in mind, page event is not only fired when changing the number of rows, but also on page change.
Example:
XHTML/JSF
<h:form>
<p:remoteCommand name="pageChanged" actionListener="#{tableBean.onPageChanged}"/>
<p:dataTable binding="#{tableBean.table}" paginator="true" rowsPerPageTemplate="5,10,20" rows="5">
<p:ajax event="page" process="#none" oncomplete="pageChanged()" />
<!-- columns here -->
</p:dataTable>
</h:form>
TableBean.java
private DataTable table;
public void onPageChanged(){
int numRows = table.getRows();
// ...
}
//getter/setter for table

Cancel button jsf not resetting entity

I'm trying to implement a cancel button to clear the fields from my entity.
Though, when I'm setting the entity to null my fields still keep their value.
Code:
The EntityBB's cancel method (note that the debugger can reach the cancel method):
public void cancelAddStandardLetter() {
setEntity(null);
standardLetterInit();
}
this method really sets all the values from the entity back to null and the standardLetterInit method sets some default values that are needed (tried the same method without the standardLetterInit -> same result).
The xhtml page (other inputfields are left out):
<o:form includeRequestParams="true" id="addStandardLetterForm">
<h:inputTextvalue="#{entityBB.entity.fileName}" styleClass="rInput"/>
<h:commandButton value="Cancel" immediate="true"
styleClass="floatRight"
action="#{entityBB.cancelAddStandardLetter()}" />
</o:form>
After pressing the "cancel" button, the values being typed in the "fileName" field are still there. How can that be?
Make sure that the bean is view scoped and use a plain GET button.
<h:button value="Cancel" />
This basically refreshes the page. It'll recreate the view scoped bean instance. No need to submit the whole form. If the input values still appear, then it's either the browser cache or autocomplete/autofill which you in turn can control with respectively a servlet filter and autocomplete="off".

JSF Live search with primefaces

I'm trying to implement live searching with primefaces inputtext, all works well until the situation where user deletes last symbol in search field and all results must be shown back. For example when i open page all results are shown, i type letter a, results being filtered, delete a and again see all results. Problem is, when i delete last letter the ajax event is not being fired (maybe because of empty string?). Code for inputtext:
<p:inputText id="searchString" title="searchString" value="#{findDoctorBean.searchString}" >
<p:ajax event="keyup" listener="#{findDoctorBean.searchForDoctorsByName}" process="#this" update=":resultGroup"></p:ajax>
</p:inputText>
How should i fire an event in such situation?
i tested your Code with the following Ajax listenerMethod:
public final void search(AjaxBehaviorEvent event){
System.out.println("search: "+this.searchString);
}
and its being fired also with empty Strings.
So your Problem is in your searchForDoctorsByName Method in your bean, you have to reset (reInit) your DB-Items List if entered String is emtpy. So your Problem is in your SQL statement not in ajax.

Primefaces multiple select checkbox bean values in Javascript function

I have a primefaces multiple select table populated from a backing bean. I am using the table.getSelectedRowsCount() javascript widget var to validate atleast one selection and it is working fine.
I now want to throw up a javascript confirmation dialog based on the state of the selected rows. for ex I have a button at the bottom of the table for printing the details of selected rows. I need to check a certain field of the bean and then allow printing.
IN pseudo code
if (#{bean.isComplete})
allowPrinting();
else
// alert user that this row is not yet in complete state
Update and panelGroup on button ajax event as shown in follow.
<h:panelGroup id="validateRerpot">
<h:panelGroup rendered="#{bean.isComplete}">
<script type="text/javascript">alert('show Dialog inplace');</script>
</h:panelGroup>
</h:panelGroup>
Try to update validateReport panel

JSF selectOneMenu is refreshing and going back to its previous state rather than showing the new value

I have a datatable where a lot of selectOneMenu items are available , for example, for 10 items each having one selectOneMenu combo. now if i click on any of the combos, they are supposed to save the value in the database and they do it. but after saving the changed value the selectOneMenu is returning back to its previous state. I want the selectOneMenu to keep its current state. also, the method is being invoked for every single combo in the datatable. i really wonder why!! i have been banging my head for the last 2 weeks. any help would be really appreciated. thanks in advance.
this is my first post here. this is my jsf datatable:
<h:dataTable value="#{careNeedBean.controlledCareNeedsList}" var="careNeed"
id="careneed_table" binding="#{careNeedBean.dataTable}">
<h:column>
<f:facet name="header">
<h:outputText value="NeedsLevel"/>
</f:facet>
<h:selectOneMenu id="needs_level_combo" style="width:200px;font-size:9px;"
onchange="submit()"
valueChangeListener="#{careNeedBean.saveTaskAsessment}"
binding="#{careNeedBean.selectOneMenu}">
<f:selectItem itemValue="not_assessed" itemLabel="----Not assessed----"/>
<f:selectItems value="#{careNeed.humanReadableNeedsList}" />
</h:selectOneMenu>
</h:column>
This is my bean code:
public String saveTaskAsessment(ValueChangeEvent event) {
//does some things
return "Success";
}
The valueChangeListener doesn't run on the recently changed component only. In fact, you're using JavaScript submit() function to submit the entire form. The valueChangeListener will always be executed whenever the new selected value differs from the old value as is been declared in the value attribute.
You don't have declared a value attribute, so its default value is effectively null. If the default selected item of the list is not null, then the valueChangeListener will be invoked.
To fix this, you need to assign a value attribute to the component
<h:selectOneMenu value="#{careNeed.needsLevel}">
and you need to prefill it with the same value as the default value of the dropdown list.
this.needsLevel = "not_assessed";
Alternatively, you can also make the default value null.
<f:selectItem itemValue="${null}" itemLabel="----Not assessed----"/>
Unrelated to the problem, since you're already on JSF 2.0, I'd suggest to use <f:ajax> to submit only the recently changed dropdown by ajaxical powers instead of using onchange="submit()" to submit the entire form. That's after all better for user experience.
<h:selectOneMenu>
<f:ajax />
</h:selectOneMenu>
Also, the valueChangeListener method doesn't need to return anything. It will be ignored anyway. Just declare it void.
You can use AjaxSingle="true" and onsubmit="form.refresh();" on your ajax request.
So that it will process only the current component.
form.refresh(); will remove the old cache value.
You will get the refreshed bean value.

Resources