JSF Live search with primefaces - jsf

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.

Related

Primefaces Data Table actionListener for inline cell editing

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

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

Disable and empty an input field after an AJAX call using JSF and Richfaces

I am using richfaces 4.2.0.Final and have the following situation: within a rich:dataTable, in which each row describes an article in a shopping cart, I have an input field
in which the user can input the quantity she wants to order. As soon as the user focuses on this input field, I have to perform some controls on the server (using Ajax) and if
the controls fail, I must empty the field and disable it.
My solution:
<rich:dataTable var="article" value="#{cart.articles} >
...
<rich:column>
<h:panelGroup id="orderQty">
<h:inputText id="qtyInput" value="#{article.qty}" disabled="#{article.controlsFailed}">
<a4j:ajax event="focus" bypassUpdates="true"
listener="#{requestBean.doAjaxControls(article)}"
execute="#this" render="qtyInput " />
</h:inputText>
</h:panelGroup>
#RequestScoped
#Named
public class RequestBean{
public void doAjaxControls(Article article){
boolean everyThingOK = doControls();//....
if (!everyThingOK){
article.setControlsFailed(true);
article.setQty(null);
} else {
article.setControlsFailed(false);
}
}
}
Before coming to this solution I tried several other combinations of execute/render, without succeeding in what I need (for example, I tried to use execute="#none" as I don't want
the value of qty to be updated on the server when I perform the ajax call, but this won't work).
My problem is I know this solution is not perfect: when I focus on a position for which the control will fail, and I am faster to type in a quantity than the server performing the controls, the field will be disabled and the server value for article#qty still set to null, but I will see the value I typed in until the next rendering of qtyInput will happen.
More strangely, if I execute this code on JBoss EAP 6.0.0.GA (AS 7.1.2.Final-redhat-1, which includes the module jboss-jsf-api_2.1_spec-2.0.2.Final-redhat-1),
every quantity typed in before doAjaxControls() is done will be cleared: this strange behaviour is fortunately not present with JBoss EAP 6.0.1.GA (AS 7.1.3.Final-redhat-4, jboss-jsf-api_2.1_spec-2.0.7.Final-redhat-1).
Do you know if/how could I improve my solution?
Thanks in advance for helping!

Why does p:resetInput require properties of a managed bean to be set to null first after the form is submitted?

In a view scoped managed bean, I'm using <p:resetInput> to clear the values held by the properties in the corresponding manged bean like,
<p:commandButton value="Reset" update="panel" process="#this">
<p:resetInput target="panel" />
</p:commandButton>
This works fine.
I have a submit button <p:commandButton> which when pressed causes the submitted values to be inserted into the database, if validation succeeds.
<p:remoteCommand name="updateTable" update="dataTable"/>
<p:panel id="panel" header="New">
<p:outputLabel for="property1" value="property1"/>
<p:inputText id="property1" value="#{bean.property1}" required="true">
<f:validateLength minimum="2" maximum="100"/>
</p:inputText>
<p:message for="property1" showSummary="false"/>
<p:commandButton id="btnSubmit"
update="panel messages"
oncomplete="if(!args.validationFailed) {updateTable();}"
actionListener="#{bean.insert}"
value="Save"/>
<p:commandButton value="Reset" update="panel" process="#this">
<p:resetInput target="panel" />
</p:commandButton>
</p:panel>
The command button invokes the insert() method in the managed bean which is defined as follows.
public void insert() {
if (service.insert(property1)) {
//...Popup a success message.
reset(); //Invoke the following private method.
} else {
//...Show the cause of the failure.
}
}
private void reset() {
property1 = null; //Set this property of type String to null.
}
If this reset() method is omitted, then <p:inputText> will not be cleared as obvious but then if I press the reset button as shown in XHTML, <p:inputText> should be cleared but it doesn't.
The showcase example demonstrates exactly the same thing. Therefore, this behaviour appears to be documented but I don't understand why doesn't <p:resetInut> clear the value of property1, if the reset() method is omitted, in this case?
The <p:resetInput> does not clear the model values as you incorrectly seemed to expect. It just clears the input component's state which may be dirty after a validation error.
The concrete problem it is trying to solve is in detail described in this answer: How can I populate a text field using PrimeFaces AJAX after validation errors occur?
This is the best understood by the following use case:
You have a single view with a single datatable and a single dialog which displays the currently selected record for editing.
You open the dialog and submits its form with invalid values. The input components are marked invalid and highlighted red.
You close the dialog without fixing the errors.
Then you select same or another row for editing. The dialog shows up, but the input components are still marked invalid and highlighted red and show the old submitted value -if any- because it's still the same view state you're working with.
Putting <p:resetInput> with target on dialog's form in the "open dialog" button fixes it.
I'm not sure if your particular case is the right use case for which <p:resetInput> is the right solution. Your code is not complete and you didn't state the concrete functional requirement behind this code anywhere, but as far as I see, there are no multiple inputs/forms which need to update each other. I believe that your case would still work even if you remove <p:resetInput>. So it would be totally superflous in your context and you could just get away with clearing the model (or.. just with refreshing the page by a synchronous GET button which implicitly recreates the view).
See also:
PrimeFaces CommandButton that Doesn't Process Data
Escape a primefaces/jsf page that has required fields

JSF/Richfaces/A4j ==> component/field conversion and reRendering problem

I have an input field in a JSF Page like the following (maps to BigDecimal on backing bean)
<h:inputText disabled="#{volumeBean.grossVolumeDisabled}" id="grossVolume" size="10" validateOnExit="true" value="#{volumeBean.enteredGrossVolume}" >
<a4j:support ajaxSingle="true" event="onblur" ignoreDupResponses="true" oncomplete="checkFieldValidation(this)" onsubmit="updateDirty()"/>
</h:inputText>
And an a4j:commandButton to "refresh" all the data from the database on the page:
<a4j:commandButton accesskey="T" action="#{volumeBean.revert}" button-type="ajax" disabled="#{volumeBean.revertDisabled}" id="volumeBean_reset" immediate="true" reRender="volumesTable" value="#{msg.button_RESET}"/>
Here are the steps to reproduce my problem:
And please note that the error occurs regardless of whether there is a reRender attribute set on the a4j:support
Here are the steps to reproduce - just to clarify further:
navigate to the screen where the BigDecimal input field exists
type aa into the field (should be a number but put non-numeric characters purposely)
tab off the field
notice that an error is reported 'aa' is not a valid netVolume
click on the RESET button
all of the changed fields have their original values EXCEPT those that have non-numeric data entered
unless the user manually deletes the non-numeric data in the fields or refreshes the entire screen, the "bad data" sticks
When you do a reset, you fire an Ajax request, the entire form is submitted and you get validation error again. So the field still has the old (incorrect) value.
Try adding the parameter ajaxSingle="true" to the button. I've found that immediate="true" is not adequate for bypassing validation on ajax components.

Resources