jsf component.valid first time entering the page - validation

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>

Related

f:ajax reload content only after page reloaded

So, i have code:
<h:form id="newMessages" rendered="#{not empty welcome.letters and urlBean.welcome}" styleClass="infoNotes">
**some not important code here**
<ui:repeat id="data" value="#{welcome.letters}" var="letter" varStatus="status">
<h:panelGroup rendered="#{status.index lt 3}">
<div>
<h:commandLink styleClass="noticeClose" rendered="#{letter.content.IMPORTANCE ne '2'}">
<f:ajax listener="#{welcome.onMessageNoticeClose(letter)}" event="click" render="#{cc.clientId}:newMessages newLettersCount"/>
</h:commandLink>
</div>
</h:panelGroup>
**some not important code here**
</ui:repeat>
**some not important code here**
</h:form>
method used when we "click" on close button
public void onMessageNoticeClose(Document letter) {
try (RequestContext ctx = RequestContextFactory.create()) {
DocumentEngine.getInstance().markAsRead(letter, true, ctx);
}
Utils.getRolesBean().recalcMessageCount();
loadMessages();
}
and couple of methods that recalc message count and load new messages. So if we have new unread messages we show them on main page (3 of them). So, problem is when we click close button 'styleClass="noticeClose"', we mark letter as read and didnt show it on main page. But with that code have bug, if in list we have only one message and button close clicked, this letter mark as "read" and message count recalc correct, but it still showed on main page, and don`t rendered only after page will be reloaded. So, solution is if we h:form surround with h:panelgroup like:
<h:panelGroup id="newMessages">
<h:form rendered="#{not empty welcome.letters and urlBean.welcome}" styleClass="infoNotes">
but i don`t understand how it work... Can anyone help me understand this or just explain. Thank you.

How to pass multiple component values to listener via ajax on button click

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

JSF input file tag + ajax

I lost whole day on this issue and got nothing. I know that the question was asked but it was never answered. BalusC said that this issue is fixed in JSF 2.2.5 but either it is not or i do something wrong.
I use h:inputFile tag with ajax to render choosen image in preview div after chosing one from disk. However it's rendered only once and i have to reload page to see next chosen image. It causes more errors. For example when I use SUBMIT button to send chosen image to DB, ajax from commandLink is not executed (image is saved and rendered after page after refresh).
It looks to me like ajax is broken after chosing an image from disk and followed ajax actions are not executed, even they dont belong to h:inputfile.
This is my JSF form (one of its versions because i tried so many tricks)
<h:panelGroup class="photo-update" rendered="#{profileBean.page eq 'photo'}">
Dodaj lub zmień swoje zdjęcie profilowe[...]
<h:form enctype="multipart/form-data">
<h:panelGroup id="form-content">
<h:panelGroup id="current-image" class="current-image">
<p:graphicImage value="#{imageBean.getUserImage()}"/>
</h:panelGroup>
<h:panelGroup id="accept-container-ajax">
<h:panelGroup id="accept-container" class="accept-container"
rendered="true">
<div class="arrow">
<img src="resources/images/arrow.png"/>
<div class="change-text">Zamień na</div>
</div>
<h:panelGroup id="new-image" class="new-image">
<p:graphicImage value="#{profileBean.getConvertedImage()}"/>
</h:panelGroup>
<h:commandLink class="btn btn-default ok-button" value="zatwierdź"
action="#{profileBean.uploadPhoto}">
<f:ajax render="accept-container-ajax current-image"
execute="#form"/>
</h:commandLink>
</h:panelGroup>
</h:panelGroup>
<div class="btn btn-default change-image-container">
Zmień zdjęcie
<h:inputFile immediate="true" id="change-image"
class="change-image" value="#{profileBean.image}">
<f:ajax render="accept-container-ajax" execute="#form"/>
</h:inputFile>
</div>
</h:panelGroup>
</h:form>
</h:panelGroup>
This is fragment of the bean:
public StreamedContent getConvertedImage() throws IOException {
return userBo.convertPartToStream(image);
}
public void uploadPhoto() {
this.renderChangeContainer = false;
if (userBo.addImage(this)) {
FacesContext.getCurrentInstance().addMessage(
null, new FacesMessage(
FacesMessage.SEVERITY_INFO, "...", null));
} else {
FacesContext.getCurrentInstance().addMessage(
null, new FacesMessage(
FacesMessage.SEVERITY_ERROR, "...", null));
}
}
injected BO methods are OK.
Please give me a clue what is going on.
EDIT:
I also see ugly iframe with some response content i guess.

How to customize the presentation of faces messages

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>

Command button inside jQuery SimpleModal window does not invoke action

I have created a DIV section in my page in the following way:
<div id="modalAlert" style="display: none;">
<h:panelGroup layout="block">
<p>My Heading </p>
</h:panelGroup>
<h:panelGroup layout="block">
</h:panelGroup><h:panelGroup layout="block">
<h:commandButton id="btnSaveConfirmation" value="save" action="#{myBean.method}"> </h:commandButton>
</h:panelGroup>
</div>
And I am using the following JS script to display a SimpleModal window using jQuery:
function showAlert() {
fundpickerdialog = $('#modalAlert').modal({
opacity : 100,
overlayCss: {backgroundColor:"#fff"},
modal : true,
dataId : 'modalAlert',
classname: 'ui-dialog ui-widget ui-widget-content ui-corner-all ui-draggable ui-resizable',
closeOnEscape : false,
width : 50,
height : 50
});
}
$(document).ready(function() {
showAlert();
}
});
The modal window is appearing but on clicking the Save button it's not calling the backing bean method.
You forgot the form tags (h:commandButton must be located inside a form), wrap the content of the div with tags
try something like this:
<div id="modalAlert" style="display: none;">
<h:form>
<h:panelGroup layout="block">
<p>My Heading </p>
</h:panelGroup>
<h:panelGroup layout="block">
</h:panelGroup><h:panelGroup layout="block">
<h:commandButton id="btnSaveConfirmation" value="save" action="#{myBean.method}"></h:commandButton>
</h:panelGroup>
</h:form>
</div>
Some JavaScript/jQuery modal dialog approaches will remove the element representing the modal dialog and all of its children from its current position in the HTML DOM tree and re-insert it as immediate child of the <body> in order to prevent potential positioning and layering issues across various browsers. Since you didn't put the <form> inside the element representing the modal dialog, it will end up being form-less.
You really need to put the <h:form> inside the element representing the modal dialog.
Further, I recommend to use a JSF component library instead of an arbitrary jQuery plugin. For example PrimeFaces has a <p:dialog> component for exactly this purpose. It has already taken potential nasty JSF-related side effects into account for you without that you need to write any additional line of JS/jQuery code.

Resources