I´m getting confused why the component p:fileUpload doesn´t call the fileUploadListener once the component is shown by the p:ajax. If I put it outside the panelGrids or even remove them, works just fine.
What isn´t working:
<div class="pure-control-group">
<label for="mostraNoIndex">Slideshow</label>
<p:selectBooleanCheckbox value="#{destaqueCadastrarBean.d.apareceNoSlide}">
<p:ajax event="change" update="upload"></p:ajax>
</p:selectBooleanCheckbox>
</div>
<h:panelGrid id="upload">
<h:panelGrid rendered="#{destaqueCadastrarBean.d.apareceNoSlide}">
<div class="pure-control-group">
<label for="mostraNoIndex">Imagem</label>
<p:fileUpload fileUploadListener="#{destaqueCadastrarBean.handleFileUpload}" mode="advanced" dragDropSupport="true" sizeLimit="100000000000" fileLimit="1" allowTypes="/(\.|\/)(gif|jpe?g|png)$/" />
</div>
</h:panelGrid>
</h:panelGrid>
What works:
<div class="pure-control-group">
<label for="mostraNoIndex">Slideshow</label>
<p:selectBooleanCheckbox value="#{destaqueCadastrarBean.d.apareceNoSlide}">
</p:selectBooleanCheckbox>
</div>
<div class="pure-control-group">
<label for="mostraNoIndex">Imagem</label>
<h:fileUpload fileUploadListener="#{destaqueCadastrarBean.handleFileUpload}" mode="advanced" dragDropSupport="true" sizeLimit="100000000000" fileLimit="1" allowTypes="/(\.|\/)(gif|jpe?g|png)$/" />
</div>
Just found out a solution for it. The bean being called was RequestScoped, changed it to ViewScoped. I guess cause the bean was requested when the form loaded and p:fileUpload can only appears after the creation of the bean, the component couldn´t reach the bean. With view scope the bean is available for components that comes afterward. If someone has a more technical and clear explanation I would like to understand better.
Related
I am using two tags <h:selectOneMenu> and <p:pickList>. I want to render <p:pickList> tag when an entry in the <h:selectOneMenu> is selected.
Earlier after page loading the add, add all other controls are visible as pickList controls but after rendering this pickList, these controls change to jsf buttons with no functionality of pickList.
Here is the snippet code(xhtml file):
<div class="form-group form-md-line-input">
<label class="col-md-2 control-label">#{texts['person.userrole']}
</label>
<h:selectOneMenu
value="#{userroleDataActions.actualUserRole.rolename}">
<f:selectItems value="#{userroleDataActions.roles}" />
<f:ajax listener="#{userroleSaveActions.rolelistener}"
render="projects"/>
</h:selectOneMenu>
<p:messages styleClass="error" />
</div>
<p:pickList id="projects"
value="#{userroleSaveActions.projectDualList}" var="projects"
itemLabel="#{projects}" itemValue="#{projects}"
converter="projectConverter" required="true" />
This question already has an answer here:
Custom JSF validator message for a single input field
(1 answer)
Closed 7 years ago.
how to add my own message for the client side validation in JSF.
<div class="ui-grid-row">
<div class="ui-grid-col-3" align="left">
<h:outputLabel for="cmpny" value="Company Name:" style="font-weight:bold" />
</div>
<div class="ui-grid-col-2">
<p:inputText id="cmpny" value="#{userData.cmpny}">
<f:validateLength minimum="10" />
<p:ajax execute="currentInput" update="company" event="blur" />
</p:inputText>
</div>
<div class="ui-grid-col-1" />
<div class="ui-grid-col-1">
<p:message for="cmpny" id="company" display="icon" />
</div>
<div class="ui-grid-col-5"></div>
</div>
</div>
<div class="ui-grid-col-3" align="left">
<h:outputLabel for="fnm" value="First Name:*" />
</div>
<div class="ui-grid-col-2">
<p:inputText id="fnm" value="#{userData.fnm}" validatorMessage="First Name cannot be left blank and must be greater than 3 characters" >
<f:validateLength minimum="4" />
<p:ajax execute="currentInput" update="firstname" event="blur" process="#this" />
</p:inputText>
</div>
<div class="ui-grid-col-7"><p:message for="fnm" id="firstname" display="icon,text"/></div>
With the help of "validatorMessage" attribute, I am able to show customized messages when ever the validation fails for the primeface elements like (inputText,calendar etc..,),.
You need to supply a message bundle via javascript. See PrimeFacesLocales for examples.
PrimeFaces User Guide, 7. Client Side Validation / 7.4 Messages.
Using f:ajax component with h:selectManyListbox, it is firing the listener method but not refreshing the rendering list.
I have Market. When I select market it needs to display Sub-Markets. Initial page load will have all the Markets and Sub-Markets, but it needs to filter when user selects "Market".
Using below code:
<ui:fragment id="uda2" rendered="#{udaList.index eq 1}">
<div class=" row form-group" >
<label class="col-sm-2" for="sel-service">Market:</label>
<div class="col-sm-10">
<h:selectManyListbox style="width:360px;" multiple="" pt:aria-required="true" required="required" pt:data-toggle="chosen"
disabled="# {licenseSelectionBean.isFieldEnabled(FormFieldsEnum.ITEM_UDA2)}"
id="#{FormFieldsEnum.ITEM_UDA2.getFieldCode()}" size="1"
name="#{FormFieldsEnum.ITEM_UDA2.getFieldCode()}"
value="#{licenseSelectionBean.selectedItemUda2}"
styleClass="sel-chosen">
<f:selectItems var="uda2"
value="#{licenseSelectionBean.selectUda2}" />
<f:ajax event="change" execute="#this" render="#this udalist3"
listener="#{licenseSelectionBean.onChangeFilter()}" />
</h:selectManyListbox>
</div>
</div>
</ui:fragment>
<ui:fragment rendered="#{udaList.index eq 2}">
<div class="row form-group" >
<label class="col-sm-2" for="sel-service">Sub-Market:</label>
<div class="col-sm-10">
<h:selectManyListbox style="width:360px;" multiple="" pt:aria-required="true" required="required" pt:data-toggle="chosen"
disabled="#{licenseSelectionBean.isFieldEnabled(FormFieldsEnum.ITEM_UDA3)}"
size="1"
pt:name="udalist3"
value="#{licenseSelectionBean.selectedItemUda3}"
pt:id="udalist3"
styleClass="sel-chosen">
<f:selectItems var="uda3"
value="#{licenseSelectionBean.selectUda3}" />
<!-- <f:ajax render="#{FormFieldsEnum.ITEM_UDA4.getFieldCode()}"
listener="#{licenseSelectionBean.onChangeFilter()}" /> -->
</h:selectManyListbox>
</div>
</div>
</ui:fragment>
Used "pt" for pass-through because JSF prefixing dynamic id.
How to resolve this problem?
Simple solution. Replace
<f:ajax event="change" execute="#this" render="#this udalist3"
listener="#{licenseSelectionBean.onChangeFilter()}" />
with
<f:ajax event="change" execute="#this" render="#form"
listener="#{licenseSelectionBean.onChangeFilter()}" />
This might cause some unnecesarry traffic. You can also encapsulate the second ui:fragment in a panelgroup, e.g.
<h:panelGroup id="wrapper">
<ui:fragment rendered="#{udaList.index eq 2}">
....
</h:panelgroup>
and add replace "udalist3" with "wrapper" in the f:ajax render attribute.
My main form is the following:
<h:form id="frmSearch" styleClass="m-bottom">
<div class="form-group">
<label>Funcionário</label>
<h:inputText id="funcionario" value="#{escalaTrabalhoBean.entityToSearch.funcionario.pessoa.nome}" readonly="true" styleClass="form-control" />
<h:commandButton id="btnFuncionario" styleClass="btn btn-default" value="Buscar funcionário" onclick="$('#modBuscaFuncionario').modal('show')" type="button" />
</div>
</h:form>
And I want to update the value of field "funcionario" after I call a function with ajax, which is inside a modal window:
<h:form id="frmSearchBuscaFuncionario">
<h:commandLink id="btnSelecionar" title="Selecionar" actionListener="#{escalaTrabalhoBean.selectFuncionario(obj)}">
<i class="fa fa-pencil-square-o"></i>
<p:ajax oncomplete="$('#modBuscaFuncionario').modal('hide');" update="frmSearch:funcionario" />
</h:commandLink>
</h:form>
This code: update="frmSearch:funcionario" is not working, and I got this error: javax.faces.FacesException: Cannot find component with identifier "frmSearch:funcionario".
Any suggestions?
When you access the components outside of your current h:form use : at the beginning of the Id of the component.
In your example:
update=":frmSearch:funcionario"
I'm having a bit of trouble getting AJAX calls to fire properly in a nested composite component with Mojarra 2.0.3 and PrimeFaces.
The child composite component looks something like this:
<cc:interface componentType="therapy">
<cc:attribute name="therapyType" type="java.lang.String" required="true"/>
<cc:attribute name="patientId" type="java.lang.String" required="true"/>
<cc:attribute name="showHistory" type="java.lang.Boolean" required="false" default="true"/>
<cc:attribute name="width" type="java.lang.String" required="false" default="350px"/>
<cc:attribute name="maxHistory" type="java.lang.String" required="false" default="3"/>
<cc:attribute name="collectDoctor" type="java.lang.Boolean" required="false" default="false"/>
<cc:attribute name="collectCareDate" type="java.lang.Boolean" required="false" default="false"/>
<cc:attribute name="important" type="java.lang.Boolean" requred="false" default="false"/>
</cc:interface>
<cc:implementation>
<script>
function #{cc.clientId}Toggle(){
$("##{cc.clientId}_newbutton").toggle();
$("##{cc.clientId}_savebuttons").toggle();
if(#{cc.attrs.collectDoctor}){
$("##{cc.clientId}_doctor").toggle();
}
if(#{cc.attrs.collectCareDate}){
$("##{cc.clientId}_care").toggle();
}
$("##{cc.clientId}_newTherapy").toggle(50);
}
function #{cc.clientId}rowHighlight(event){
if(event.status == 'begin'){
$("##{cc.clientId}_loader").toggle();
}
if(event.status == 'success'){
$("##{cc.clientId}\\:histTable tr:eq(1)").effect("highlight", {color:"#FED17A", easing:"easeInCubic"}, 2000);
}
}
$(function(){
if(#{cc.attrs.important}){
$("div[class~='ui-panel-titlebar'][id^='#{cc.clientId}']").css("background", "#FED17A");
}
});
</script>
<h:form prependId="false">
<p:panel styleClass="mcoPanel" style="width:#{cc.attrs.width};">
<f:facet name="header">
<h:panelGroup>
<span id="#{cc.clientId}_title">#{cc.myType.word}</span>
<span id="#{cc.clientId}_newbutton" class="mcoPanel-controls">
<span onclick="#{cc.clientId}Toggle();">
<h:graphicImage name="page_new.gif" library="images"/>
</span>
</span>
<span id="#{cc.clientId}_savebuttons" class="mcoPanel-controls" style="display:none;">
<span id="#{cc.clientId}_loader" style="display:none;">
<h:graphicImage name="ajax-loader.gif" library="images" height="16" width="16"/>
</span>
<h:commandLink action="#{cc.saveNewTherapy}">
<f:ajax execute="newOnTherapy newExemption newDoctor newCareDate" render="#form" onevent="#{cc.clientId}rowHighlight"/>
<h:graphicImage name="action_save.gif" library="images"/>
</h:commandLink>
<span onclick="#{cc.clientId}Toggle();">
<h:graphicImage name="page_cross.gif" library="images"/>
</span>
</span>
</h:panelGroup>
</f:facet>
<div id="#{cc.clientId}_newTherapy" class="mcoPanel-new" style="display:none;">
<h:outputLabel for="newOnTherapy" value="Satisfied:" style="position:relative; top: -10px;"/>
<p:selectOneMenu id="newOnTherapy" label="Satisfied" value="#{cc.newOnTherapyValue}" style="width: 60px;">
<f:selectItem itemLabel=""/>
<f:selectItems value="#{cc.yesNoList}"/>
</p:selectOneMenu>
<br/>
<h:outputLabel for="newExemption" value="Exemption:" style="position:relative; top: -10px;"/>
<p:selectOneMenu id="newExemption" value="#{cc.newExemption}" style="width: 150px;">
<f:selectItems value="#{cc.exemptions}"/>
</p:selectOneMenu>
<span id="#{cc.clientId}_doctor" style="display:none">
<br/>
<h:outputLabel for="newDoctor" value="Doctor:"/>
<p:inputText id="newDoctor" value="#{cc.newDoctor}"/>
</span>
<span id="#{cc.clientId}_care" style="display:none">
<br/>
<h:outputLabel for="newCareDate" value="Care Date:"/>
<p:calendar id="newCareDate" label="Care Date" value="#{cc.newCareDate}" showButtonPanel="true">
<f:converter converterId="dateOfBirthConverter"/>
</p:calendar>
</span>
</div>
<h:messages id="#{cc.clientId}_messages" errorClass="errorMessage"/>
<p:dataTable id="histTable" value="#{cc.history}" var="item" rendered="#{cc.attrs.showHistory}">
<!-- Table Output -->
</p:dataTable>
</p:panel>
</h:form>
And the parent composite component looks something like this:
<cc:interface>
<cc:attribute name="title" type="java.lang.String" required="true"/>
</cc:interface>
<cc:implementation>
<h:outputScript name="containerpanel.js" library="js/components" target="head"/>
<p:panel toggleable="true" styleClass="contentPanel" toggleSpeed="500" style="width:1100px;">
<f:facet name="header">
#{cc.attrs.title}
<div class="ui-panel-titlebar-icon ui-corner-all ui-state-default contentSaveAll">
Save All
</div>
<div class="ui-panel-titlebar-icon ui-corner-all ui-state-default contentExpandAll">
++
</div>
<div class="ui-panel-titlebar-icon ui-corner-all ui-state-default contentCollapseAll">
- -
</div>
</f:facet>
<cc:insertChildren>
<!-- Child components go here -->
</cc:insertChildren>
</p:panel>
</cc:implementation>
The implementation is supposed to allow for any number of child components inside the container component.
The child components send ajax requests and update their internal components perfectly if they are placed on a page outside of the Container component. In addition, if I use the same structure of the container, but not an actual composite component, everything works just fine.
As soon as I place the child components as children of the Container component, that's where things go wonky. No ajax calls in the child components fire properly (i.e. the save commandLink) Using firebug to help debug this, I've been able to determine the following:
The ajax post request appears to be being sent. The "begin" onevent is firing, and looking at the console in firebug shows a post being made to the server, with the proper component ids and values being sent back.
The action in the backing bean is not being called. I have a print statement as the first line and it's not printing.
The ajax request appears to be completing properly, the "success" onevent is firing.
Nothing is being updated on the page. The form does not refresh, nor does the p:messages object at the top of the page.
Obviously I can do this without the Container component, but I would prefer to be able to of course take advantage of code reuse. Am I missing something obvious here that I need to do to get the ajax to work properly?
I am having the exact same problem with MyFaces 2.1.6.
I can't make AJAX calls from nested Composite Components using ClientBehavior in the interface of the CC.
Like moneyT wrote the server is being notified of the events specified in the ajax tag, but when the lifecycle went to phase 5 - Invoke Application, the event was null and no listener was called. More and more it looks like a bug in the implementation of MyFaces.
EDIT: I have found another solution which is much better than hardcoding ajax in the composite component. I have refactored the outer composite component to be facelet. It loses some of the quirks of the composites but it gets the job done. Also it is reusable.
The only solution (more of a workaraund than solution) I found is to hardcode ajax in the composite component rather than to use ClientBehavior, like this:
<composite:implementation>
<h:panelGroup layout="block" id="listBox" class="list-box-scroll-pane" style="height:#{cc.attrs.visibleLines*27 + 5}px; width:#{cc.attrs.width}px">
<h:inputText id="submit-value" style="visibility: hidden; width:0px; height: 0px;" value="#{cc.attrs.property}">
<f:ajax event="change"
render="carModel"
listener="#{carDetailsMediator.changeCarMake}"
onevent="initComboboxes"/>
</h:inputText>
<ui:repeat value="#{cc.attrs.items}" var="element" varStatus="loop">
<input id="input-#{cc.attrs.customId}-#{loop.index}" type="hidden"
value="#{element.value}" />
<div id="div-#{cc.attrs.customId}-#{loop.index}" class="list-box-row">#{element.label}</div>
</ui:repeat>
</h:panelGroup>
</composite:implementation>
However this workaround is not very good, because the idea behind composite components is that you can reuse them with many different options. Hardcoding ajax in it kind of limits the options.
I believe your problem is this:
<f:ajax execute="newOnTherapy newExemption newDoctor newCareDate" ...
The execute attribute can refer to the special keywords (Eg. #this, #form, etc...) or according to the documentation:
If a literal is specified, it must be a space-delimited String of component identifiers and/or one of the keywords.
When you are inserting this component as a child to the parent component then the component Ids are going to by dynamically determined and can't be referred to absolutely.