Reset value to null in primefaces autocomplete event - jsf

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.

Related

JSF PrimeFaces rendering components

Let's say I have a simple method that, like this:
public String test()
{
return "hello";
}
Now let's say I have the following PrimeFace component:
<p:fieldset styleClass="containers" rendered="#{controller.test()}">
<h2>Testing</h2>
<p:outputLabel for="test" value="Test" />
<p:inputText id="test" />
</p:fieldset>
The method above returns "hello". I would like to dynamically show and hide that fieldSet by comparing the returned value of that method to a field of one of my beans. For instance, on the rendered parameter, I would like to do something like: controller.test() != "some variable" which would return true or false. Am I allow to do that? If not, what is the way of doing it?
Basically the goal is to dynamically show and hide some container by comparing the returned value of a method with a bean property.
Look Like you misunderstood rendered
The rendered Attribute
A component tag uses a Boolean EL expression, along with the rendered
attribute, to determine whether or not the component will be rendered.
If you will check above definition you will know what exactly is the use of this attribute.
More you can see below
The rendered attribute which uses Boolean EL expression indicates
whether a component is currently visible or not. The property is
useful when you want to hide components for specific users or based on
condition. The default value of rendered attribute is true.
<h:outputText value=”mapping” rendered=”Boolean EL expression” />
For example, the commandLink component in the following section of a page is not rendered if the cart contains no items:
<h:commandLink id="check"
...
rendered="#{cart.numberOfItems > 0}">
<h:outputText
value="#{bundle.CartCheck}"/>
</h:commandLink>
With your concrete problem you can do like this
Make a String variable call value
Now create get/set methods for above variable
Now in your test method you can add
public void test(){
value="hello";
}
Bur remember you have call test() method of page load
Now in your Xhtml or Jsf or Jsp page
rendered="#{controller.value != 'hello'}"
Or better way create a Boolean variable and do all the magic of hide and show the component

Call an action listener via ajax when user presses enter on a h:form input field

I have this form
<h:form id="formId" prependId="false">
Descrizione <h:inputTextvalue="#{bean.description}" />
Prezzo: <h:inputText value="#{optionalManaged.price}" />
<a4j:commandLink styleClass="button smallButton" actionListener="#{bean.method}"
execute="formId" render="otherDiv">
+
</a4j:commandLink>
</h:form>
At the moment, pressing the a4j:commandLink stores the two input filelds' values inside my bean and calls my action listener correctly.
What I'd like to happen is that pressing enter on the second inputText does the same.
I made a naive try by calling the a4j:commandLink click() via jquery from inside the inputText. This, obviously, didn't work.
Any idea on how I could do this?
You need to detect if Enter key was pressed and click the command link programmatically. Just don't forget to set its id, as well as id of input component. The piece of JavaScript you need to add when the page has finished loading is:
document.getElementById('input').onkeypress = function(e) {
var event = e || window.event;
var code = event.which || event.keyCode;
if (code == 13) {
document.getElementById('link').click();
return false;
}
}

Using JSF Validator

I am using Prime faces 3.4.1 as component framework and JSF 2.0 as the server side framework
Following is my requirement
1) I have a field with label as "Meeting Required". Then I have SelectOneRadio with two options "No" and "Yes" with default value as "No". I am using JSF/HTML component h:SelectOneRadio.
2) I have another field which is Calendar component and this is a primefaces calendar component. When the user selects "Yes" which indicates the "Meeting is required" and the user should select a date from the calendar control.
3) If the user selects "Yes" and does not select a date, then a Validation message should be displayed indicating that the date should be selected.
I created a Custom Validation component and attached to the SelectOneRadio and I am able to see the selected value in the Custom validator. Now, I try to get the value from the Calendar component to check if the value is empty, through UIComponent.getParent().findCompoent("rvmDate"), I get the component but I do not know how to check if the date component is empty or contain any values.
Please help me out to get the date value selected by the user.
Please help me out to resolve the issue. Or is there any other way? Please find the source code.
XHTML Page
<h:selectOneRadio id="rvmMeetingOption"
readonly="#{wipMB.rvmMeetingOptionReadOnly}"
value="#{wipMB.requirementsMeeting}"
disabled="#{wipMB.rvmMeetingOptionDisabled}"
validator="#{wipMB.validateRVMDate}"
validatorMessage="Please enter RVM Date>
<f:selectItem itemLabel="No" itemValue="0"></f:selectItem>
<f:selectItem itemLabel="Yes" itemValue="1" ></f:selectItem>
<f:attribute value="#{rvmDateComp}" name="rvmDateComp"></f:attribute>
</h:selectOneRadio>
<p:calendar id="rvmDate"
readonly="#{wipMB.rvmMeetingDateReadOnly}"
disabled="#{wipMB.rvmMeetingDateDisabled}"
readonlyInput="true"
navigator="true" mode="popup"
pattern="dd/MM/yyyy"
value="#{wipMB.rvmDate}"
effect="explode"
yearRange="1900:2500"
style="margin-left:5px"
binding="#{rvmDateComp}"
</p:calendar>
<p:message id="rvmDateMsg" for="rvmDate" display="both" ></p:message>
Custom Validator
public void validateRVMDate(FacesContext context, UIComponent component, Object value)
throws ValidatorException
{
String invalidDate;
String rvmOption;
Date rvmDate;
String rvmDt = "";
try
{
FacesContext fc = FacesContext.getCurrentInstance();
rvmOption = value.toString();
DateFormat formatter = new SimpleDateFormat("E MMM dd HH:mm:ss Z yyyy");
UIInput rvmCompDt = (UIInput)component.getAttributes().get("rvmDateComp");
rvmDateId = rvmCompDt.getId();
rvmDt = rvmCompDt.getSubmittedValue() == null ? "" : rvmCompDt.getSubmittedValue().toString();
if (rvmOption.equals("1") && rvmDt.isEmpty())
{
FacesMessage msg = new FacesMessage("RVM date is required");
msg.setSeverity(FacesMessage.SEVERITY_ERROR);
fc.addMessage("rvmDateMsg", msg);
throw new ValidatorException(msg);
}
}
catch (Exception ex)
{
String msg = ex.getMessage();
}
}
In JSF each component is a little MVC stack of its own; there is the Model (stored as value), the Controller (the component object) and View (renderer). Validators and controllers are part of the architecture and are needed to move the values between the model and the view.
While JSF Validators play an important role, it is important only INSIDE this little MVC stack. They were not designed to "validate forms", they are made strictly to "validate component value". Lamentably, the name "validator" makes everyone who comes to JSF think, that each time any validating needs to be done, validator is the solution. Strangely, converters are not so abused.
In your case, building a custom validator created a strange situation, where:
validator and view have a cyclic dependency on each other,
there is a need to use hacks (such as "immediate") and low-level APIs,
hard-coding view logic in an unlikely place,
requires much more knowledge and is flaky. For example the logic of acquiring value from calendar might be different depending on whether radio button is before or after calendar in document order.
The problems above could be solved, but since they all arise from abusing JSF architecture, I think it would be better to rethink the problem. Since your validation concerns flow of application, it is a perfect fit for the action method, where all the complications will dissolve into a single, simple "if" statement with a conditional "addMessage".
You first need to remove immediate="true" from the <p:calendar>, otherwise it's not processed at all when the radio button is processed.
Then, to check if a string is null or empty, just do
String dt = (String) uiCalendar.getSubmittedValue();
if (dt == null || dt.isEmpty()) {
// dt is null or empty. Throw validator exception depending on the
// current radio button value. Note: you should not catch it yourself!
}
Note that this has nothing to do with JSF. It's just basic Java. Your initial attempt as if (dt == "") is indeed completely invalid. The String is an object, not a primitive. The == compares objects by reference, not by their internal value. Technically, you should have used if (dt.equals("")) instead, but the isEmpty() is nicer.
Unrelated to the concrete problem, a much easier way is to just check the radio button value in the required attribute of the calendar component. First bind the radio button component via binding to a variable in the view, then reference its UIInput#getValue() method in the required attribute.
<h:selectOneRadio id="rvmMeetingOption" binding="#{rvmMeetingOption}"
readonly="#{wipMB.rvmMeetingOptionReadOnly}"
value="#{wipMB.requirementsMeeting}"
disabled="#{wipMB.rvmMeetingOptionDisabled}">
<f:selectItem itemLabel="No" itemValue="0"></f:selectItem>
<f:selectItem itemLabel="Yes" itemValue="1" ></f:selectItem>
</h:selectOneRadio>
<p:calendar id="rvmDate"
readonly="#{wipMB.rvmMeetingDateReadOnly}"
disabled="#{wipMB.rvmMeetingDateDisabled}"
readonlyInput="true"
navigator="true" mode="popup"
pattern="dd/MM/yyyy"
value="#{wipMB.rvmDate}"
effect="explode"
yearRange="1900:2500"
style="margin-left:5px"
required="#{rvmMeetingOption.value == 1}">
</p:calendar>
use
UIInput uiCalendar = (UIInput) component.getParent().findComponent("rvmDate");
Date test = uiCalendar.getValue();
if(test==null){
throw ValidatorException
}
test will then have the date filled in or will be null when nothing is chosen in teh date field

how to disable multiple h:inputtext fields in JSF

In my home page(.xhtml),I'm having 4 h:inputText box and one serach button(h:commandButton)in JSF page
<h:inputText id="stlID" value="#{searchSettlementTransRequest.stlmtTransId}" name='stlmt'>
<h:inputText id="pmtID" value="#{searchSettlementTransRequest.pmtTransId}" name='pmt'>
<h:inputText id="AgentID" value="#{searchSettlementTransRequest.AgentId}" name='agnt'>
<h:inputText id="AgencyID" value="#{searchSettlementTransRequest.AgencyId}" name='agncy'>
<h:commandButton id="tranSearchBtn" styleClass="valign first button-search sSearch" action="stlmtSubmit"/>
My requirement is:
on entered data in 1st input field the other input fields should be disabled(ie. 2,3,4).
on entered data in 2nd input field the other input fields should be disabled(ie. 1,3,4). and so on..
Note: at the sametime if user entered data in 1st or 2nd or 3rd or 4th (user dynamic)field and delete the same before leaving out the input field in such case all field should be enabled.
When i get response back(empty or non-empty data response) after clicking "search" button now all the input fields should be enabled for another search(now user may input data in any of the 4 fields)
If you want the inputs to be enabled after each page load you can have a flag representing the page is loaded and set that flag to false after each ajax request through an listener. And to ensure that the flag is set to true after complete page loads you can use preRenderView event. You just need a method to be executed for preRenderView event which set the flag to true if the page is loaded through complete request rather than an ajax request. If the page is loaded with ajax request, faces-request parameter will be set to "partial/ajax".
public static final String INITIAL_VALUE = ""; // I assume your fields are integer and they are initialized to INITIAL_VALUE in the first place
public Boolean pageIsLoadedWithFullRequest = true;
public void preRenderView()
{
//check whether the request is an ajax request or not
Map<String, String> requestHeaderMap = FacesContext.getCurrentInstance().getExternalContext().getRequestHeaderMap();
if(!"partial/ajax".equals(requestHeaderMap.get("faces-request")))
{
pageIsLoadedWithFullRequest = true;
}
And if you want to disable other inputs whenever the user writes into one of the fields, you can make an ajax call after a blur event to change the state of other input fields and set the pageIsLoadedWithFullRequest flag to false in a listener.
public void madeAjaxRequest()
{
pageIsLoadedWithFullRequest = false;
}
public Boolean getStlIDEnabled()
{
return pageIsLoadedWithFullRequest || !stlmtTransId.equals(INITIAL_VALUE) && pmtTransId.equals(INITIAL_VALUE) && AgentId.equals(INITIAL_VALUE) && AgencyId.equals(INITIAL_VALUE);
}
public Boolean getPmtTransIdEnabled()
{
return pageIsLoadedWithFullRequest || stlmtTransId.equals(INITIAL_VALUE) && !pmtTransId.equals(INITIAL_VALUE) && AgentId.equals(INITIAL_VALUE) && AgencyId.equals(INITIAL_VALUE);
}
public Boolean getAgentIdEnabled()
{
return pageIsLoadedWithFullRequest || stlmtTransId.equals(INITIAL_VALUE) && pmtTransId.equals(INITIAL_VALUE) && !AgentId.equals(INITIAL_VALUE) && AgencyId.equals(INITIAL_VALUE);
}
public Boolean getAgencyIdEnabled()
{
return pageIsLoadedWithFullRequest || stlmtTransId.equals(INITIAL_VALUE) && pmtTransId.equals(INITIAL_VALUE) && AgentId.equals(INITIAL_VALUE) && !AgencyId.equals(INITIAL_VALUE);
}
<f:event type="preRenderView" listener="#{searchSettlementTransRequest.preRenderView()}"/> <!--This will ensure that preRenderView method will be called right before rendering of the view ends -->
<h:inputText id="stlID" value="#{searchSettlementTransRequest.stlmtTransId}" name='stlmt' disabled="#{not searchSettlementTransRequest.stlIDEnabled}"/>
<h:inputText id="pmtID" value="#{searchSettlementTransRequest.pmtTransId}" name='pmt' disabled="#{not searchSettlementTransRequest.pmtTransIdEnabled}"/>
<h:inputText id="AgentID" value="#{searchSettlementTransRequest.AgentId}" name='agnt' disabled="#{not searchSettlementTransRequest.AgentIdEnabled}"/>
<h:inputText id="AgencyID" value="#{searchSettlementTransRequest.AgencyId}" name='agncy' disabled="#{not searchSettlementTransRequest.AgencyIdEnabled}"/>
If you want to disable them through ajax you should add the f:ajax command and render all four of these inputTexts. Example:
<h:inputText id="stlID" value="#{searchSettlementTransRequest.stlmtTransId}" name='stlmt' disabled="#{not searchSettlementTransRequest.stlIDEnabled}">
<f:ajax event="blur"
listener=#{searchSettlementTransRequest.madeAjaxRequest()}
execute="stlID pmtID AgentID AgencyID"
execute="stlID pmtID AgentID AgencyID"/>
</h:inputText>
Unrelated It is not a good practice to capitalize the first letters of variables such as AgentId, AgencyID, it should be better if you change them to agentId and agencyID.
Cheers
If you want to do this only in jsf just have to add some AJAX calls. Some suggestions below:
Add to all your <h:inputText attribute disabled with value of #{searchSettlementTransRequest.getDisabled('this_component_id')". So the whole thing will look like this:
<h:inputText id="someId1" value="#{searchSettlementTransRequest.someValue}" name="stlmt" disabled="#{searchSettlementTransRequest.getDisabled('someId1')}"/>
Next in your bean processing this request change settter for `stlmTransId, pmtTransId, AgentId, AgencyId' that their will mark that this value is being set:
public void setXXX(XXX xxx) {
// your actual code comes here and at the end set that this component was changed
actuallyChanged = id_of_input_text_component_corresponding_to_this_value_as_string;
}
Of course you have to add field String actuallyChanged to your bean.
Method getDisabled(String compId) will know looks:
public String getDisabled(String compId) {
if (actuallyChanged.equals(compId)) {
return "";
else {
return "disabled";
}
}
For all your components you have also add AJAX call like this:
<f:ajax event="change" execute="#this" render="stlID pmtID AgentID AgencyID"/>
So know when value of one component will change all other will be disabled. But there is immposible to make them enabled after call is make because without cliend side scripting you cannot easly make them available on select or focus gained or anything.
If you like to disable components temporary, for example when user type in one component other all disabled, but when he select some of them then this one selected is enabled and all other, included this in which he firstly write text, will be disable. In that case better aproach is to use client side scripting for this, JavaScript for example.
Update to exactly match your problem in JavaScript (jQuery)
add to all components an event like this:
onkeyup="$('#thisComponentId').attr('disabled', false); $('#otherComponentId').attr('disabled', true); $('#otherComponentId').attr('disabled', true); "
After your comment you can change it to:
onkeyup="if ($('#thisComponentId').val() && $('#thisComponentId').val() == '') { // here set enable for all components } else { // here set disable for all other components }
This isn't very sophisticated way but it should work. Know when you start typing in one component other will be disabled but when you send request all will be enabled again.

richfaces text and text area on rerender unable to use keyboard up and down arrow keys to move the cursor

I am using RichFaces 3.3.2 and JSF 1.2.
Scenario:
In my application when the user enters some text in a text field or a text area we have to enable the apply button. For this we are using rerender 'onkeyup' event.
Validation error mesage should be shown when user enters invalid date
JSF Page code:
<h:inputText id="input" required="true" requiredMessage="Value cann't be null"
value="#{client.Value}" validatorMessage="Value should be between 0 and 999999999999.99" valueChangeListener="#{myHandler.onChange}" maxlength="30">
<f:validateDoubleRange minimum="0" maximum="999999999999.99"/>
<a4j:support event="onkeyup" eventsQueue="A4JQueue" reRender="outputPanel_btn_save"></a4j:support>
Apply button code:
<a4j:outputPanel id="outputPanel_btn_save">
<a4j:commandButton value="#{msg.btn_Apply}" id="applyButton" reRender="outputPanel_btn_save" eventsQueue="A4JQueue" disabled="#{myHandler.isApplyButtonDisabled}" styleClass="button" action="#{myHandler.update}">
</a4j:commandButton>
</a4j:outputPanel>
Backing bean code for myHandler.onChange()
MyHandler {
public void onChange(ValueChangeEvent event) {
Iterator<FacesMessage> facesMessages = getFacesContext().getMessages();
boolean isMessagePresent=false;
while(facesMessages.hasNext()){
FacesMessage message = facesMessages.next();
isMessagePresent=true;
break;
}
if (event != null
&& event.getNewValue() != event.getOldValue()&& !isMessagePresent) {
this.isApplyButtonDisabled = Boolean.FALSE;
}
if(isMessagePresent){
this.isApplyButtonDisabled = Boolean.TRUE;
}
}
}
Problem:
When the user enters some text onkeyup event we are rerendering the apply button. Due to rerender keyboard arrow keys are not working as the field is loosing it's focus onKeyup event.
I tried using JS to enable the apply button, when user enters some text. But then JSF validations are not being executed and no validation message are being displayed.
Question:
Can you suggest a way to enable the apply button with out loosing focus on the text field / text area and also JSF validations should be executed / displayed?
Try using focuc attribute on a4j:support. It allows to set focus on a component after Ajax request.

Resources