Request update of component with ajax from LazyDataModel.load? - jsf

I'm using PrimeFaces version 3.5.
I want to implement the message informing that the filter in the DataTable have return too many rows and only first 50 will be displayed.
I've tried to do it with both Messages and outputText. I set the text to display and request update:
RequestContext context = RequestContext.getCurrentInstance();
context.update("form:message");
context.update("form:text");
message = "Too many rows";
The components:
<p:message id="message" for="message"/>
<h:outputText id="text" value="#{userPicker.model.message}"/>
However, I don's see the proper update sections in partial-request response. Is it possible to request the update of components from within the LazyDataModel.load function (and if, what I'm doing wrong here)? If it is not possible (why?) how else can I force refresh of element from DataTable filtering?

The load method of LazyDataModel is invoked in render phase, when it's too late to add additional components to update.
However, it is possible to add JavaScript execution command:
context.execute("show_message()");
Where function show_message will display the message on client side, which enables to accomplish the task with single request.

Related

Using ajax status for single ajax request in primefaces

I am sending multiple ajax request in PrimeFaces. I have used <p:ajaxStatus /> component to show loading dialog. I am performing CRUD operation in PrimeFaces. So all CRUD operations are using ajax request. So whenever i am performing any CRUD operation loading dialog is shown. Where as i just want to show Loading dialog only for DELETE operation.
So is there any way that i can prevent ajax status for a particular request?
Think the other way around…
"How can I show a dialog when a command starts and hide it when it end"
The answer is very simple then. Use the onstart and oncomplete attributes of the single commandbutton to show/hide a specific dialog. You can customize that one specific dialog in any way you want.
You can also use a p:blockUI as correctly stated in the comments
The ajaxstatus is a kind of optimization if you want it for all requests. In this case you want it for one request. So don't use the onstart and oncomplete of an ajaxstatus then.

jsf get disabled field values in requestscoped bean

Could you please give me some directions on how to pass values from disabled or readonly input fields in xhtml page to requestscoped bean?
I thought that I can bypass jsf checking the field state by disabling
fields in javascipt code on form open and then submit form, but that
did not help too.
I cannot use view scope, because I would have to set then almost
every page in my application in view scope.
It is very inconvenient to use hidden fields for this purpose,
because it would double the number of fields on the page.
Maybe I have missed some clean solution?
Thank you in advance for any help.
Disabling fields using JavaScript didn't work probably because you didn't enable them just before sending a form. Values of disabled fields are not sent (see input documentation).
For example the following code works perfectly well:
<h:form>
<h:inputText id="disabledinput" styleClass="disabled"
value="#{someBean.property}"></h:inputText>
<h:outputScript>
$('.disabled').attr('disabled', 'disabled');
</h:outputScript>
<h:commandButton action="#{someBean.action}"
onclick="$('.disabled').removeAttr('disabled'); return true;"
value="Submit" />
</h:form>
onclick attribute executes JavaScript code that enables input just before sending the form.
If you use AJAX request you have to restore disabled state using oncomplete or similar.
The problem with this solution is that user can manipulate the value. E.g. she/he can use javascript console in a browser to change the input to enabled or use some tool (e.g. curl) to prepare or tamper request. So if the value is sensitive or should never be changed by the user consider storing the value in the session.
IMHO if the value was provided by the user in one of the previous steps then it doesn't matter that much. However, if value is calculated (like total value or something) you should not depend on its value as users could change it. Personally I would prefer to store the value on server side (in session or in flash).

Pure Java/JSF implementation for double submit prevention

We're using JSF 2.0 on WebSphere v8.5 with several component libraries PrimeFaces 4.0, Tomahawk 2.0, RichFaces, etc.
I am looking for generic mechanism to avoid form re-submission when the page is refreshed, or when the submit button is clicked once again. I have many applications with different scenarios.
For now I have considered disabling the button with a piece of JavaScript in onclick attribute, but this is not satisfying. I'm looking for a pure Java implementation for this purpose, something like the Struts2 <s:token>.
I am looking for generic mechanism to avoid form re-submission when the page is refreshed
For that there are at least 2 solutions which can not be combined:
Perform a redirect after synchronous post. This way the refresh would only re-execute the redirected GET request instead of the initial request. Disadvantage: you can't make use of the request scope anymore to provide any feedback to the enduser. JSF 2.0 has solved this by offering the new flash scope. See also How to show faces message in the redirected page.
Perform the POST asynchronously in the background (using ajax). This way the refresh would only re-execute the initial GET request which opened the form. You only need to make sure that those forms are initially opened by a GET request only, i.e. you should never perform page-to-page navigation by POST (which is at its own already a bad design anyway). See also When should I use h:outputLink instead of h:commandLink?
or when the submit button is clicked once again
For that there are basically also at least 2 solutions, which could if necessary be combined:
Just block the enduser from being able to press the submit button during the submit and/or after successful submit. There are various ways for this, all depending on the concrete functional and design requirements. You can use JavaScript to disable the button during submit. You can use JSF's disabled or rendered attributes to disable or hide the button after submit. See also How to do double-click prevention in JSF 2. You can also use an overlay window during processing ajax requests to block any enduser interaction. PrimeFaces has <p:blockUI> for the purpose.
Validate uniqueness of the newly added entity in the server side. This is way much more robust if you absolutely want to avoid duplication for technical reasons rather than for functional reasons. It's fairly simple: put a UNIQUE constraint on the DB column in question. If this constraint is violated, then the DB (and DB interaction framework like JPA) will throw a constraint violation exception. This is best to be done in combination with a custom JSF validator which validates the input beforehand by performing a SELECT on exactly that column and checking if no record is returned. A JSF validator allows you to display the problem in flavor of a friendly faces message. See also among others Validate email format and uniqueness against DB.
Instead of creating a token manually, you can use BalusC' solution. He proposed a Post-Redirect-GET pattern in his blog
Alternative solutions can be found in these answers:
Simple flow management in Post-Redirect-Get pattern
How can Flash scope help in implementing the PostRedirectGet (PRG) pattern in JSF2.0
<!--Tag to show message given by bean class -->
<p:growl id="messages" />
<h:form>
<h:inputText a:placeholder="Enter Parent Organization Id" id="parent_org_id" value="#{orgMaster.parentOrganization}" requiredMessage="Parent org-id is required" />
<h:commandButton style="margin-bottom:8px;margin-top:5px;" class="btn btn-success btn-block " value="Save" type="submit" action="#{orgMaster.save}" onclick="resetform()" />
</h:form>
public String save() {
FacesContext context = FacesContext.getCurrentInstance();
context.getExternalContext().getFlash().setKeepMessages(true); //This keeps the message even on reloading of page
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Your submission is successful.", " ")); // To show the message on clicking of submit button
return "organizationMaster?faces-redirect=true"; // to reload the page with resetting of all fields of the form.. here my page name is organizationMaster...you can write the name of form whose firlds you want to reset on submission
}

Primefaces datatable custom pagination not updating

I am working on an application where we have our older code base (Struts 1) and are now building out a newer code base using JSF to run alongside the rest of the (old) application. The older datatables that we have across our application show the following for pagination:
"Showing 1 to 20 of 50 entries"
I have been tasked with getting the new PF datatable to display the same way.
I was able to get this working for the first page by overriding the encodePaginatorMarkup method of the primefaces DataRenderer class. The problem comes when the page is changed - this method is not being called to update the pagination. This is confusing to me because the current page (and everything else) gets updated in the normal pagination template without this method getting called.
I looked at the AJAX response being sent back when changing pages and don't see any HTML generated for updating the pagination (only the total count). This leads me to believe that everything is being handled in JS.
The way I'm currently thinking of implementing it would be to use an f:ajax for changing the page, and in the oncomplete pass the widgetVar value for the table and have a common method that will update the pagination based on properties of that datatable in JS. This seems like overkill and I don't want to over-complicate the code if I don't have to.
Is there any better way to go about this? Does anyone have any other suggestions?
Well since there is no other input I went ahead and implemented it using the page event:
<p:dataTable id="users" widgetVar="userTable" paginator="true" rows="20" sortBy="userId">
<p:ajax event="page" oncomplete="setTimeout(function() { update_pagination('userTable'); }, 0)" />
...
</p:dataTable>
The setTimeout was required because the JS object was still not updated when called from oncomplete - so I bumped it into the next event loop, where the values are up-to-date.
Here is the update_pagination JS function:
function update_pagination(table) {
table = PF(table);
var paginator = table.cfg.paginator;
var $pageStart = $(table.jq).find('.paginator_pagestart');
var $pageEnd = $(table.jq).find('.paginator_pageend');
$pageStart.html(paginator.page*paginator.rows+1);
$pageEnd.html(Math.min(paginator.rowCount, paginator.page*paginator.rows+paginator.rows));
}
I pass it the table name, grab the actual PF object and then use the paginator part of the cfg to update the current entries being shown. I use Math.min because on the last page it might not have enough data, and I didn't want it reading "Showing 1 to 20 of 7 entries", but rather "Showing 1 to 7 of 7 entries"

SelectManyCheckbox onHide with remoteCommand

I ran into a very interesting issue. Here is my scenario:
My Goal
Use a SelectManyCheckbox with a nested tooltip.
Use SelectManyCheckbox onHide event to fire an Ajax (ActionListener) call
and update the
SelectManyCheckbox label and nested tooltip text.
My Approach
Use a remoteCommand and tie it to the SelectManyCheckbox onHide event
XHTML
<p:selectCheckboxMenu id="sourceFilter"
onHide="sourceFilterCommand();"
value="#{viewRevenueBean.sourceSelectManyMenu.selectedValues}"
label="#{viewRevenueBean.sourceSelectManyMenu.label}"
filter="true" filterMatchMode="contains"
validator="#{viewRevenueBean.sourceSelectManyMenu.validate}"
widgetVar="srcFilterDropDown">
<f:selectItems id="sourceItems"
value="#{viewRevenueBean.sourceSelectManyMenu.availableItems}"
var="source" itemLabel="#{source.label}" itemValue="#{source.value}" />
<f:convertNumber type="number" />
<p:tooltip id="srcToolTip"
for="sourceFilter"
value="#{viewRevenueBean.sourceSelectManyMenu.tooltipText}"
showEffect="fade"
hideEffect="fade"/>
<p:remoteCommand name="sourceFilterCommand" update="sourceFilter"
actionListener=#{viewRevenueBean.sourceSelectManyMenu.defaultEventHandler}"/>
</p:selectCheckboxMenu>
My Results
Ajax (Action Listener) gets fired and SelectManyCheckbox label and nested tooltip are updated (expected behavior).
In Firebug, I noticed that each onHide event Ajax call is multiplying the preceding number of server side requests by two (unexpected behavior).
e.g
1st onHide event = 1 Request
2nd onHide event = 2 Requests
3rd onHide event = 4 Requests
4th onHide event = 8 Requests
5th onHide event = 16 Requests
etc.....
This is obviously not desired and leads to a big slow down after just
a couple onHide events.
Experiments I tried
I created a p:command button which accomplished the desired Ajax call and correct element updates (without the multiplied request
issue) . I then proceeded to steal it's Ajax JavaScript call via
Firebug and placed it in my own JavaScript function, which I then
used as my onHide callback. Again, I experience the same unwanted
result, the label and tooltip are updated, but the requests start to
multiply.
I tried placing the remoteCommand in different locations
(outside the menu, inside it's own form etc). It doesn't make a
difference. The problem is still encountered.
I tried simplifying the SelectManyCheckbox scenario (remove
tooltip, coverter, tweak various attributes etc) to eliminate other
possibilities. No difference.
I tried a p:ajax instead of p:remoteCommand using onchange.
The Ajax requests work fine but obviously it's not what I am after.
I need to trigger it onHide.
Instead of a SelectCheckboxMenu , i tried using a
SelectManyCheckbox (no label) with onchange and keeping everything
else the same. The remoteCommand works fine, the Ajax call gets
called once and everything is nice and dandy. [/list] [list] * I
tried the PrimeFaces 3.5-SNAPSHOT as well. No difference. Issue is
still manifested.
Haven't found any clues on the forum or the net thus far in regards
to this issue. Does this sound like a bug or programmer clumsiness
:roll: ? Of course any insight and/or suggestions are highly
appreciated.
I have run into similar problems when using p:remoteCommand. I can't say for sure that the root cause is the same in your case, but maybe this can help somewhat.
In my case the problem was caused by multiplied registering of jquery bindings; the p:remoteCommand seem not to use $(somesource).off("some_event").on("some_event", some_function). That means - as far as I have understood - that if you update the component containing the p:remoteCommand, it's action will be registered over and over again, each time it's being updated. That in turn will mean that if you call on the name of the p:remoteCommand, it will fire the same amount of times as it's been registered.
You said you'd tried to move it outside and still got the same problem, so maybe it's not this problem after all. In my case I tested this assumption using a p:commandLink instead and had that call the backing bean. The goal for me was to make sure that any previous registration of a binding was removed, so through registering the binding like mentioned above:
$(somesource).off("some_event").on("some_event", some_function), and let some_function click the link, you can at least check if it solves the problem.

Resources