Dynamically loaded commandlinks not working - java

I am trying to dynamically load a view using <f:ajax render=":component"/>.
That part works with no problems. Using commandLinks in that view, however, does not.
Container that loads the target view dynamically:
<h:form>
<h:commandLink>
<f:param name="tmp2" value="tmp/newxhtml.xhtml"/>
<f:ajax render=":newXhtml"/>
</h:commandLink>
</h:form>
<h:panelGroup layout="block" id="newXhtml">
<ui:include src="#{param['tmp2']}"/>
</h:panelGroup>
When clicking the commandLink, the tmp2 value is set and the 'newXhtml' is re-rendered through ajax.
This link is on the included .xhtml and is not working:
<h:form>
<h:commandLink>
<f:ajax listener="#{backingBean.sampleMethod}"/>
</h:commandLink>
</h:form>
BackingBean.java:
public class BackingBean{
public void sampleMethod() {
//breakpoint here is never hit
}
}

I got it to work when I'm not using <f:ajax> to include the page but rather use normal <h:commandLink> with the action attribute which will save the include page into a #SessionScope bean.
The including xhtml:
<h:form>
<f:ajax render=":newXhtml">
<h:commandLink action="#{includeBean.setIncludePage('tmp/newXhtml.xhtml')}">
</h:commandLink>
</f:ajax>
</h:form>
<h:panelGroup layout="block" id="newXhtml">
<ui:include src="#{includeBean.includePage}"/>
</h:panelGroup>
The included .xhtml can stay the same.
And the backing bean for the include page:
#Named
#SessionScope
public class IncludeBean implements Serializable {
private static final long serialVersionUID = 1L;
private String includePage;
#PostConstruct
public void init() {
includePage = "tmp/newxhtml.xhtml";
}
public String getIncludePage() {
return includePage;
}
public void setIncludePage(String includePage) {
this.includePage = includePage;
}
}

Related

JSF - Using different instances of ManagedBean for same view in Primefaces wizard

I'm developing a web application with JSF 2.1 and Primefaces 5.1 in the front-end. I have a page that allows me to manage players (players.xhtml). In that page I include another one (search_players.xhtml) that defines the search functionality (it has the input fields and the dataTable showing the players):
players.xhtml
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:f="http://java.sun.com/jsf/core"
template="resources/templates/template.xhtml">
<ui:define name="contextual_content">
<ui:include src="resources/snippets/search_players.xhtml"/>
<p:commandButton id="add_player_button_id" value="#{msgs.add}" onclick="PF('dlg').show();" />
...
</ui:define>
</ui:composition>
search_players.xhtml
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:f="http://java.sun.com/jsf/core">
<h:form id="search_player_form_id">
<p:panelGrid columns="3">
<h:panelGroup layout="block" >
#{msgs.id}: <p:inputText value="#{playersBean.id}" styleClass="search_input_text" />
</h:panelGroup>
...
</p:panelGrid>
<p:dataTable id="players_table_id" var="player" value="#{playersBean.players}" rowKey="#{player.id}" paginator="true"
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
rowsPerPageTemplate="5,10,15" selectionMode="single" selection="#{playersBean.player}">
...
</p:dataTable>
</h:form>
</ui:composition>
As a backing bean, I have a ViewScoped managed bean that has the list of players to populate the table, the placeholders for the input fields and the selected player (from the table).
PlayersBean.java
#ManagedBean
#ViewScoped
public class PlayersBean implements Serializable {
private static final long serialVersionUID = 1L;
private static final Logger logger = LogManager.getLogger(PlayersBean.class);
/* List to populate table */
private List<DtoPlayer> players;
/* Placeholders */
private BigDecimal id;
...
/* Selected player*/
private DtoPlayer player;
#EJB
private PlayersService playersService;
#EJB
private StartupBean startupBean;
public PlayersBean() {
logger.entry();
}
#PostConstruct
public void init() {
...
}
public void searchPlayers() {
...
}
public void createPlayer() {
...
}
// getters and setters
}
Everything works fine here.
Now I want to have a page (similar to players.xhtml) that allows the management of configurations (configurations.xhtml). Creating a configuration involves a set of steps, for which I have created a wizard. In two of those steps, users have to choose a player (the source and the destination) - that's why I have the snippet for searching players defined in a separated .xhtml, to be able to reuse it now.
configurations.xhtml
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:f="http://java.sun.com/jsf/core"
template="resources/templates/template.xhtml">
<ui:define name="contextual_content">
<p:commandButton id="add_configuration_button_id" value="#{msgs.add}" onclick="PF('dlg').show();" />
<p:dialog header="#{msgs.add_configuration}" widgetVar="dlg" closeOnEscape="true" width="1050" height="600" minWidth="1050" minHeight="600">
<h:form id="create_configuration_form_id">
<p:wizard id="create_configuration_wizard" styleClass="wizard" widgetVar="wiz" flowListener="#{configurationsBean.handleFlow}">
<p:tab ...>
...
</p:tab>
<p:tab id="create_configuration_wizard_player_source_tab" title="#{msgs.source}">
<f:subview id="player_source">
<ui:include src="resources/snippets/search_players.xhtml"/>
</f:subview>
</p:tab>
<p:tab id="create_configuration_wizard_player_destination_tab" title="#{msgs.destination}">
<f:subview id="player_destination">
<ui:include src="resources/snippets/search_players.xhtml"/>
</f:subview>
</p:tab>
...
<p:tab id="create_configuration_wizard_confirm" title="#{msgs.confirm}">
<p:panel header="#{msgs.confirm}">
...
<p:commandButton id="save_configuration_button_id" value="#{msgs.save}" action="#{configurationsBean.createConfiguration}" onclick="PF('dlg').hide();" update=":search_configuration_form_id:configurations_table_id" />
</p:panel>
</p:tab>
</p:wizard>
</h:form>
</p:dialog>
</ui:define>
</ui:composition>
And for this page, I follow the same approach as with players: I have a ViewScoped managed bean. This one injects references to 2 instances of PlayersBean (the source and destination).
ConfigurationsBean.java
#ManagedBean
#ViewScoped
public class ConfigurationsBean implements Serializable {
private static final long serialVersionUID = 1L;
private static final Logger logger = LogManager.getLogger(ConfigurationsBean.class);
/* List to populate table */
private List<DtoConfiguration> configurations;
/* Placeholders */
private BigDecimal id;
...
#ManagedProperty(value="#{playersBean}")
private PlayersBean playersSourceBean;
#ManagedProperty(value="#{playersBean}")
private PlayersBean playersDestinationBean;
#EJB
private ConfigurationsService configurationsService;
#EJB
private StartupBean startupBean;
public ConfigurationsBean() {
logger.entry();
}
#PostConstruct
public void init() {
...
}
public void searchConfigurations() {
...
}
public void createConfiguration() {
try {
logger.entry();
logger.info(this.playersSourceBean == this.playersDestinationBean ? "same player" : "different players");
...
}
public String handleFlow(FlowEvent event) {
String currentStepId = event.getNewStep();
logger.info("CurrentStepId: " + currentStepId);
return event.getNewStep();
}
// getters and setters
}
And now the problem arises. The wizard gets created correctly but both source and destination player steps use the same PlayersBean instance. So I select the source player in the "Source Player" step, and when I step to the "Destination Player", the player in the table is already selected. In the end, when I submit, I can see that the source and destination players are the same. But I want to have 2 different instances! How can I solve this problem?
PS: In case you need to know any project configuration (like web.xml, faces-config.xml) let me know.

JF2 Dynamic form element doesn't remember input and page refreshes every time I add element

I am trying to make a form with options to add rows. However, after I type in some input and click the add button again, the input I enter disappears. I'm not sure what is wrong with my code. In addition, when I click the add button, the page refreshes. Is there way to stop this page refresh?
Person.java
public class Person{
private List<String> guys = new ArrayList<String>();
public List<String> getGuys() {
return guys;
}
public void setGuys(List<String> guys) {
this.guys = guys;
public void addNewItem(){
guys.add("");
}
}
form.xhtml
<h:form>
<h:panelGrid columns="2">
<h:outputText value="Guys: " />
<h:dataTable value="#{person.guys}" var="men">
<h:column>
<p:inputText value="#{men}" />
</h:column>
</h:dataTable>
<h:commandButton name="add" value="Add" action="#{person.addNewItem}" />
</h:panelGrid>
<br />
<h:commandButton name="submit" type="submit" value="Submit"></h:commandButton>
</h:form>
Provided that the bean is placed in the right scope for the functional requirement, the view scope, the only major mistake left is that you're expecting that the String class has some magic setter method.
It hasn't. The String class is immutable. The following will never work on a String:
<p:inputText value="#{men}" />
You have 2 options:
Create a real model class. You can find complete examples in the following answers:
How to dynamically add JSF components
Recommended JSF 2.0 CRUD frameworks
Set the value by row index instead:
<h:dataTable binding="#{table}" value="#{person.guys}">
<h:column>
<p:inputText value="#{person.guys[table.rowIndex]}" />
</h:column>
</h:dataTable>
(note: no additional bean property necessary for the table! the code is as-is)
This does basically a person.getGuys().add(table.getRowIndex(), submittedValue). I.e. the setter is invoked on the List itself, which works perfectly fine. See also the following related answers concerning ui:repeat:
Using <ui:repeat><h:inputText> on a List<String> doesn't update model values
How map multiple inputText to an array property?
You never update your list, you are just adding empty items. You should do something like this:
Person.java (viewscoped)
public class Person implements Serializable {
private List<String> guys = new ArrayList<String>();
private HtmlDataTable dtGuys;
public void addNewItem() {
guys.add("");
}
public void addToList(ValueChangeEvent e) {
guys.set(dtGuys.getRowIndex(), e.getNewValue().toString());
}
public String save() {
System.out.println("saving...");
for (String item : guys) {
System.out.println("item= " + item);
}
return null;
}
//gettes and setters
}
form.xhtml
<h:form id="frmPrincipal">
<h:panelGrid columns="2">
<h:outputText value="Guys: " />
<h:dataTable value="#{person.guys}" var="men" binding="#{person.dtGuys}" >
<h:column>
<p:inputText value="#{men}" valueChangeListener="#{person.addToList}" />
</h:column>
</h:dataTable>
<h:commandButton name="add" value="Add" action="#{person.addNewItem}" />
</h:panelGrid>
<br />
<h:commandButton id="submit" name="submit" value="Submit" action="#{person.save}"/>
</h:form>
Using jsf 2.0.10 and primefaces 3.5
Its because you don't have an scope for that bean, so its request scoped, so when you call the action the bean is created again, you can fix this using a sessionScope or conversationScope

How to send/recieve data to/from bean function using JSF Richfaces AJAX?

I'm trying to get some code working in an XHTML/JSF/Spring application through which I send an ID to a bean function and expect a string in return. I haven't found an understandable tutorial on this nor any answered question here on SO.
XHTML:
<h:form>
<h:inputText id="inputId" value="#{npBean.idString}"/>
<a4j:commandButton value="get def" render="out">
<f:param value="#{npBean.idString}" name="id" />
<f:setPropertyActionListener target="#{npBean.definition}"/>
</a4j:commandButton>
<a4j:outputPanel id="out">
<h:outputText id="outputId" value="#{npBean.def}"
rendered="#{not empty npBean.def}"/>
</a4j:outputPanel>
</h:form>
Java:
public String getDefinition(int id)
{
def = this.getXService().getXData(id).getDefinition();
return def;
}
All values shown have their getters and setters in the bean.
What we basically do:
Map the value of the <h:inputText> component to a property (with getter/setter) in the managed-bean (which is called myBean)
By using the reRender attribute of the <a4j:commandButton> component, we point which component on the page to be re-rendered (refreshed) when the button is clicked.
When clicking on the button, the invokeService() method from the managedBean is executed and it updates the other property of the managedBean.
In the <h:panelGroup> below, we have several <h:outputText> components and with the rendered attribute we specify when a component has to be displayed on the page.
Exploring the managed-bean, the only thing that is required, are the accessors for the property, which holds the result from the service invoke.
Here's the *.xhtml sample:
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:a4j="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich">
<a4j:form>
<h:panelGrid columns="3">
<h:outputText value="String value:" />
<h:inputText value="#{myBean.value}" />
<a4j:commandButton value="Click" reRender="out">
<a4j:actionListener listener="#{myBean.invokeService}" />
</a4j:comandButton>
</h:panelGrid>
</a4j:form>
<rich:spacer height="7"/>
<br />
<h:panelGroup id="out">
<h:outputText value="Service returned: " rendered="#{not empty myBean.result}" />
<h:outputText value="#{myBean.result}" />
</h:panelGroup>
</ui:composition>
Managed-bean:
#ManagedBean(name = "myBean")
#SessionScoped //for example
public class MyBean {
private String value;
private String result;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String getResult() {
return result;
}
public void invokeService(ActionEvent actionEvent) {
this.result = "Hello, " + value + "!";
}
}
As #Luiggi mentioned, the accessor methods MUST meet the following conventions (if we assume you have a private <some-type> property; in the managed-bean.)
public <some-type> getProperty {
return property;
}
public void setProperty(<some-type> property) {
this.property = property:
}
In order to learn how the RichFaces components work, combined with good code examples, I suggest you open this address and play around with the components.

rendering <h:panelGroup> by ajax in jsf

I've got this piece of code, which doesn't do exactly what I thought. I try to set property by Ajax and then re-render one component. My .xhtml looks like this
<h:form>
<h:commandButton value="Render!" >
<f:ajax render=":result" listener="#{eFindUser.findUser}" />
</h:commandButton>
</h:form>
<h:panelGroup id="result" layout="block" rendered="#{eFindUser.responseRendered}" >
This is some text that is supposed to be rendered later
</h:panelGroup>
the backing bean looks like this
#Named(value = "eFindUser")
#ViewScoped
public class EFindUserManagedBean implements Serializable{
private boolean responseRendered = false;
/**
* Creates a new instance of EFindUserManagedBean
*/
public EFindUserManagedBean() {
}
public void findUser(AjaxBehaviorEvent abe) {
responseRendered = !responseRendered;
System.out.println("finding..... ("+ responseRendered+")" + this);
}
public boolean isResponseRendered() {
return responseRendered;
}
public void setResponseRendered(boolean responseRendered) {
this.responseRendered = responseRendered;
}
}
When I re-click the button, the property is not changed. There is a message in serverlog, which says
INFO: finding..... (true)backingbeans.EFindUserManagedBean#5736b751
INFO: finding..... (true)backingbeans.EFindUserManagedBean#23959d6f
Clearly there is some issue with the managed bean as it is created every time there is a request even if it should be view-scoped.
What should I change so the panelgroup(id:"result") could change it's visibility? No richfaces or any other technology allowed.
Thank you very much for your answers
You can't render dynamically a JSF component that is not rendered all time. The object must exist in the DOM client side. When using rendered="false", the output is not generated server side.
Change your code like this :
<h:form>
<h:commandButton value="Render!" >
<f:ajax render=":result" listener="#{eFindUser.findUser}" />
</h:commandButton>
</h:form>
<h:panelGroup id="result">
<h:panelGroup layout="block" rendered="#{eFindUser.responseRendered}" >
This is some text that is supposed to be rendered later
</h:panelGroup>
</h:panelGroup>
With that, the DOM will always contain something with the id="result".
This works for me:
<ui:composition>
<h:form id="mainForm">
<h:commandButton value="Render!" action="#{eFindUser.findUser}">
<f:ajax event="action" render=":result" />
</h:commandButton>
</h:form>
<h:panelGroup id="result" layout="block" rendered="#{eFindUser.responseRendered}" >
This is some text that is supposed to be rendered later
</h:panelGroup>
</ui:composition>
Bean:
#ManagedBean
#ViewScoped
public class EFindUser implements Serializable{
private static final long serialVersionUID = -7106162864352727534L;
private boolean responseRendered = false;
public EFindUser() {
}
public void findUser() {
responseRendered = !responseRendered;
System.out.println("finding..... ("+ responseRendered+")" + this);
}
public boolean isResponseRendered() {
return responseRendered;
}
public void setResponseRendered(boolean responseRendered) {
this.responseRendered = responseRendered;
}
}
Take a look on JSF 2.0 + Ajax Hello World Example

JSF Output not coming as expected by using commandLink, ViewScope in dataTable

Below are the files I have.
manageStaff.xhtml
<h:dataTable var="c" value="#{newStaffMemberServiceBean.newStaffMemberDataBeanList}"
styleClass="order-table"
headerClass="order-table-header"
rowClasses="order-table-odd-row,order-table-even-row"
border="1" id="staffListDataTable" width="100%">
<h:column>
<f:facet name="header">
Staff Member Name
</f:facet>
<h:form>
<h:commandLink action="viewStaffMemberProfileData" value="#{c.firstName}">
<f:setPropertyActionListener target="#{newStaffMemberServiceBean.userId}" value="XXXYYYZZZZ"/>
</h:commandLink>
</h:form>
</h:column>
</h:dataTable>
viewStaffMemberProfileData.xhtml
My Name is -<h:outputText value="#{newStaffMemberServiceBean.userId}" />-
NewStaffMemberServiceBean.java
#ManagedBean(name = "newStaffMemberServiceBean")
//#RequestScoped
#ViewScoped
//#SessionScoped
public class NewStaffMemberServiceBean {
private String userId;
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
In output what I get is in below format
Staff Member Name
++++++++++++++++++
Name 1
Name 2
Name 3
.
.
.
.
On Clicking Name 1, I get re-directed to viewStaffMemberProfileData.xhtml.
BUT problems are
To get re-directed on viewStaffMemberProfileData.xhtml page, I have to click link (Name 1, Name 2, etc) twice :(
When I get re-directed to viewStaffMemberProfileData.xhtml I only see output as
My Name is --
What I want is My Name is -XXXYYYZZZZ-.
Suggest me where I am going wrong.
NOTE
I have all beans in ViewScope.
Update 1
#prajeeshkumar
Getter setter are as below
public List<NewStaffMemberDataBean> getNewStaffMemberDataBeanList() {
return newStaffMemberDataBeanList;
}
public void setNewStaffMemberDataBeanList(List<NewStaffMemberDataBean> newStaffMemberDataBeanList) {
this.newStaffMemberDataBeanList = newStaffMemberDataBeanList;
}
The reason for this behavior is the view scope of the newStaffMemberServiceBean , its being destroyed and created again... so the value is being nullified... here an alternative solution:
haven't tried this one, But worth trying
change
<h:commandLink action="viewStaffMemberProfileData" value="#{c.firstName}">
<f:setPropertyActionListener target="#{newStaffMemberServiceBean.userId}" value="XXXYYYZZZZ"/>
</h:commandLink>
into
<h:link value="#{c.firstName}" outcome="nameOfXhtmlGoesHere">
<f:param name="id" value="XXXYYYZZZZ" />
</h:link>
and in viewStaffMemberProfileData.xhtml
add this before the <h:head>
<f:metadata>
<f:viewParam name="id" value="#{newStaffMemberServiceBean.userId}" />
</f:metadata>
you can also add <f:event type="preRenderView" listener="#{newStaffMemberServiceBean.init}" /> to the f:metadata in order to do some init...
based on this BalusC great article - Communication in JSF 2.0
OR
you can turn the scope of newStaffMemberServiceBean into SessionScope...
If you have newStaffMemberServiceBean in view scope, then when you are going to a different page (view) will that bean be available in that scope ? I mean manageStaff.xhtml will have one instance and viewStaffMemberProfileData.xhtml will have another one. Your solution here will be using the session scope or using the h:link or h:outputLink

Categories

Resources