p:steps example not functioning - jsf

I'm trying use the STEPS component - Primefaces. But in the documentation the tutorial is very poor.
Can someone write an example using steps with property rendered or something like that, how Can I show and hide a panel using STEPS component.
I tried like this but does not work
My xhtml
<p:steps id="testSteps">
<p:menuitem value="Personal" update="testSteps" actionListener="#{BeanTest.shown2()}"/>
<p:menuitem value="Seat Selection" update="testSteps"/>
</p:steps>
<form id="formShowField1" >
<p:panel rendered="#{BeanTest.showfield1}">
<p:outputLabel value="FORM 1"/>
</p:panel>
</form>
<form id="formShowField2">
<p:panel rendered="#{BeanTest.showfield2}">
<p:outputLabel value="FORM 2" />
</p:panel>
</form>
My bean
public void shown1(){
showfield1 = true;
updateEntirePage("formShowField1");
}
public void shown2(){
showfield1 = false;
updateEntirePage("formShowField1");
showfield2 = true;
updateEntirePage("formShowField2");
}

As stated by comments, there are multiple issues with your XHTML code.
1) Use <h:form> instead of <form>
2) The p:steps component is readonly by default. Set readonly="false" in order to have interactive menu items. In this mode, it needs to be placed somwhere inside a h:form to - I get a javax.faces.FacesException: MenuItem must be inside a form element else.
3) Your menuItems update the p:steps component only. Your other panels won't ever show up this way as they are not updated. You should update an element containing them too. Don't know what updateEntirePage is though, especially when invoked twice.
4) Bean names like Java variables typically start with lower case character.
Try it like this:
<h:form>
<p:steps id="testSteps" readonly="false">
<p:menuitem value="Personal" update="#form" actionListener="#{beanTest.shown2()}"/>
<p:menuitem value="Seat Selection" update="#form"/>
</p:steps>
<p:panel rendered="#{neanTest.showfield1}">
<p:outputLabel value="FORM 1"/>
</p:panel>
<p:panel rendered="#{beanTest.showfield2}">
<p:outputLabel value="FORM 2" />
</p:panel>
</h:form>
And in your bean:
public void shown2(){
showfield1 = false;
showfield2 = true;
}

Related

Creating master-detail table and dialog, how to reuse same dialog for create and edit

I am attempting to create a dialog that will serve the purpose of both creating objects and updating them. So if I happen to click the 'new' button I will be presented a dialog containing empty fields to be filled or if I click on an edit button for an entry, that entry's data will presented in the dialog for update.
Following the example in the primefaces showcase for version 5.2, I can present the data in a read only outputText form, however when I change it to an inputText, the field remains empty. The following code is an example of what I have:
<h:form id="form">
<p:dataGrid id="guestList" var="guest" value="${guestList.guests}" columns="3" paginator="true" rows="20">
<f:facet name="header">
Guest List
</f:facet>
<p:panel>
<h:outputText value="${guest.name}" />
<br />
<h:outputText value="${guest.street}" />
<br />
<h:outputText rendered="#{guest.street2.length() gt 0}"
value="${guest.street2}" />
<h:panelGroup rendered="#{guest.street2.length() gt 0}">
<br />
</h:panelGroup>
<h:outputText value="${guest.city}, " />
<h:outputText value="${guest.state} " />
<h:outputText value="${guest.zipCode}" />
<p:commandButton update="#form:newGuestDetail" oncomplete="PF('newGuestDialog').show()" icon="ui-icon-edit" styleClass="ui-btn-inline">
<h:outputText styleClass="ui-icon ui-icon-edit" style="margin:0 auto;" />
<f:setPropertyActionListener value="#{guest}" target="#{guestList.selectedGuest}" />
</p:commandButton>
</p:panel>
</p:dataGrid>
<p:dialog header="#{guestList.hasSelected() ? 'Edit Guest' : 'New Guest'}" widgetVar="newGuestDialog" modal="true" showEffect="fade" hideEffect="fade">
<p:outputPanel id="newGuestDetail">
<h:outputText value="'#{guestList.selectedGuest.name}'"/>
<p:inputText id="guestName" value="#{guestList.hasSelected() ? '' : guestList.selectedGuest.name}" pt:placeholder="Name"/>
<p:commandButton value="#{guestList.selectedGuest == null ? 'Create Guest' : 'Update Guest'}"/>
</p:outputPanel>
</p:dialog>
</h:form>
The hasSelected() method evaluates whether the selected guest is null or not, returning true if not null. The selectedGuest should be set when the commandButton is clicked so that an object is available for retrieval by the dialog, however, with tracers in the get/set for selectedGuest, I am not seeing the setter called with the above snippet. If I remove the inputText, then even though the hasSelected is still returning false, and thus the 'New Guest' is heading the dialog, the outputText is filled with a value.
I found this great post talking about the order of execution with respect to the action, action listener, etc., but don't think this quite my issue: Differences between action and actionListener.
So the ultimate question is why will my setter get called with the command button when I only have an outputText, but with an inputText, I never see it called in the log?
I appreciate the time and help anyone can provide.
Even if we fix your problem, this construct
<p:inputText value="#{guestList.hasSelected() ? '' : guestList.selectedGuest.name}">
is not ever going to work. It needs to reference a model property, not an empty string.
You'd best just reuse the edit form and let the create button precreate an empty entity. This would simplify a lot in the view side. It'd be more easy if the entity has an #Id property which is only present when it's persisted in the database.
Here's a kickoff example:
<h:form id="entitiesForm">
<p:dataTable id="entitiesTable" value="#{bean.entities}" var="entity">
<p:column>#{entity.foo}</p:column>
<p:column>#{entity.bar}</p:column>
<p:column>
<p:commandButton id="edit" value="Edit"
process="#this" action="#{bean.edit(entity)}"
update=":entityDialog" oncomplete="PF('entityDialog').show()" />
<p:commandButton id="delete" value="Delete"
process="#this" action="#{bean.delete(entity)}"
update=":entitiesForm:entitiesTable" />
</p:column>
</p:dataTable>
<p:commandButton id="add" value="Add"
process="#this" action="#{bean.add}"
update=":entityDialog" oncomplete="PF('entityDialog').show()" />
</h:form>
<p:dialog id="entityDialog" widgetVar="entityDialog"
header="#{empty bean.entity.id ? 'New' : 'Edit'} entity">
<h:form id="entityForm">
<p:inputText id="foo" value="#{bean.entity.foo}" />
<p:inputText id="bar" value="#{bean.entity.bar}" />
<p:commandButton id="save" value="#{empty bean.entity.id ? 'Create' : 'Update'} entity"
process="#form" action="#{bean.save}"
update=":entitiesForm:entitiesTable" oncomplete="PF('entityDialog').hide()" />
</h:form>
</p:dialog>
With this #ViewScoped bean:
private List<Entity> entities; // +getter
private Entity entity; // +getter
#EJB
private EntityService entityService;
#PostConstruct
public void load() {
entities = entityService.list();
entity = null;
}
public void add() {
entity = new Entity();
}
public void edit(Entity entity) {
this.entity = entity;
}
public void save() {
entityService.save(entity); // if (id==null) em.persist() else em.merge()
load();
}
public void delete(Entity entity) {
entityService.delete(entity); // em.remove(em.find(type, id))
load();
}
See also:
Creating master-detail pages for entities, how to link them and which bean scope to choose
Keep p:dialog open when a validation error occurs after submit

Button in dialog inside p:dialog is not calling controller method

I've got a problem as described in the title.
Small description of the problem is as following:
I have button which is used to open dialog. Then, inside that dialog, there is button which opens another dialog on top of the first one. After clicking second button I want method from controller to be called but nothing happens. Value in h:outputText is read properly, so I guess it is not a problem with connection controller->view.
I'm using:
Spring web 3.1.2.RELEASE
JSF 2.2.10
Primefaces 5.1
Code:
beans.xml
<bean id="testController" class="test.TestController" />
TestController.java
public class TestController implements Serializable
{
private static final long serialVersionUID = 7028608421091861830L;
private String test;
public TestController()
{
test = "abc";
}
public void testMethod()
{
test = "cba";
}
public String getTest()
{
return test;
}
}
test.xhtml
<h:panelGrid columns="1" cellpadding="5">
<p:commandButton value="Basic" type="button" onclick="PF('dlg1').show();" />
</h:panelGrid>
<p:dialog widgetVar="dlg1">
<h:outputText value="Resistance to PrimeFaces is futile!" />
<h:panelGrid columns="1" cellpadding="5">
<p:commandButton value="Basic" type="button" onclick="PF('dlg2').show();" />
</h:panelGrid>
<p:dialog widgetVar="dlg2">
<h:outputText value="#{testController.test}" />
<p:commandButton value="Call method" type="button" actionListener="#{testController.testMethod}" />
</p:dialog>
</p:dialog>
What I tried:
adding appendToBody="true" to each p:dialog
changing from p:commandButton to p:button
changing from actionListener to action
but nothing helps.
I would be grateful for any help or advice of what can be the reason of not calling given method.
There are 3 problems.
You're nesting <p:dialog> components. This doesn't make sense. Separate them.
A <p:dialog> must have its own <h:form>, particularly when you explicitly use appendToBody="true" or appendTo="#(body)", otherwise nothing can be submitted because JavaScript would relocate the dialog out of its position in the HTML DOM tree to the end of body, causing it to not be sitting in a form anymore.
A <p:commandButton type="button"> acts as a "click" button, not as a submit button. Remove that attribute from submit buttons.
All in all, this is how it should look like:
<h:form>
<h:panelGrid columns="1" cellpadding="5">
<p:commandButton value="Basic" type="button" onclick="PF('dlg1').show();" />
</h:panelGrid>
</h:form>
<p:dialog widgetVar="dlg1">
<h:form>
<h:outputText value="Resistance to PrimeFaces is futile!" />
<h:panelGrid columns="1" cellpadding="5">
<p:commandButton value="Basic" type="button" onclick="PF('dlg2').show();" />
</h:panelGrid>
</h:form>
</p:dialog>
<p:dialog widgetVar="dlg2">
<h:form>
<h:outputText value="#{testController.test}" />
<p:commandButton value="Call method" actionListener="#{testController.testMethod}" />
</h:form>
</p:dialog>
OK. I guess I found a way to fix this problem.
It seems that the problem was:
type="button"
I deleted it from the list of attributes of each button and now it works even without h:form. Thanks for help.

navigation by action for p:menuitem doesn't work

I am currently using PrimeFaces 5.
I have this method in a bean called home:
public String panelSearch() {
pnlsearch = true;
return "home";
}
pnlsearch is a property that makes a panel visible
home.xhtml contains:
<p:menubar>
<p:menuitem id="mnusearch"
value="Search"
ajax="true"
action="#{home.panelSearch}"
icon="ui-icon-search" />
<p:menuitem value="Search" >
<p:commandLink ajax="false"
action="#{home.panelSearch}"
value="Search" />
</p:menuitem>
</p:menubar>
<h:panelGrid rendered="#{home.pnlsearch}">...</h:panelGrid>
panelSearch is called with action in both p:menuitem and in p:commandLink
but panelSearch is visible only with p:commandLink
Why panelSearch is not made visible with a click on p:menuitem alone as well?
note: p:commandLink is called no matter the navigation-rule in faces-config.xml

How to Hide/show <p:toolbar> onclick of a <p:menuitem>

I am working with JSF 2.0 and primefaces 3.3. I want to hide/show a toolbar onclick of a menuitem.
Here is the more info.
<p:menubar autoSubmenuDisplay="true" style="width:99%">
<p:submenu label="Projects">
<p:menuitem id="m11" value="Select Product" actionListener="#{menuBean.renderTool}" update="t1" />
<p:menuitem id="m12" value="Select Project" />
<p:menuitem id="m13" value="Select Contract" />
</p:submenu>
<p:menuitem id="m2" value="Global" />
<p:menuitem id="m7" value="Exit" />
</p:menubar>
<p:toolbar id="t1" rendered="#{menuBean.renderToolbar}">
<p:toolbarGroup align="left" style="height:20px;">
<h:outputText value="Projects " />
<h:outputText value=" - select Product" />
</p:toolbarGroup>
</p:toolbar>
ManagedBean
private boolean renderToolbar = false;
//getters and setters
public void renderTool(ActionEvent actionEvent){
System.out.println("inside renderTool method...");
renderToolbar = true;
}
The actionListener method is executing But, it's not updating or rendering the toolbar.
add some boolean variable to your bean
boolean someBoolean; //+ getter/setter
and inside your renderToolbar method add
someBoolean = !someBoolean; // toggle the disaplay on and off
in xhtml change
<p:toolbar id="t1" rendered="#{menuBean.renderToolbar}">
into
<h:panelGroup id="t1">
<p:toolbar rendered="#{menuBean.someBoolean}">
.
.
.
</h:panelGroup>
Not much info that you provided.
However, one way to do it is using Javascript with the onclick event handler.
Like this (untested code):
<p:toolbar id="toolbarID" />
<p:menu>
<p:menuitem onclick="$('#toolbarID').toggle();" />
</p:menu>
I think primefaces already includes jquery so you should be able to use jquery selectors out of the box.
The solution Daniel provided works using a backing bean. However if showing/displaying some element isn't dependent on data but is more a client-side thing or a simple user controlled element I would advice against using a backing bean. Using a backing bean for client-side stuff causes delays or as a regular user would put it: "It's slow".
In stead use client side things like JavaScript as Jens suggested. Since you're using PrimeFaces you can make use of jQuery. A simple example to demonstrate jQuery's toggle(), show() and hide() functions:
<h:form>
<p:menubar>
<p:menuitem value="Toggle" onclick="$("[id='t1']").toggle()" />
<p:menuitem value="Show" onclick="$("[id='t1']").show()" />
<p:menuitem value="Hide" onclick="$("[id='t1']").hide()" />
</p:menubar>
</h:form>
<p:toolbar id="t1" />
Note that if your p:toolbar lives in a container like a form or such the client-side ID is prefixed with the form's ID.

Primefaces dialog is rendering twice

I've created an ui:component to use like a popup, so I can create a lot of popups using the standard of this template.
The component is just a popup with two buttons (cancel and submit) and a content that can be overriden, like you can see here:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.prime.com.tr/ui">
<ui:component>
<p:dialog widgetVar="#{idPopup}" id="#{idPopup}" modal="#{popup.modal}"
draggable="#{popup.modal}"
rendered="#{popup.visivel}" visible="#{popup.visivel}"
closeOnEscape="false" closable="false" header="#{titulo}"
resizable="false" styleClass="autoWidthDialog" showEffect="fade"
hideEffect="fade">
<h:panelGroup style="width:100%">
<p:focus />
<ui:insert name="conteudo">Nenhum conteúdo definido!</ui:insert>
<h:panelGrid id="#{idPopup}PainelMensagens" style="width:100%">
<p:messages />
</h:panelGrid>
<ui:insert name="barraDeBotoes">
<h:panelGroup layout="block" style="width:100%">
<p:commandButton value="CANCELAR" immediate="true" update="#form"
style="float:right" action="#{controladorPopup.fechar}"
onclick="#{idPopup}.hide();" />
<p:commandButton value="OK" style="float:right"
update="#form formAlerta"
action="#{controladorPopup.submit}"
process="#form" />
</h:panelGroup>
</ui:insert>
</h:panelGroup>
</p:dialog>
</ui:component>
</html>
The problem happen when I try to submit the form without filling the required fields. The correct behavior is just show again the popup with messages, but the dialog is rendered twice, one with the messages and one without the messages.
You can see this behavior here:
this is one use of this template:
<ui:composition template="../templates/popupSubmit.xhtml">
<ui:param name="titulo" value="Buscar pessoa" />
<ui:param name="popup" value="#{modeloPopupBuscaPessoa}" />
<ui:param name="controladorPopup"
value="#{controladorPopupBuscaPessoa}" />
<ui:define name="conteudo">
<h:panelGroup>
<h:panelGrid columns="2">
<h:outputLabel value="Tipo de cadastro:" style="float:none" />
<h:selectOneMenu value="#{controladorSugestaoPessoa.tipoCadastro}"
immediate="true">
<f:selectItems value="#{carregadorTipoCadastro.itens}" />
<f:ajax event="change" immediate="true" />
</h:selectOneMenu>
</h:panelGrid>
<h:outputText value="Buscar por:" />
<h:selectOneRadio value="#{controladorSugestaoPessoa.tipoBusca}"
immediate="true">
<f:selectItems value="#{carregadorTipoBuscaPessoa.itens}" />
<f:ajax event="change" immediate="true" />
</h:selectOneRadio>
<p:autoComplete value="#{modeloPopupBuscaPessoa.itemSelecionado}"
forceSelection="true" maxResults="10" queryDelay="500"
completeMethod="#{controladorSugestaoPessoa.atualizarSugestoes}"
var="pessoa" itemLabel="#{pessoa.label}" itemValue="#{pessoa}"
converter="#{conversorSelectItem}" />
</h:panelGroup>
</ui:define>
</ui:composition>
And these are some use:
<h:form id="cadastroPessoa">
<ui:include
src="resources/components/popups/modulo_cadastro/popupNovoCadastroPessoa.xhtml">
<ui:param name="idPopup" value="popupNovoCadastroPessoa" />
</ui:include>
<ui:include
src="resources/components/popups/modulo_cadastro/popupCadastroPessoa.xhtml">
<ui:param name="idPopup" value="popupEdicaoCadastroPessoa" />
</ui:include>
<ui:include
src="resources/components/popups/modulo_cadastro/popupBuscaPessoa.xhtml">
<ui:param name="idPopup" value="popupBuscaCadastroPessoa" />
</ui:include>
</h:form>
<h:form id="cadastroProduto">
<ui:include
src="resources/components/popups/modulo_cadastro/popupCadastroProduto.xhtml">
<ui:param name="idPopup" value="popupNovoCadastroProduto" />
</ui:include>
</h:form>
Could someone tell me why this is happening??
I've posted the same question in primefaces forum (like Tommy Chan told), and someone answered this:
You are probably placing your dialog in the form you are updating which is a nono. Never update the dialog only the stuff in the dialog
I've tried to do this until I saw all my dialogs have "rendered" attribute coming from server (just see the first xml), I have a lot of dialogs in this application and some of them have relation with others (on server), these last are on the same form.
I did something different, I only created this javascript code:
function removerDialogo(id) {
setTimeout(function() {
removerDialogoAposIntervalo(id);
}, 100);
}
function removerDialogoAposIntervalo(id) {
id = id.replace(':', '\\:');
jQuery('div.ui-dialog')
.find('#' + id)
.parent().eq(1)
.remove();
}
and called this on dialog "onShow" attribute:
<p:dialog widgetVar="#{idPopup}" id="#{idPopup}" modal="#{popup.modal}"
draggable="#{popup.modal}" rendered="#{popup.visivel}"
visible="#{popup.visivel}" closeOnEscape="false" closable="false"
header="#{titulo}" resizable="false" styleClass="autoWidthDialog"
showEffect="fade" hideEffect="fade" onShow="removerDialogo(this.id)">
I don't like to do things like this, but I can't find a better way to solve this...
If someone give me a better solution, I will be grateful
In my case I cannot user oncompleteI) method to hide the dialog because it has to be closed to some business logic.
I my case I have use primefaces tabs on UI. Every time I navigate the tabs and then click on button on which dialog appears then my dialogs number are increasing proportionality
So I have used simple jquery script to remove all the duplication dialog from the UI
e UI.
function removeDuplicateDialogs(dialogId) {
\\ generally all our components have : character we have to
\\ replace ':' with '\\:'(applying escape character)
dialogId = dialogId.replace(/\:/g, '\\:');
var dialogs = jQuery("div[id=" + dialogId + "]");
var numOfDialogs = dialogs.length;
numOfDialogs = numOfDialogs - 1;
for (var i = 0; i < numOfDialogs; i++) {
jQuery(dialogs[i]).remove();
}
}
As i said on the primefaces forum, you are updating your forms with the dialog in it... you need to place your dialogs out of your form and update them seperatly. If you need to use a form in your dialog then place it in you dialog:
<p:dialog><p:form> </p:form> </p:dialog>
I had the same problem with a dialog, the solution was place in the update of the commandButton that show the dialog component the specific id of the Dialog Component not the form id, the solution looks like this:
<p:dialog id="dialogId">
<p:commandButton value="OK" style="float:right"
update="#form dialogId"
action="#{controladorPopup.submit}"
process="#form"/>
</p:dialog>
I would check that your widgetVar="#{idPopup}" id="#{idPopup}" is the same before you submit and after you submit the form. Maybe it has changed and primefaces thinks it doesn't exist anymore and creates a new one.
Add the oncomplete attribute to your submit button and let it hide the dialog:
<p:commandButton value="OK" style="float:right"
update="#form formAlerta"
action="#{controladorPopup.submit}"
process="#form"
oncomplete="#{idPopup}.hide();"/>
putting the forms inside dialog isnt the best way to solve it, if you access your application with IExplorer, dialogs wont work with this approach
This is an awful bug with no official answer...
I'm using a dialog to render a Google map. The way I handle the bug (using JQuery) is by counting the number of ".map" elements in the DOM on primefaces:dialog.onShow... I then select the :last .map instance rendered (or in your case, whatever content class you're working with), and .remove() the dialog which contains it:
Markup (approx):
<pri:dialog onShow="popupOpen();" etc...>
<div id="map" class"map"></div>
</pri:dialog>
JavaScript:
function onShowDialog(){
if($(".map").length > 1){
$cull = $(".map:last");
$cull.closest(".ui-dialog").remove();
}
}
If you're a sadist you could, quite comfortably, make that a one liner... I see this as a Primefaces bug. The close button should outright destroy the dialog.

Resources