Call MangedBean using onSlide event instead of SlideEndEvent event - jsf

Currently we are using ajax slideEnd event and in backEndBean we are doing some % calculation
<h:outputText id="brightness" value="#{brightnessBean.brightnessLevelValue} %" />
<h:inputHidden id="brightnessLevel" value="#{brightnessBean.editingObj.brightnessLevel}" />
<p:slider for="brightnessLevel" minValue="0" maxValue="255" step="1" >
<p:ajax event="slideEnd" listener="#{brightnessBean.brightnessSildeEnd}" update="brightness"></p:ajax>
</p:slider>
Our backendBean is doing some percentage calculation using
public void brightnessSildeEnd(SlideEndEvent endEvent) {
brightnessLevelValue = (100 * endEvent.getValue()) / 255;
}
But now we want to do this using onSlide event but <p:ajax></p:ajax> is not supporting this event.
Please guide me the way we can display % when user uses slider instead of end of the slider.

Related

ADF popup cancel listener not invoked on closing dialog with error values

The issue is when I enter some negative value in the inputBox within the dialog component and the validator throws error something like "Negative numbers not allowed". The dialog now has an error input box marked with red border and I decide to click outside the dialog to close it and reset the input box, but the inputBox is not reset and if I press Esc key or Ok button then only the popupCanceledListener is called and the inputBox is reset. Below is the code which contains a popup with dialog and inputBox within it.
JSF code:
<af:popup contentDelivery="lazyUncached" autoCancel="enabled"
popupCanceledListener="#{pageFlowScope.testBean.handleResetPopup}"
childCreation="deferred" id="testPopup">
<af:dialog type="none" modal="false"
id="Dlg1">
<af:inputText label="DECIMAL PLACES"
columns="2"
validator="#{pageFlowScope.testBean.validateDecimalPlaceValue}"
value="#{pageFlowScope.testBean.decimalPlace}"
id="input1" autoSubmit="true"></af:inputText>
<f:facet name="acceptNFChange">
<af:commandButton text="OK" id="cb1"
actionListener="#{pageFlowScope.testBean.handleOkFromPopup}"
partialSubmit="true"></af:commandButton>
</f:facet>
</af:dialog>
</af:popup>
Bean code:
public void handleResetPopup(PopupCanceledEvent popupCanceledEvent) {
try {
UIComponent component = popupCanceledEvent.getComponent();
RichInputText inputText = (RichInputText)JSFUtil.findComponent(component, "input1");
inputText.resetValue();
} catch (Throwable th) {
this.handleException(th);
}
}
Problem: When clicking outside the dialog to close it and reset the inputbox, the popupCanceledListener is not invoked.
The best way is to use client listener with type popupClosed. Here is example for your code:
<af:popup contentDelivery="lazyUncached" autoCancel="enabled"
popupCanceledListener="#{pageFlowScope.testBean.handleResetPopup}"
childCreation="deferred" id="testPopup">
<af:dialog type="none" modal="false"
id="Dlg1">
<af:inputText label="DECIMAL PLACES"
columns="2"
validator="#{pageFlowScope.testBean.validateDecimalPlaceValue}"
value="#{pageFlowScope.testBean.decimalPlace}"
id="input1" autoSubmit="true"></af:inputText>
<f:facet name="acceptNFChange">
<af:commandButton text="OK" id="cb1"
actionListener="#{pageFlowScope.testBean.handleOkFromPopup}"
partialSubmit="true"></af:commandButton>
</f:facet>
</af:dialog>
<af:clientListener type="popupClosed" method="popupCloseClientListener"/>
<af:serverListener type="popupClosedEvent" method="#{pageFlowScope.testBean.handlePopupClosed}"/>
</af:popup>
then you need to write somewhere in JSF script:
<script>
function popupCloseClientListener(event) {
component = event.getSource();
AdfCustomEvent.queue(component,
"popupClosedEvent",
{payload:component.getSubmittedValue()},
true);
event.cancel();
}
</script> ]]>
In this way you can always correctly handle popup closed event from client. And implement all server logic you need.
The solution provided in this link https://community.oracle.com/thread/4112016 works fine for my scenario.

how to get selected records count in rich data table having multiple pages rich:datascroller

I am facing a problem where i want to test that whether a user has selected any record or not from the multiple page in rich:dataTable. These pages are created through rich:datascroller. Related code is given below.
<rich:datascroller id="dataScroller" selectedStyleClass="myClass" renderIfSinglePage="false"
align="center" for="dataList" maxPages="10"
pageIndexVar="currentPage" pagesVar="totalPages" reRender="pageNum,dataList" ajaxSingle="false">
<f:facet name="first"><h:outputText value="First" /></f:facet>
<f:facet name="last"><h:outputText value="Last" /></f:facet>
</rich:datascroller>
<h:inputHidden id="pageNum" value="#{currentPage}"></h:inputHidden>
<h:inputHidden id="numOfRows" value="10"></h:inputHidden>
The problem is that if user selects a record (say on 3rd page) and after that he moves to page one. Now in this case when i try to iterate through the table in Java Script to know that whether he has selected any record or not than it always allows me to iterate till the current page on which i am and hence i am unable to give user the proper alert message for selecting a record first on pressing of submit button. All i want is to know that user has checked the check box against a record on any page from the available pages , irrespective of the fact that on which page is currently opened. Any ideas?
Try it via the Richfaces Javascript API.
For every component you have in your page, there's a representing Javascript object, named as next:
Richfaces_componentId (small 'f' for faces).
Using that and to understand it live, go to the ScrollableDatatable Live Demo, open your chrome browser console, and execute this:
Richfaces_ScrollableGrid_j_id353_carList.selectionManager.selection.ranges
This will print out an empty javascript array.
Try selecting some rows, and running that line again, you'll have an array containing the indexes of your selected rows.
So to put that in a function:
<script>
function tableHasSelection() {
return Richfaces_ScrollableGrid_j_id353_carList.selectionManager.selection.ranges.length != 0;
}
</script>
Now you call this function via onclick of your submit button, and return false in case of no selection to prevent submission.
Of course you would replace Richfaces_ScrollableGrid_j_id353_carList with your component's javascript representing object.
Hopefully this will help.
[UPDATE]
According to our discussion in the comments, here is an update that might be helpful.
Your data table would be like this:
<rich:extendedDataTable value="..." var="element" id="table" selectionMode="..." selection="...">
<rich:column>
<h:selectBooleanCheckbox value="..." onclick="toggleSelection(this, #{element.id});" />
</rich:column>
</rich:extendedDataTable>
<h:commandButton value="Submit" action="#{...}" onclick="return tableHasSelection();" />
And your script would have these functions:
<script>
var selectedElements = [];
function toggleSelection(checkbox, id) {
if ($(checkbox).is(':checked')) {
//add selected row if checkbox is checked
selectedElements.push(id);
} else {
//or find it in the array and remove it
var index = selectedElements.indexOf(id);
if (index > -1) {
array.splice(index, 1);
}
}
}
function tableHasSelection() {
return selectedElements.length != 0;
}
</script>
(<rich:extendedDataTable> has selectable rows, you may want to look at that)
One thing you can do is to submit the selection when the user clicks it. E.g.
<h:selectBooleanCheckbox onclick="saveSelection(#{rowId})">
…
<a4j:jsFunction name="saveSelection">
<a4j:param name="id" assignTo="#{bean.selectedId}">
</a4j:jsFunction>
But if the user will only be choosing one row then simply say if the selected row is not on the current page the user didn't select anything, I don't think that's a wrong approach.

How to evaluate a FacesComponent property inside a custom component

Lately, I've been working on a dynamic form project but is stop with a custom component problem. What I have:
A faces component for formField:
#FacesComponent(value = "formField")
public class FormFieldCompositeComponent {
private boolean email;
}
A custom component jsf:
<o:validator for="email_text" validatorId="emailValidator" disabled="#{not cc.email}" />
OR
<c:if test="#{not cc.email}">
<f:validator for="email_text" validatorId="emailValidator"></f:validator>
</c:if>
OR
<f:validator disabled="#{not cc.email}" for="email_text" validatorId="emailValidator"></f:validator>
And the validator:
#FacesValidator("emailValidator")
public class EmailValidator implements Validator { }
My problems are:
1.) If I use an ordinary f:validator, like the one I use above and then use c:if to enable/disable it, then it will not work. According to some articles I've read it's because f:validator validates on build time, not on render time.
2.) If I use o:validator, it works but the problem is every time you hit submit a new line of invalid email error is added to p:messages. Example I clicked submit button 3 times, then I get 3 times the email error.
Any idea?
More info (anatomy of the project)
Example I have a page user with field email, it will include the following custom components:
+user.xhtml
+formPanel
+formField (this is where the validator is defined)
+formButtons (the action button)
+p:messages is defined
user.xhtml
<formPanel>
<formField field="email" />
<formButtons />
</formPanel>
Command button is like (formButtons):
<p:commandButton id="saveButton" rendered="#{cc.attrs.edit}"
value="#{messages['action.save']}"
action="#{cc.attrs.backingBean.saveOrUpdate()}" icon="ui-icon-check"
ajax="#{cc.attrs.ajaxSubmit}">
<c:if test="#{cc.attrs.backingBean.lcid != null}">
<f:param name="cid" value="#{cc.attrs.backingBean.lcid}" />
</c:if>
</p:commandButton>
The p:messages as defined on formPanel:
<p:messages id="formMessages" showDetail="true" showSummary="false" redisplay="false"></p:messages>
Note:
1.) What I've noticed is that the validator is called n times, where n is the number of submit or click done.
xhtml - https://github.com/czetsuya/crud-faces/blob/master/crud-faces/src/main/webapp/administration/user/user.xhtml
the tags - https://github.com/czetsuya/crud-faces/tree/master/crud-faces/src/main/webapp/resources/tags
bean component - https://github.com/czetsuya/crud-faces/tree/master/crud-faces/src/main/java/org/manaty/view/composite
Seems like there's no chance for the f:validator so I push through o:validator and come up with a workaround. Need to catch if the error is already in the FacesMessages list:
boolean match = false;
for (FacesMessage fm : context.getMessageList()) {
if (fm.getDetail().equals(message)
|| fm.getSummary().equals(message)) {
match = true;
break;
}
}
if (!match) {
throw new ValidatorException(facesMessage);
}

Reset value to null in primefaces autocomplete event

I have an autocomplete event that fires correctly once a value is selected. I want another event to fire once I erase the value in the textbox and reset the value to null. I was thinking of using the onChange attribute but I was having issues so I reverted back to my original code.
<p:autoComplete id="deviceAuto" dropdown="true" scrollHeight="250"
value="#{summaryReportController.device.nickname}"
forceSelection="true"
completeMethod="#{summaryReportController.deviceComplete}">
<p:ajax event="itemSelect"
listener="#{summaryReportController.handleDeviceSelect}"
update="printThis" />
</p:autoComplete>
public void handleDeviceSelect(SelectEvent event) {
String deviceSelect = event.getComponent().getId();
if (deviceSelect.equalsIgnoreCase("deviceAuto")) {
Device selectedDevice = deviceMgr.getDevicebyNickname(device.getNickname());
setDevice(selectedDevice);
}
updateInterface();
}
When you modify the text content of the AutoComplete textfield, the search method (aka. completeMethod) will be called on the backing bean. You can reset the value to null there if you get an empty string.
Backing Bean
// insert getter and setter for the device property ...
/** Search for devices by name */
public List<String> deviceComplete(String search) {
if (StringUtils.isBlank(search)) {
setDevice(null); // textfield was cleared, reset device value!
return Collections.emptyList();
} else {
// search for devices ...
return deviceNames;
}
}
Note that I used Apache Commons StringUtils.isBlank(String) to check if the string was null or did only contain whitespace characters.
JSF View
In your XHTML file you probably want to listen to any Ajax event to update your view -- or you figure out the event you need (blur, change, whatever) yourself:
<p:autoComplete ...>
<p:ajax event="itemSelect" listener="..." update="..." />
<p:ajax process="#this" update="..." />
</p:autocomplete>
I hope this helps.
An alternative could be something like a "clear" or "reset" button next to the search textfield to make it clear to the user that the value will be cleared.
The default autoComplete minQueryLength attribute equals 1 and your search string will be updated when you deleting it until it has lenght of 1 character.
E.g.:
You entering 'foo' - and this string is provided to search method (updating after entering first character - minQueryLength = 1)
But when you delete search string - it is also updated until it will have length of 1.
Solution:
set attribute minQueryLength="0"
Or:
if you need bigger value add to your autoCompleteMethod(String search) condition:
if (search.length()<={your minQueryLength attribute} ) field = null;
Old question, but I think it worths another view.
The problem with minQueryLenth = 0 or minQueryLenth = 1 is that it can return hundreds of options (and for sure the user won't read all of them to choose one). My solution was as follows.
First of all I need the input to be sent to the server as soon as the user select one of its values (in my use case the user is not allowed to go to next step in a wizard if this value is null or empty). So I put an ajax function triggered in the event of a selected value.
xhtml:
<p:autoComplete
id="someId"
value="#{myViewScopedBean.selectedValue}"
...
...
minQueryLenth="5"
onblur="autoCompleteLostFocus('someId', 'someCommand()')">
<p:ajax
event="itemSelect"
listener="#{myViewScopedBean.newValueSelected}"
process="#this"
update="commandButtonGoToNextStep" />
</p:autoComplete>
<p:remoteCommand
name="someCommand"
actionListener="#{myViewScopedBean.setValueNull}"
update="commandButtonGoToNextStep" />
<p:commandButton
id="commandButtonGoToNextStep"
...
...
disabled="#{myViewScopedBean.selectedValue == null}" />
If the user clean the text, I need to send that value to "myViewScopedBean" and update the component that allows the user to go to the next step. I solved that putting a javascript function that is called when the autocomplete lose focus.
javascript:
function autoCompleteLostFocus(autocompleteId, comand) {
if ($("[id='" + autocompleteId + "_input']").val().trim() == "") {
eval(comando);
}
}
in myViewScopedBean:
public void setValueNull() {
selectedValue = null;
}
I hope it helps. A lot of work, but the behaviour is exactly what I wanted. The reason for the javascript function is that it just send information to the servlet if the value is equals to "", otherwise it does nothing.
From a completely different angle...
Why do you have summaryReportController.device.nickname as a value in autoComplete?
I'd suggest you to use device as a value and specify
var
itemLabel
itemValue
converter
in your autocomplete, while your completeMethod will return list of devices filtered by nickname. Converter is implementation of javax.faces.convert.Converter.
See the POJO case in PF Showcase.

Rerendering show/hide trick with AJAX (JSF+richfaces) only work for first record in a4j:repeat

For a while now, I've been working on a JAVA-based web project, and have found this website to be very helpful on numerous occasions.
So, 'got some problems of my own now - and would appreciate if you help out!
Ok, so Here's the thing -
I'm trying to render a list of messages, each of which consists of a message title and a message body. The trick I'm working on is that the message body, for as long as the title (which is an a4j:commandLink) hasn't been clicked-on, should be hidden. And once the title's clicked - the body should be displayed. And once its clicked again - hide. And so forth.
Here's what I did at the JSF side (some parts have been omitted for simplicity):
<a4j:repeat var="msg" value="#{ForumRenderJSF.messages}">
<a4j:region id="msgAjaxRegion" renderRegionOnly="true">
<a4j:outputPanel id="msgPanel" ajaxRendered="true">
<rich:panel style="width: 100%; border: 0">
<a4j:form id="msgForm">
<!--
The message's title.
Each click results in either the revealing or hiding of the message's body.
-->
<a4j:commandLink value="#{msg.title}" action="#{ForumRenderAssistJSF.reevaluateRender}"/>
<h:outputText value=" By: <i>#{msg.userNick}</i>, #{msg.timestamp}" escape="false"/>
<!--
The message's body.
-->
<!-- A (textual) flag, indicating whether the body should be rendered. -->
<h:inputText id="renderBodyFlag"/>
<br/>
<!-- The body. -->
<a4j:outputPanel rendered="#{rich:findComponent('renderBodyFlag').value == true}">
<h:outputText value="#{msg.body}"/>
</a4j:outputPanel>
</a4j:form>
</rich:panel>
</a4j:outputPanel> <!-- msgPanel -->
</a4j:region>
</a4j:repeat>
Note the usage of:
1. A dummy "renderFlag" field (should be hidden, eventually), which value denotes whether the body should be rendered.
2. A backing bean for rendering assistance (ForumRenderAssistJSF); It goal is to flip the proper renderFlag's value from "true" to "false", and vice-versa.
3. An a4j:region to isolate each message when firing the request for ForumRenderAssistJSF.reevaluateRender() -- so that the bean can find the right "renderFlag" field.
As for the bean:
public class ForumRenderAssistJSF {
public void reevaluateRender()
{
FacesContext context = FacesContext.getCurrentInstance();
UIViewRoot root = context.getViewRoot();
UIComponent renderFlagComp = (new UIComponentLookup()).lookup(root, compLookup); // My recursive search
String renderFlagVal = (String) ((HtmlInputText)renderFlagComp).getValue();
if (!renderFlagVal.equals("true"))
{
((HtmlInputText)renderFlagComp).setValue("true");
}
else
{
((HtmlInputText)renderFlagComp).setValue("false");
}
}
}
AND THE PROBLEM IS:
The trick actually works -- but only for the first message in the list!
For the rest of them, I see that the server can reach the right renderFlag input-text component (tested by inserting values at the client), but for some reason - the client always renders it blank (no content) upon AJAX reply!
I tried digging deep inside richfaces tutorials and manuals, and to me it seems like everything is as it should be. So, I'm kind'a lost here, and as I said - would deeply appreciate your help in regards!
Thanks!
Have you tried using a rich:simpleTogglePanel? It seems to provide all the functionality you need.

Resources