Customizing a p:growl message - primefaces

<h:form id="aform">
<p:growl id="debug-growl" showSummary="true" showDetail="true" sticky="false" />
<p:inputText id="expression" value="#{debug.expression}"
required ="true" requiredMessage="Value is required" />
...
If user did not provide an input and submit the form then a pop-up appears and it contains two lines of info.
Value is required
Value is required
I would like to change the subject of the pop-up (a bold part of it) to Error for instance.
How can I make it?

The bold part of your growl message is the summary message, like a heading. The other one is the detail message. You can disable the one or the other. You've set both on true.
You can define and personalize your message by FacesContext as follows:
FacesContext context = FacesContext.getCurrentInstance();
context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Validation error", "Value is required");
Source: http://www.primefaces.org/showcase/ui/message/growl.xhtml
I hope this helps!

Related

Primefaces steps skip validation on primefaces file uploader [duplicate]

since fileLimit doesn't exist in primefaces 3.4 anymore I'm trying a work around implementing a validator, the problem is that the method validate is never invoked. That's my Validator:
#FacesValidator(value ="fileLimitValidator")
public class FileLimitValidator implements Validator {
#Override
public void validate(final FacesContext context, final UIComponent component,
final Object value) throws ValidatorException {
final String fileLimit = (String)component.getAttributes().get("fileLimit");
final String size = (String)component.getAttributes().get("size");
if (fileLimit!=null && size!=null) {
if (Integer.valueOf(size) >= Integer.valueOf(fileLimit)) {
FacesUtils.throwErrorExceptionFromComponent(component,"fichero_confidencialidad_error");
}
}
}
}
and in my facelet I've tried:
<p:fileUpload id="#{id}FileUpload"
fileUploadListener="#{bean[metodoTratarFichero]}" mode="advanced"
multiple="true" allowTypes="#{allowTypes}" showButtons="false"
update="#{id}ListaDocs #{id}MsgError" auto="true"
label="#{fileuploadmsg.label_boton}"
invalidFileMessage="#{fileuploadmsg.tipo_incorrecto}" >
<f:validator validatorId="fileLimitValidator"/>
<f:attribute name="fileLimit" value="#{fileLimit}"/>
<f:attribute name="size" value="#{listaDocumentos.size}"/>
</p:fileUpload>
and:
<p:fileUpload id="#{id}FileUpload"
fileUploadListener="#{bean[metodoTratarFichero]}" mode="advanced"
multiple="true" allowTypes="#{allowTypes}" showButtons="false"
update="#{id}ListaDocs #{id}MsgError" auto="true"
label="#{fileuploadmsg.label_boton}"
invalidFileMessage="#{fileuploadmsg.tipo_incorrecto}"
validator="fileLimitValidator">
<f:attribute name="fileLimit" value="#{fileLimit}"/>
<f:attribute name="size" value="#{listaDocumentos.size}"/>
</p:fileUpload>
and:
<p:fileUpload id="#{id}FileUpload"
fileUploadListener="#{bean[metodoTratarFichero]}" mode="advanced"
multiple="true" allowTypes="#{allowTypes}" showButtons="false"
update="#{id}ListaDocs #{id}MsgError" auto="true"
label="#{fileuploadmsg.label_boton}"
invalidFileMessage="#{fileuploadmsg.tipo_incorrecto}"
validator="#{fileLimitValidator}">
<f:attribute name="fileLimit" value="#{fileLimit}"/>
<f:attribute name="size" value="#{listaDocumentos.size}"/>
</p:fileUpload>
and:
<p:fileUpload id="#{id}FileUpload"
fileUploadListener="#{bean[metodoTratarFichero]}" mode="advanced"
multiple="true" allowTypes="#{allowTypes}" showButtons="false"
update="#{id}ListaDocs #{id}MsgError" auto="true"
label="#{fileuploadmsg.label_boton}"
invalidFileMessage="#{fileuploadmsg.tipo_incorrecto}"
validator="#{fileLimitValidator.validate}">
<f:attribute name="fileLimit" value="#{fileLimit}"/>
<f:attribute name="size" value="#{listaDocumentos.size}"/>
</p:fileUpload>
but the validate method is never called. What is the correct way to do it?
According to the FileUpload and FileUploadRenderer source code, the validator is only invoked when mode="simple" is been used (note: this in turn requires ajax="false" on command). The advanced mode will namely not set the uploaded file as component's submitted value, causing it to remain null until the listener method is invoked. As long as the submitted value is null, the validators are not invoked.
I'm not sure if this is intentional. Theoretically, it should be possible to set UploadedFile as submitted value and have the validator to rely on it. You might want to create an enhancement report at PrimeFaces issue tracker.
In the meanwhile, in spite of it being a poor practice, your best bet is really performing the validation in fileUploadListener method. You can just trigger validation failure add faces messages through the FacesContext like follows:
if (fail) {
context.validationFailed();
context.addMessage(event.getComponent().getClientId(context), new FacesMessage(
FacesMessage.SEVERITY_ERROR, messageSummary, messageDetail));
}
Otherwise, you'd need to create a custom renderer for the <p:fileUpload> which sets the submitted value during the decode() (I however don't guarantee that it would work in practice, you'll maybe stumble upon a peculiar problem which may turn out to be the reason why PrimeFaces didn't initially implement it like that).
By the way, your first and second validator attempt are correct. The third attempt works only if you used #ManagedBean instead of #FacesValidator (which is often done when injection of an #EJB is mandatory — which isn't possible in a #FacesValidator). The fourth attempt is invalid.
For validating a required primefaces file upload in mode advanced (ajax) it is possible to use this:
<f:metadata>
<f:event listener="#{bean.processValidations()}" type="postValidate" />
</f:metadata>
Where the implementation of the bean.processValidations() method would be something along the lines of:
public void processValidations() {
FacesContext context = FacesContext.getCurrentInstance();
UIInput fileUploadComponent = fileUploadsBean.getFileUploadComponent();
if (fileUploadComponent!=null && !isFileUploaded()) {
fileUploadComponent.setValid(false);
context.addMessage(fileUploadComponent.getClientId(context), new FacesMessage(FacesMessage.SEVERITY_ERROR, messageSummary, messageDetail));
context.validationFailed();
}
}
Where fileUploadsBean would be a REQUEST scoped CDI bean (won't work with standard JSF ManagedBeans) which you inject to your bean which has the processValidations() method defined, the method fileUploadsBean.getFileUploadComponent() returns the primefaces file upload component (you will use <p:fileUpload binding="#{fileUploadsBean.fileUploadComponent}" ...> for that). The method isFileUploaded() will determine if the file has been uploaded or not (probably just a null check on a member variable which you fill from fileUploadListener).
If you want to highlight the file upload button you can of course conditionally add a styleClass which you can then use for adding a red border for example.
styleClass="#{fileUploadsBean.fileUploadComponent.valid ? '' : 'validationFailed'}"
As a result the validation failed message for the primefaces file upload will be displayed along with all other jsf validation messages. You might have problem with maintaining order of the validation messages (will be always at the end), but it still beats displaying the failed upload file validation after user dealt with all the standard jsf validation messages from different fields and your action in a backing bean has been finally reached.

Why does my form isn't reseting his styling after render?

I have a form with tree buttons on in. One of them is the "Cancel" button that goes back to the previous page.
The problem is there is any validation issue, like a mandatory field not submited, the styling of the field is not reset when I go back to the form.
This is a simplified structure of the xhtml:
<panel id="horizontal">
<form id="filterVipLoungeForm">
</form>
<form id="frmAddPax">
<form id="frmAccessType">
</form>
</form>
<panelGrid>
<commandButton value="agregar" />
<commandButton value="limpiar" />
<commandButton value="cancelar" />
</panelGrid>
</panel>
The code of the button that calls the add passenger form:
<p:commandButton
value="#{label['manageVipLoungeEntrance.button.addPassenger']}"
action="#{manageVipLoungeEntranceExtMB.setRenderStatus(3, 1)}"
actionListener="#{manageVipLoungeEntranceExtMB.hideMainForm}"
update=":filterVipLoungeForm :horizontal">
</p:commandButton>
The code of the cancel button:
<p:commandButton
value="#{label['manageVipLoungeEntrance.button.cancel']}"
onclick="showLocalDate()"
action="#{manageVipLoungeEntranceExtMB.setRenderStatus(0, 1)}"
actionListener="#{manageVipLoungeEntranceExtMB.setRenderStatus(3, 0)}"
update=":filterVipLoungeForm :horizontal">
</p:commandButton>
This calls a method from the backing bean calls setRenderStatus that set the form and he's render status to be evaluated in the rendered attribute.
In this process the render status of the cancel button's form is set to false and the render status of the previous form is set to true.
The hideMainForm method calls two times the setRenderStatus method, setting the main form render status to false and the add passenger render status to true.
The problem there is any validation error and if I go back to the previous page and come back to the form I'm still getting the validation errors.
[EDIT]
Sorry I forgot to add the code of the rendered evaluation of the two forms involucrated in this:
Render status validation for form "frmAddPax"
<h:form id="frmAddPax" rendered="#{manageMB.renderStatus.isRenderFormAddPax()}">
Render status validation for form "filterVipLoungeForm"
<h:form id="filterVipLoungeForm" style="width:95% !important;"
rendered="#{manageMB.renderStatus.isRenderFormMain()}"
onkeypress="return event.keyCode != 13">
I have tried by using the <p:resetInput>but it didn't work, with this I was expecting the form with the id frmAddPax reset his status but it didn't work:
<p:commandButton
value="#{label['manageVipLoungeEntrance.button.cancel']}"
onclick="showLocalDate()"
action="#{manageVipLoungeEntranceExtMB.setRenderStatus(0, 1)}"
actionListener="#{manageVipLoungeEntranceExtMB.setRenderStatus(3, 0)}"
update=":filterVipLoungeForm :horizontal">
<p:resetInput target=":frmAddPax" />
</p:commandButton>
I used the <p:ajax resetValues="true"> and this one works as I needed.
I really don't know why work with the ajax and not with the resetInput.
<p:commandButton
value="#{label['manageVipLoungeEntrance.button.cancel']}"
onclick="showLocalDate()"
action="#{manageVipLoungeEntranceExtMB.setRenderStatus(0, 1)}"
actionListener="#{manageVipLoungeEntranceExtMB.setRenderStatus(3, 0)}"
update=":filterVipLoungeForm :horizontal">
<p:ajax update=":frmAddPax" resetValues="true" />
</p:commandButton>

is possible use two growls in one page

I want to use two growls in one page. One use to show success message that do auto hide (sticky="false"), the other one use to show failed messages that do not auto hide (sticky="true"):
<p:growl id="globalSuccessMessageGrowl" showDetail="false"
showSummary="true" life="3000" />
<p:growl id="globalFailedMessageGrowl" showDetail="false"
showSummary="true" sticky="true" />
public static void globalSuccessMessage(String message,
FacesMessage.Severity severity) {
FacesContext.getCurrentInstance().getViewRoot().findComponent("globalSuccessMessageGrowl");
renderComponent(new FacesMessage(severity, message, message), null,
"globalSuccessMessageGrowl");
}
public static void globalFailedMessage(String message,
FacesMessage.Severity severity) {
renderComponent(new FacesMessage(severity, message, message), null,
"globalFailedMessageGrowl");
}
...but the two growls do not auto hide after 3 seconds. Failed growl effects success growls?
You can assign different severity levels to each one. This was an attribute added to primefaces in version 3.3.
Check this question . The user had the same problem as you do.

How to show primefaces icon error programatically?

i have input field and message icon component as follows:
<h:form id="myForm" >
<p:inputText id="email" />
<p:message id="iconMessage" for="email" display="icon" />
and i have a submit button that checks in server side for email existence in database, and if it exists i want to make the error icon appears as follows:
FacesContext.getCurrentInstance().addMessage("myForm:email",
new FacesMessage(FacesMessage.SEVERITY_ERROR, "", ""));
but the error icon won't render, please advise how to fix that.
You have to update the component:
RequestContext.getCurrentInstance().update("myForm:email");
from
org.primefaces.context.RequestContext;
But I would advise specifying a validator instead:
<p:inputText id="email" validator="{yourBean.validateEmail}" />
and in your managed bean:
public void validateEmail(FacesContext context, UIComponent component, Object value) {
String email = value.toString();
//check if email exists in DB
FacesContext.getCurrentInstance().addMessage(component.getClientId(context),
new FacesMessage(FacesMessage.SEVERITY_ERROR, "", ""));
}
}

Update the page with command bouton primefaces

I want to get the value of the input Textarea and show it in the same page by clicking on the command button "compiler "
however i don't get any result ! and the contnet is only shown when I update with the browser updater
Sh How do I upate the page and the managed beans to show the content of a primefaces textarea in the same page
this is the code:
<p:layoutUnit position="west" size="520" header="Code à executer" resizable="true" >
<h:form id="moncode">
<p:inputTextarea id="mycode" value="#{fichier.code}" rows="17" cols="50" />
<p:commandButton value="compiler" id="btn3" action="guest.xhtml" styleClass="myButtonClass" />
</h:form>
</p:layoutUnit>
<p:layoutUnit position="east" size="550" header="Resultat d'execution" resizable="true" >
<h:outputText value="#{fichier.code}" />
</p:layoutUnit>
<p:layoutUnit position="south" >
my application is about compiling a given code: I write a code and then I executed with the button "compiler" so a file will be created however the file is always created with "null" and I think because the var "code" is not yet set in the managed bean that why I want to update the page so the managed bean ill be set here is compile:
`
private String code;
private String error;
public String getCode() {
return code;
}
public String getError() {
return error;
}
public void setCode(String code) {
this.code = code;
}
public void compile() throws IOException {
File file = new File("C:\\Users\\Rad1\\test.c");
PrintWriter ecrivain;
ecrivain = new PrintWriter(new BufferedWriter (new FileWriter(file)));
ecrivain.println(code);
ecrivain.close();
`
There are two ways to achieve what you want: either by using a synchronous submit of a form with a subsequesnt postback, or by sending an AJAX request to partially update necessary parts of the page.
Synchronous submit
<p:inputTextarea id="mycode" value="#{fichier.code}" rows="17" cols="50" />
<p:commandButton value="compiler" id="btn3" action="#{fichier.action}" styleClass="myButtonClass" ajax="false" />
<h:outputText id="upd" value="#{fichier.code}" />
with action method
public String action() {
//do business job
return null;
}
This way a fields will be refreshed by making a postback. Don't forget that the bean Fichier must be view scoped. Note the ajax="false" attribute of <p:commandButton>.
AJAX call
<p:inputTextarea id="mycode" value="#{fichier.code}" rows="17" cols="50" />
<p:commandButton value="compiler" id="btn3" action="#{fichier.action}" styleClass="myButtonClass" update="upd" />
<h:outputText id="upd" value="#{fichier.code}" />
with the same action method
public String action() {
//do business job
return null;
}
This way only the contents of <h:outputText> will be updated after AJAX call is finished. Don't forget that the bean Fichier should also be view scoped. Note that id attribute of <h:outputText> must be specified.
Actually, you don't call the action itself. Your action forwards to a certain page. There is no race condition or syncronization problems in a JSF action betwwen setting the properties and the action itself. I recommend you to read JSF life cycles tutorial by BalusC Aplly request values phase run before the action.
Try to call action on command Button.
<p:commandButton value="compiler" id="btn3" action="#{fichier.compile}" update="outputCode" styleClass="myButtonClass" />
Add an id attribute to your output panel and specify it in the action button.
<p:layoutUnit id="outputCode" position="east" size="550" header="Resultat d'execution" resizable="true" >
<h:outputText value="#{fichier.code}" />
</p:layoutUnit>
P.S. It is also good to read this BalusC answer for better understanding of actions, Ajax/non Ajax request etc.