I'm using JSF and I'd like to call a listener on an InputText element's keyup events, but only if the input text is longer than 3 chars.
My code is:
<h:inputText id="myId" styleClass="iceInpTxt uppercase" maxlength="15"
value="#{controller.model.value}">
<f:ajax event="keyup" listener="#{controller.listener}" render="anotherElement"/>
</h:inputText>
Now I'm checking the text's length in my listener, works perfectly but way to slowly.
Is there a workaround, like a conditional listener, which is only called when inputText.length() > 3, in other cases the listener is ignored?
you can simply use a javascript-function that only returns true and hence triggers the listener if your required condition is matched.
<h:inputText id="myId"
onkeyup="return checkLength(this)"
styleClass="iceInpTxt uppercase" maxlength="15"
value="#{controller.model.value}">
<f:ajax event="keyup" listener="#{controller.listener}" render="anotherElement"/>
</h:inputText>
javascript:
function checkLength(value){
return value.length > 3;
}
Related
I'm displaying a small icon next to input fields when validation did not pass. I can do it but I was hoping for a better solution than what I have currently:
<p:inputText ... binding="#{myfield}">
<f:validator binding="#{myfieldValidator}"/>
<f:ajax event="blur" render="myfieldFeedback"/>
</p:inputText>
<h:panelGroup id="myfieldFeedback">
<div class="failedIndicator colorRed" jsf:rendered="#{myFieldvalidator.isIndicatorvisible.myFieldfailed}">!</div>
<div class="successIndicator" jsf:rendered="#{myFieldValidator.isIndicatorVisible.myFieldSuccess}">v</div>
</h:panelGroup>
With inside my validator:
private Map<String, Boolean> isIndicatorVisible;
isIndicatorVisible.put("myFieldSuccess", false);//if validation succeeds goes to true
isIndicatorVisible.put("myFieldFailed", false);// opposite of above
I'm hoping for a better solution (that doesn't use a map) like this:
<h:panelGroup id="myfieldFeedback">
<div class="#{myfield.valid ? 'successIndicator' : 'noDisplay'}">v</div>
<div class="#{myfield.valid ? 'noDisplay' : 'failedIndicator colorRed'}">!</div>
</h:panelGroup>
The field is valid upon entenring for the first time the dialog in which the form is displayed. Thus there is a valid feedback which is displayed I do not wish to have.
You thus want to make sure the conditions are only evaluated during a postback request, not during an initial (GET) request. You can check that by FacesContext#isPostback().
<h:panelGroup id="myfieldFeedback">
<ui:fragment rendered="#{facesContext.postback}">
<div class="...">v</div>
<div class="...">!</div>
</ui:fragment>
</h:panelGroup>
I have a selectonemenu that includes some items. And a null item for showing "please choose one"..
MY goal is to query some data when I select one of them. And if i select the "please choose one" do another thing.
But eventually, the change event is fired for normal values but if I select "please choose one" item , it is not fired. Thanks for your help. Here is my code.
<p:selectOneMenu style="width: 200px" id="positionForward" value="#{hrProcessController.queryCriteria.positionForward}" converter="listConverter"
effect="fade" var="u" filter="true" filterMatchMode="startsWith" validator="#{hrProcessController.isOpenPositionForwValid}">
<f:selectItem itemLabel="#{menu['onemenu.choose']}" itemValue="#{null}"/>
<f:selectItems value="#{hrProcessController.positionList}" var="position" itemLabel="#{position.name}" itemValue="#{position}" />
<p:ajax event="change" listener="#{hrProcessController.onPositionSelect}" update="openPositionForward"/>
<p:column>
<h:outputText value="#{u==null ? menu['onemenu.choose'] : u.name}" />
</p:column>
</p:selectOneMenu>
public void onPositionSelect()
{
if(queryCriteria.getPositionForward()!=null)
{
OpenPositionQueryCriteria criteria = new OpenPositionQueryCriteria();
criteria.setPosition(queryCriteria.getPositionForward());
List<OpenPosition> openPositions = openPositionService.searchOpenPosition(criteria);
setOpenPositionList(openPositions);
}
else
{
List<OpenPosition> positions = openPositionService.getActiveOpenPositionList();
setOpenPositionList(positions);
}
}
If you use itemValue="#{null}" or itemValue="", the valueChangeListener method never will be called.
That's a better approach if you want your first item null:
<f:selectItem
itemDisabled="true"
itemLabel="#{null}"
itemValue="#{null}" />
I had the same problem.
Change event WON'T be fired by selecting default value. Why that is so is beyond me. Such things are normal usually.
I didn't find any real solution.
You should try to write custom validator and converter for this.
Try this:
Using a "Please select" f:selectItem with null/empty value inside a p:selectOneMenu
OK, I finally found the solution to this!
you need to add immediate="true" to ajax call.
Adding immediate tells ajax to ignore any potential validation errors and call the onChange anyway.
Try it.
I was with the same issue so I put the selectItem without the propertie itemValue like that:
<f:selectItem itemLabel="#{menu['onemenu.choose']}" />
I have select box for list of account numbers, an input field to enter amount and a button to calculate total debit. I want to pass the amount and account values via ajax to an event handler on click event.
Some how I am not able to pass the values entered to event handler.
Can someone suggest me, on how to do ?
My Xhtml:
<h:selectOneMenu class="RUIFW-from-el form-control"
id="fromAccountIndex" value="#{parentBean.fromAccountIndex}"
validator="#{tptValidator.validateFromAccount}">
<f:selectItems value="#{parentBean.fromAccountUIMap}"/>
</h:selectOneMenu>
<h:inputText id="amount" name="amount" value="#{parentBean.amount}" class="RUIFW-form-el form-control" validator="#{tptValidator.validateAmount}"/>
Updated code:
<h:commandLink class="RUIFW-btn mar-lft-10 veraligntop">
<h:outputLabel value="#{GIBBundle.tpt_btn_calculate}"/>
<f:ajax execute="#this fromAccountIndex amount onclick" listener="#{parentBean.calculateClickedListener}"/>
</h:commandLink>
My Bean Method
public void calculateClickedListener(AjaxBehaviorEvent event) {
System.out.println("getFromAccountIndex()....."+getFromAccountIndex());
System.out.println("getAmount()....."+getAmount());
}
You're not setting the execute attribute on the f:ajax. That attribute defaults to #this, and as a result, no other component will be processed and no values will be set. This is why the value bindings of your input components are likely to turn out null.
Set your execute="#form" or execute="#this fromAccountIndex amount" to get the values updated in your bean
Reference:
f:ajax Javadoc
I have a validation on my selectOneMenu to prevent the user to select "None" item in the list.
<h:selectOneMenu id="selectMenu" value="#{bean.selectedValue}" required="true" requiredMessage="Please select an item">
<f:ajax render="toRender selectMenuMessage" listener="#{bean.onSelect}"/>
<f:selectItem itemLabel="None" noSelectionOption="true"/>
<f:selectItems value="#{bean.items}" var="item" itemValue="#{item.id}" itemLabel="#{item.label}"/>
</h:selectOneMenu>
I have my panel below and a want to show it only when my item is not "None".
So when I select "None", the message should render and the panel disappear.
<h:panelGroup id="toRender">
<h:panelGrid rendered="#{bean.selectedValue == 0 ? false : true">
...
</h:panelGrid>
</h:panelGroup>
It's working without the validation but I can't make both work.. It's like if validation prevents rendering.
Any suggestion?
Thanks
I guess that bean.selectedValue is an Integer, so try this:
<f:selectItem itemValue="0" itemLabel="None" noSelectionOption="true"/>
Edit:
Ah sorry, I think misunderstood your problem a little bit.
The problem here is, that if you are requiering a value for the selectOneMenu the value will not submitted if it is empty. And if the item with noSelectionOption="true" is selected, it will be handled as empty, so no value will be submitted. When you are checking against bean.selectedValue == 0, selectedValue will never - except maybe initially - be 0, because when you select the item with value 0 it will not be submitted, as described above.
So you are right, your validation and the check for bean.selectedValue == 0 can not work together. I would recommend you to just remove the validation.
If this is no option for you, please explain me why you need it to work that way in more details.
I have a response, it's not the solution but it's another way to do this...
<h:selectOneMenu id="selectMenu" value="#{bean.selectedValue}">
<f:ajax render="toRender selectMenuMessage" listener="#{bean.onSelect}"/>
<f:selectItem itemLabel="None" noSelectionOption="true"/>
<f:selectItems value="#{bean.items}" var="item" itemValue="#{item.id}" itemLabel="#{item.label}"/>
</h:selectOneMenu>
And in the bean
public void onSelect() {
if(this.selectedValue != 0) {
// Do smthg here
} else {
// Display error message
UIComponent component = Outils.getFacesContext().getViewRoot().findComponent(":form:selectMenu");
if(component != null) {
Outils.getFacesContext().addMessage(component.getClientId(), new FacesMessage(FacesMessage.SEVERITY_ERROR, "", "Test msg"));
}
}
}
This way the validation process is not launched and the verification is done in the bean.
If someone find something better, let me know!
I would like to customize the presentation of faces messages.
For this,
<h:inputText id="name" required="true" />
when validation is failed, then it will be shown in a
<h:message for="name" />
However, I would like to customize the presentation call JS as follows:
<div class="notification"></div>
function showNotification(msg){
$(".notification").html(msg);
$(".notification").fadeIn(1000, function(){
timeout = setTimeout(function(){
$(".notification").fadeOut(1000);
}, 5000);
});
}
How can I achieve this?
You can use FacesContext#getMessageList() to get the messages in the view, if necessary the ones for a specific client ID. You can iterate over them in a ui:repeat. Each item is a FacesMessage which has several getters. You can display any HTML in the message unescaped by using <h:outputText escape="false">.
So, in a nutshell:
<ui:repeat value="#{facesContext.messageList('form:name')}" var="message">
<div><h:outputText value="#{message.summary}" escape="false" /></div>
</ui:repeat>
(in the above example, I assume that your form has id="form")
Or, if that HTML help link is actually not part of the message, then so:
<ui:repeat value="#{facesContext.messageList('form:name')}" var="message">
<div>#{message.summary} help</div>
</ui:repeat>