primefaces fileupload required attribute not working - jsf

I have a JSF form which contains a Primefaces fileupload component.
The required attribute of the fileupload component is not working; When I hit the form's send button without file attachments, the form is sent and no error message is displayed.
This is the simplified form code I am using for testing:
<h:form id="NewRegistryForm">
<fieldset>
<p:outputLabel for="address" value="Address" />
<h:inputText
name="address"
value="#{registryBean.address}"
required="true"
requiredMessage="Address field is required" />
</fieldset>
<fieldset>
<p>File attachments:</p>
<p:fileUpload
fileUploadListener="#{registryBean.handleFileUpload}"
mode="advanced"
label="Choose file"
multiple="true"
update="registryFileList"
invalidFileMessage="Invalid file type"
sizeLimit="512000"
fileLimit="15"
allowTypes="/(\.|\/)(jpg|png|gif|pdf|odt|doc|docx)$/i"
onstart="setSubmitButtonEnabled(false)"
oncomplete="setSubmitButtonEnabled(true)"
onerror="setSubmitButtonEnabled(true)"
auto="true"
required="true"
requiredMessage="A file attachment is required." />
</fieldset>
<p:dataList id="registryFileList" value="#{registryBean.uploadedFiles}"
var="file" emptyMessage="" >#{file.file.fileName}, #{file.file.size}</p:dataList>
<p:commandButton
type="submit"
action="#{registryBean.sendRequest}"
value="Send form"
validateClient="true" />
</h:form>
The required text input field shows an error message when the field is not filled, but the fileupload component produces no message when no file is attached. What am I doing wrong?

Related

globalOnly="true" in h:messages and bean validation

I use globalOnly="true" in h:messages to show messages as success or errors during bean methods......
<div class="row">
<div class="col">
<h:messages id="mensagens" warnClass="alert alert-danger" infoClass="alert alert-success" errorClass="alert alert-danger" globalOnly="true" />
</div>
</div>
and h:message for="" to validate field by field with bean validation
<h:inputText id="nome" styleClass="form-control" value="#{lojaMB.filial.nome}" />
<h:message for="nome" class="text-danger" />
It's works well......
But when I click on the "+" green button the modal opens
This modal use other managed bean and other form with ajax...
<h:commandButton value="Salvar" styleClass="btn btn-secondary" action="#{supermercadoMB.salvar}">
<f:ajax execute="#form" render=":mensagens :frmNovaFilial:supermercado #form" onevent="hideModal" />
</h:commandButton>
THE PROBLEM
when I click "Salvar" button the function "hideModal" executes, modal closes and bean validation send a error message by the blank field to parent page h:messages (no h:message ...) ....... but this message doesn't show........ Just shows when I remove globalOnly="true" .....but If I remove globalOnly="true" validations of field by field are show too on h:messages and h:message ......
how resolve this?
Create a parent element to your message component and after process the button update it
In the commandButton process only the nome inputText and the button itself
<h:panelGrid id="grid" columns="1">
<h:inputText id="nome" styleClass="form-control" value="#{lojaMB.filial.nome}" />
<h:message for="nome" class="text-danger" />
</h:panelGrid>
<h:commandButton value="Salvar" action="#{supermercadoMB.salvar}">
<f:ajax execute="#this :nome" render=":grid" onevent="hideModal" />
</h:commandButton>

Submit form with file upload

I would like to implement form with file upload. I tried this.
<f:websocket channel="uploadProgress" scope="view" onmessage="updateProgressBar" />
<h:form id="form" enctype="multipart/form-data">
<h:panelGrid columns="2" styleClass="new_table">
..................
</h:panelGrid>
<div class="row">
<h:messages id="uploadMsgId" globalOnly="true" showDetail="false" showSummary="true"/>
<h:inputFile id="fileToUpload" required="true" requiredMessage="No file selected ..." value="#{newProcedure.file}"/>
<h:message showDetail="false" showSummary="true" for="fileToUpload"/>
<h:commandButton value="Upload" action="#{newProcedure.upload()}">
<f:ajax execute="#form" onevent="progressBar" render="#form"/>
</h:commandButton>
<div>
<div id="progressBarId" width="250px;" height="23"/>
</div>
</div>
<h:commandButton styleClass="button" value="Create Procedure" action="#{newProcedure.addNewProcedure(1)}">
<f:ajax render="#form" execute="#form"></f:ajax>
</h:commandButton>
</h:form>
I can upload file when I press the internal h:commandButton but when I press the second button to submit the form with the attached file nothing happens.
Any idea why it;s not working? Also if there is no selected file how I can submit the form without the attached file? I need to implement some check?

Submit form without attached file

I want to create JSF form with attached file. But also to give a option form the users to submit the for without attach file. I don't want this to be mandatory.
<h:form id="form" enctype="multipart/form-data">
<div class="string">
<label class="name">
<h:inputText id="name" value="#{contacts.name}" pt:placeholder="Name*:"/>
</label>
</div>
<label class="message">
<h:inputTextarea value="#{contacts.comment}" pt:placeholder="Comment*:"/>
</label>
<h:inputFile id="fileToUpload" value="#{contacts.file}" required="true" requiredMessage="No file selected ..."/>
<h:commandButton value="Upload" action="#{contacts.upload()}">
<f:ajax execute="fileToUpload" />
</h:commandButton>
<h:message showDetail="false" showSummary="true" for="fileToUpload" style="color:red"/>
<div class="btns">
<h:commandLink id="submitlink" class="link" value="submit" action="#{contacts.sendEmail}" >
<f:ajax render="#form" execute="#form" onevent="handleDisableButton" resetValues="true"/>
</h:commandLink>
</div>
<h:outputText id="output" value="#{contacts.result}" />
</h:form>
Is there a way to implement this because now if I try to submit the form I always get message No file selected ...?
Also when I attach a file using the button upload button no message appears for successful file upload.
You have your inputFile as required. That is why you have to upload first always.
Also, if you are not seeing any message it's because you are not rendering again your h:message. Try using this in your managed bean:
FacesContext.getCurrentInstance().getPartialViewContext().getRenderIds()
.add("idMessage");
change
<h:inputFile id="fileToUpload" value="#{contacts.file}" required="true" requiredMessage="No file selected ..."/>
to
<h:inputFile id="fileToUpload" value="#{contacts.file}" />

Referring composite component ID in f:ajax render

I am writing a composite component that is intended to wrap an input element, and augment it with an 'optional field' designation and h:message element below it.
Here is the component (in input.xhtml file):
<composite:interface/>
<composite:implementation>
<div>
#{component.children[1].setStyleClass(component.children[1].valid ? '' : 'inputError')}
<composite:insertChildren/>
</div>
<h:panelGroup styleClass="optional"
rendered="#{!component.parent.children[1].required}"
layout="block" >
#{msgs['common.optional.field']}
</h:panelGroup>
<h:message id="msgId"
for="#{component.parent.children[1].id}" errorClass="error"/>
</composite:implementation>
Again, the intended usage of the component is to wrap an h:input* element which is expected to be the first and immediate child of it in a using page.
In a using page I would then write:
<h:form id="f1">
<h:panelGrid border="0" columns="2" style="width: 80%">
<f:facet name="header">
<col width="40%" />
<col width="60%" />
</f:facet>
<h:outputLabel styleClass="sectionBody" for="i1"
value="Input 1"></h:outputLabel>
<my:input id="ii1">
<h:inputText id="i1" size="20" maxlength="20" tabindex="0"
required="true" label="Input 1">
</h:inputText>
</my:input>
<h:outputLabel styleClass="sectionBody" for="i2"
value="Input 2"></h:outputLabel>
<my:input id="ii2">
<h:inputText id="i2" size="20" maxlength="20" tabindex="0"
label="Input 2">
</h:inputText>
</my:input>
</h:panelGrid>
<br />
<h:commandButton value="Submit" tabindex="1">
<f:ajax listener="#{terminalImportBean.addTerminal}"
execute="#form" render="#form"/>
</h:commandButton>
</h:form>
This would work just fine using normal posts.
However if I add add f:ajax validation for "Input 1" (id="i1") and try to re-render the composite (ii1) using the following:
...
<h:outputLabel styleClass="sectionBody" for="i1"
value="Input 1"></h:outputLabel>
<my:input id="ii1">
<h:inputText id="i1" size="20" maxlength="20" tabindex="0"
required="true" label="Input 1">
<f:ajax listener="#{myBean.checkInput1}"
event="blur"
render="ii1"/>
</h:inputText>
</my:input>
...
I gen an error in the browser during ajax response processing:
malformedXML: During update: f1:ii1 not found
I tried using f1:ii1, :f1:ii1, but to no avail. When I use msgId or :f1:ii1:msgId it works. Does anybody know why?
I am using Mojarra 2.1.3
Thanks
That's because the composite component does by itself not render anything to the HTML. Only its children are been rendered to HTML. There does not exist any HTML element with ID f1:i11 in the generated HTML output. Open the page in browser, rightclick and View Source. Look in there yourself. There's no such element with that ID. JavaScript/Ajax is encountering exactly the same problem. It can't find the element in order to update it.
To solve this, you'd need to wrap the entire composite body in a HTML <div> or <span> and assign it an ID of #{cc.clientId} which basically prints UIComponent#getClientId().
<cc:implementation>
<div id="#{cc.clientId}">
...
</div>
</cc:implementation>
Then you can reference it as below:
<my:input id="foo" />
...
<f:ajax ... render="foo" />
You can even reference a specific composite component child.
<f:ajax ... render="foo:inputId" />
See also:
Is it possible to update non-JSF components (plain HTML) with JSF ajax?
How to find out client ID of component for ajax update/render? Cannot find component with expression "foo" referenced from "bar"

Error "<f:ajax> contains an unknown id" when used to render <rich:message>

This is my form:
<h:body>
<h:form>
<h:panelGrid columns="3" >
<h:outputLabel for="name" value="Primeiro nome:" />
<h:inputText id="name" value="#{register.person.name}" >
<f:ajax event="blur" render="m_name" listener="#{register.validateName}" />
</h:inputText>
<rich:message id="m_name" for="name" />
//.. others fields
</h:panelGrid>
</h:form>
</body>
When i try to execute on Glassfish gives the follow error :
javax.servlet.ServletException: <f:ajax> contains an unknown id 'm_name' - cannot locate it in the context of the component name
But if i change <rich:message ..> by <h:message..> it works (I want it works with rich:message because it returns an image and a message )
Why this is happening ? Never happened with me before, until now.
The RichFaces component reference tells this about the <rich:messages>:
13.1.1. Basic usage
...
The <rich:message> component is automatically rendered after an Ajax request. This occurs without the use of an component or a specific reference through the render attribute of the Ajax request source.
So, I'd just remove the render attribute on m_name and replace <f:ajax> by <a4j:ajax>.
<h:inputText id="name" value="#{register.person.name}" >
<a4j:ajax event="blur" listener="#{register.validateName}" />
</h:inputText>
<rich:message id="m_name" for="name" />
If you want to explicitly specify it anyway, you can set ajaxRendered="false" on the <rich:message> component.
<h:inputText id="name" value="#{register.person.name}" >
<f:ajax event="blur" listener="#{register.validateName}" render="m_name" />
</h:inputText>
<rich:message id="m_name" for="name" ajaxRendered="false" />
Looks like a richfaces behavior to me. I suspect you will have to file a bug report.
A work-around is to enclose the rich:message tag inside a rich:message tag inside a div tag, then give the div tag an id="m_name".

Resources