How to pass ajax event to client side callback in primefaces? - ajax

I am using Primefaces 10.0.0, and I am working with a data table that allows reordering of rows. I am trying to pass the reorder event in the client side callback when any reordering happens.
<p:ajax event="reorderRows" listener="#{bean.doSomething}" oncomplete=#{dothis(passTheReorderEvent)} />

Related

Primefaces slider <p:slider>: detect sliding

Is it possible to detect the event "while sliding" in a primefaces slider?
I have a poll (every 3 seconds the sliders are updated) to update the sliders' values (as multiple clients can use the slide).
When I am sliding and a periodic ajax call is made (by <p:poll>), the slider returns to its initial position. This behavior is understandable, because the form itself is refreshed.
I need to avoid this: when I'm sliding, I want the poll to stop. When I stop sliding the ajax event "slideEnd" is called. In this event, I would return the poll refresh process normally.
Is this possible? What would I need?
Edit: I found out about onSlide and onSlideStart attributes of <p:slider>. I used something like:
<p:slider for="porta2005" minValue="0.0" maxValue="100.0" step="1" styleClass="width-100" onSlide="#{dimmerBean.slideStart()}">
<p:ajax event="slideEnd" listener="#{dimmerBean.mudaTensao2005}" update="tensao2005"/>
</p:slider>
But the method slideStart() is called on every poll request inside bean, not only when I effectively slide. Is it wrong to call a bean method inside onSlide like this?
I am using Primefaces 6.1.
The onSlide, onSlideStart, and onSlideEnd are client side callbacks. So if a backing bean method is put in these attributes, it will be called during render, and not during the actual event.
From the documentation:
Name Default Type Description
onSlide null String Client side callback to execute during sliding.
And a little below this:
Client Side Callbacks
Slider provides three callbacks to hook-in your custom javascript, onSlideStart, onSlide and
onSlideEnd. All of these callbacks receive two parameters; slide event and the ui object containing
information about the event.
You can stop polling by using the poll widget functions. Suppose your p:poll has a widgetVar attribute as myPoll, you can pause it during sliding as shown.
<p:slider for="porta2005" minValue="0.0" maxValue="100.0" step="1" styleClass="width-100"
onSlideStart="PF('myPoll').stop()" onSlideEnd="PF('myPoll').start()">

Rerender all h:inputText fields with same id inside h:dataTable

I think I am wasting my time yet again figuring out how to do such a simple thing in JSF, but assuming the following set-up:
<h:form id="form">
<h:dataTable id="table">
<! -- not shown: other columns with other input fields -->
<h:column>
<h:inputText id="myinput">
<f:ajax execute="#this" render="????" listener="#{bean.action}" />
</h:inputText>
</h:column>
</h:dataTable>
</h:form>
What do I specify in the render tag to ONLY re-render all "myinput" components across all rows in the datatable, ie without specifying "#form" that will re-render the other components as well? I have tried #this and ":form:table:myinput", but it always just re-renders the very first row of the dataTable. It seems like this should be such a simple use-case, so I have to obviously be misunderstanding something.
Note: I don't know if internally JSF creates N HtmlInputTextComponents for each row or just 1, but obviously when I say "all myinput components", I mean all rendered input fields back to the browser that were generated from the h:inputText tag and that have the same browser DOM id of form:table:myinput:n.
As a corollary and additional question, I don't want to process or re-render the whole form components because of possible validation/conversion errors. I simply want the following to happen: only the initiating "myinput" component that triggered the ajax call is validated, and if success, all of the other "myinput" components are populated and subsequently re-rendered with new model values that were changed from the action listener "#{bean.action}".
Additional information:
I am currently using the mojarra implementation version of JSF 2.1 (I think). I would like to avoid any third party JSF libraries.
Bonus questions (which perhaps the answer to my original question would also answer):
How to re-render and/or execute all input components but only for a single row
How to re-render and/or execute set of input components but only for a single row
How to re-render and/or execute all input components for a set of rows (not all)
How to re-render and/or execute set of input components for a set of rows (not all)
To everyone replying that I can set the id of the inputText based upon the current rowIndex or current iteration variable - NO, that does not work. See: Set id of a component within JSF dataTable to value from current item in the array
I really think the only way to accomplish what I want is to abandon using a datatable and render the table columns/rpws with JSTL myself such that I can assign unique ids and have full control. However, I still think this is a huge design flaw in JSF to not support such a seemingly simple use-case.
What do I specify in the render tag to ONLY re-render all "myinput" components across all rows in the datatable, ie without specifying "#form" that will re-render the other components as well?
TL;DR: How do I re-render the entire column?
This is not possible using standard JSF facilities. You basically need to (auto)generate the collection of client IDs form:table:0:myinput, form:table:1:myinput, form:table:2:myinput, etc yourself based on row count/index, and manually add them all to the PartialViewContext#getRenderIds() collection during #{bean.action}. It's not possible to specify them in render attribute as those client IDs don't exist in JSF component tree, but JSF strictly wants to validate them (and you thus end up with confusing "cannot find client ID" exceptions).
I'm aware that you want to avoid 3rd party libraries, but OmniFaces Ajax#updateColumn() provides exactly this functionality which only takes the table component and the (zero-based) column index as arguments. E.g.
public void action() {
// ...
UIData table = Components.findComponent("form:table");
Ajax.updateColumn(table, 2); // Updates third column.
}
Feel free to borrow/steal/improve the source under Apache 2.0 license if the remainder of OmniFaces isn't sufficiently convenient to not anymore consider it as an "average" 3rd party library.
We have by the way a possible enhancement in the queue for a future OmniFaces release, which must make this kind of requirements more hair-friendly: event driven updates.
How to re-render and/or execute all input components but only for a single row?
How to re-render and/or execute set of input components but only for a single row?
You can specify them in render attribute using relative client IDs like so:
<h:column><h:inputText id="input1" ... /></h:column>
<h:column><h:inputText id="input2" ... /></h:column>
<h:column><h:inputText id="input3" ... /></h:column>
<h:column><h:inputText id="input4" ...><f:ajax render="input1 input2 input3" ... /></h:inputText></h:column>
Note: there's no way to explicitly say "all input components". You'd have to specify them individually. If you happen to use PrimeFaces, or are open to using it, then PrimeFaces Selectors would make this much easier. See also among others How do PrimeFaces Selectors as in update="#(.myClass)" work?
How to re-render and/or execute all input components for a set of rows (not all)
How to re-render and/or execute set of input components for a set of rows (not all)
Also here, no standard facility. You could extend on the aforementioned Ajax#updateColumn() source code. The key problem is that you wanted to update other rows as well than only the current row. For that you'd really need to (auto)generate full client IDs and add them to PartialViewContext#getRenderIds().
<h:form id="form">
<h:dataTable id="table" rowIndexVar="idx">
<! -- not shown: other columns with other input fields -->
<h:column>
<h:inputText id="myinput#{idx.index}">
<f:ajax execute="#this" render="????" listener="#{bean.action}" />
</h:inputText>
</h:column>
</h:dataTable>
</h:form>
using firebug, you can see that all your inputs have an id now. Now, you can put in your render what you want according to this id.
you must use
RequestContext.getCurrentInstance().update(lstIndex);
in your java code where lstIndex is the list of ids that you want to update

How to stop next ajax request until current one get completed?

Hi In my project I have input text box like following, where on "keyup" event I am making a call to managed bean where I perform searching operation in a arraylist.
That arraylist I show in p:dataTable which is named as userDataTable
My Code for xhtml
<p:inputText id="searchText" binding="#{searchText}"
value="#{userData.searchReq}" autocomplete="off">
<p:ajax listener="#{userManagement.userTable.searchListener}"
event="keyup" update="userDataTable/>
</p:inputText>
This basically gives user to perform filtering on table when he types in inputText. But problem is user can type very fast. I want to stop next ajax call until current ajax call completed. How I can achieve that?
Since you're already using Primefaces, you can use the AutoComplete component to perform exactly what you're ttrying to do. The first example shows a basic autocomplete functionality using arraylists.... you may refer that.
Autocomplete also has the feature of delaying your hit to the server to compensate for fast typing - the queryDelay attribute. Refer to the User Guide for complete details.

Should immediate="true" never be used when dealing with an AJAXified JSF 2.0 component?

Should immediate="true" never be used when dealing with an AJAXified JSF 2.0 component?
The example might be:
If I want to implement a "Cancel" button on JSF 2.0 page where if the user hits "Cancel", no validations should run, should I set immediate="true" on the component if it is an ajaxified component or should specify that no components on the form should be processed? If so, what is the way to implement this functionality using the AJAXified features of the component and not the "old way" of using immediate="true"?
Indeed, the purpose of using immediate="true" on a cancel button has become useless since <f:ajax> which you can just set to execute="#this" (which is the default already) to skip the processing of all input components in the same form.
You may only run into problems when the form was already been submitted beforehand but failed due to a conversion/validation failure. If you hit the cancel button by ajax and render the form thereafter, the inputs would still be marked invalid and any changes in the model value are not reflected (you're probably doing a entity = new Entity(); or something in cancel action method to clear out the old values of the form). This problem does not happen when using a synchronous (non-ajax) request with immediate="true". This issue has actually nothing to do with immediate="true", but with the JSF lifecycle of ajax requests. You basically need to reset the invalidated state of the involved input components by calling EditableValueHolder#resetValue() on the components which are not included in the ajax execute, but are included in the ajax render. OmniFaces has a ResetInputAjaxActionListener for exactly this purpose.

Event to sort by a column

I've a <p:datatable> with sortable columns. I would like obtaining the event when click on header in any column.
Any idea?
What Primefaces version?? Maybe it would be for the best to create two different primefaces tags (2 and 3)...
About your solution...you know that DataTable has built-in support for ajax sorting. Means that every sort would be an ajax request, so you could intercept this ajax call. A solution to do that would be to implement an ajax status component that on start, or on complete to call a javascript function or a server side method...
Here you can find the ajax status: http://www.primefaces.org/showcase-labs/ui/ajaxStatusHome.jsf

Resources