adding duplicate components to a JSF panel grid - jsf

I am reasonably new to Java/JSF development (previously Mainframe legacy) so I am hoping someone will be able to let me know if what I am about to ask is possible and how to do it. Or at least point me in the right direction.
I'm trying to create a portlet where I can add the same component over and over again up to a maximum of 30 times. Eventually the data behind these components will be different in each one but from the same database. What I've done so far is create a container component and a button which calls a method to add something to the container. Like as follows:
<h:body>
<h:form>
<ice:panelGrid binding="#{simpleBean.containerComponent}"/>
<br/>
<ice:commandButton value="add new section" action="#{simpleBean.addComponent}" />
</h:form>
</h:body>
What I'm struggling with is the backing bean to create and render the component. At the minute I am just trying to create anything that repeats. The final code will be more complex than this.
private HtmlPanelGrid containerComponent;
private int i = 1;
public void addComponent() {
UIColumn uiColumn = new UIColumn();
uiColumn.setId("UIColumn_"+i);
HtmlOutputText htmlOutputText = new HtmlOutputText();
htmlOutputText.setId("HtmlOutputText_"+i);
htmlOutputText.setValue("HtmlOutputText_1_Value");
HtmlInputText htmlInputText = new HtmlInputText();
htmlInputText.setId("HtmlInputText_"+i);
htmlInputText.setValue("HtmlInputText_1_Value");
uiColumn.getChildren().add(htmlOutputText);
uiColumn.getChildren().add(htmlInputText);
if (containerComponent == null) {
containerComponent = new HtmlPanelGrid();
}
containerComponent.getChildren().add(uiColumn);
i++;
}
I can get the code to render something the first time the button is clicked but nothing happens subsequently. In an ideal world I'd get 30 of the same component displayed on the screen.
Can anyone offer any advice?
Thank you in advance.
Chris

Related

JSF Request Scoped Bean not displaying data in page

I'm experimenting with JSF scopes, and have some issues when using a session scoped bean within a request scoped bean.
The basic workflow is that the user would click a View button on an item from the home page, which then calls my code to load & display that item's information.
Here's my UPDATED code:
#ManagedBean(name="itemViewBean")
#RequestScoped
class ItemViewBean {
#ManagedProperty("#{itemBean}")
private ItemBean itemBean;
private ItemViewObject itemViewObject;
private int itemId;
public void init() {
itemViewObject = itemBean.readItem(itemId);
}
public String readItem(int itemId) {
// itemViewObject = itemBean.readItem(itemId); // moved to init();
return "/pages/viewItem.xhtml?faces-redirect=true";
}
public ItemViewObject getItemViewObject() {
return itemViewObject;
}
// getters & setters as needed
}
#ManagedBean(name="itemBean")
#SessionScoped
class ItemBean {
public ItemViewObject readItem(int itemId) {
// hardcoded creating a ItemViewObject for now.
// eventually would be loaded from the database.
....
}
}
My UPDATED view page then has things like:
<!-- added the metadata -->
<f:metadata>
<f:viewParam name="id" value="#{itemViewBean.itemId}" />
<f:event listener="#{itemViewBean.init}" type="preRenderView" />
</f:metadata>
<!-- same as before -->
<h:outputText value="#{itemViewBean.itemViewObject.description}" />
If my viewBean is request scoped (or view scoped), I get empty data on the view page. If the viewBean is session scoped, things work. And I'm not understanding why?
From what I see in my debugger, readItem(itemId) is called (from the home page when clicking a view button), but when the view page itself calls the getItemViewObject(), the itemViewObject is null.
What am I doing wrong?
UPDATE
I forgot to mention earlier how my home page was calling readItem method, and that was through a command button:
<h:commandButton class="btn btn-mini firefoxBtnMiniCorrection"
value="View"
action="#{itemViewBean.readItem(b.itemId)}"/>
Each item listed in the home page has its own View button.
Also forgot to mention that both the home page and my view page are using JSF Templates. I don't know if that matters.
From the comments below which people have made, I came up with the code changes above. And things work now. Using either request scope or view scope with ItemViewBean works now.
And I am surprised this worked! I'm not quite certain I fully understand why it works.
Are my changes the correct way to do things? Or is there a better way?
Also, I'm using JSF 2.1.
Update 2
It doesn't work. The scoping works, but I discovered that the itemId in the viewParam is always null. Why?
itemViewObject is private in a RequestScoped bean. After readItem() got a value for itemViewObject, this value will be forgotten after this request and will be null at the next request (`#RequestScoped').

using a variable value as an a href link

I have a backing bean and an XHTML that is tied to this backing bean. I have a private instance variable called testerString.
Here is an excerpt of the backingbean
public class LinkDataBackingBean {
Map<String, LinkInfo> linkMap = new HashMap<String, LinkInfo>();
List<LinkInfo> list = new ArrayList<LinkInfo>();
private String testerString = "http://www.google.com";
public String getTesterString() {
return testerString;
}
public LinkDataBackingBean() throws FileNotFoundException {
System.out.println("hello");
for(int i = 0; i < 10; i++){
list.add(new LinkInfo("hi", "www.google.com"));
//linkMap = getLinkData()
}
}
As you can see, I've manually populated the variable with http://www.google.com. There comes a time in my XHTML where I would like to have someone click on a link and then it will go to the URL described by testerString.
One way I tried this was this, as a passed variable.
<f:metadata>
<f:viewParam name="id" value="#{linkDataBackingBean.testerString}" />
</f:metadata>
And then:
TEST
This did not work, in the sense that "TEST" did not appear as a hyperlink at all (whereas if I manually put in "http://www.google.com" for the value of the former statement, it DOES appear as a hyperlink and works fine).
I've also tried the following, plugging the backing bean value directly (have to screw up formatting or SO won't show):
TEST
This yielded a similar result - TEST did not appear as an underlined hyperlink kind of thing.
I considered using outputLink, but faced similar woes, I do get the Text to be a hyperlink, but it does not link to the domain I specified:
<h:outputLink id="link1" value="#{ linkDataBackingBean.testerString}">
<h:outputText value="TEST" />
</h:outputLink>
This links to the base dir of my whole project - http://localhost:8080/name-of-my-proj/faces/
When I do the same as above, but populate value with "http://www.google.com", it properly goes there. It doesn't seem to get/understand my reference to the backingbean.
What sticking me is identifying what would be required to have TEST appear as a hyperlink and, when someone clicks on it, them being directed to the URL indicated by testerString? Surely there is some JSF "plumbing" I am missing.

JSF - p:ajax listener asking for parameters netBeans/primefaces

Versions:
NetBeans: 7.2.1
PrimeFaces: 3.5.3
GlassFish: 3.1.2
JDK 1.6
I've been trying to find related issues and have found topics that are close, but not quite what I'm looking for. I'm trying to do something similar to the p:schedule demo from PrimeFaces ShowCase where I want a dialog to appear showing the details of the event clicked.
I think the issue is coming from calling the listener method from the backing bean. When I go to type in the listener method in the p:ajax tag, NetBeans forces me to pass in a parameter like:
listener="#{cmodel.onEventSelect(e)}"
which I don't think is necessary as I don't have a value to pass in anyways.
I'm thinking either:
Something is up with NetBeans that doesn't recognize the method as a listener. (Since i keep seeing multiple examples of people calling the method without needing to pass a parameter.)
or
I'm not registering the method as a listener properly in the Model.
Also, I have directly copied and pasted the demo from the ShowCase into a project and it didn't work which is making me lean more towards an issue with NetBeans. (that is, the dialog appears but with no information on the event that was selected)
So to summarize; events are showing up as they should on the schedule itself, I just cant get the dialog to show the event details of the event that was selected.
Any help would be greatly appreciated!
View Layer:
<h:form>
<p:schedule id="nelsonsSchedule" value="#{cmodel.scheduleModel}" showHeader="true"
leftHeaderTemplate="none" rightHeaderTemplate="prev, next today"
draggable="false" timeZone="UTC" styleClass="schedule">
<p:ajax event="eventSelect" listener="#{cmodel.onEventSelect}"
update="eventDialog eventDetails" oncomplete="eventDialog.show()"/>
</p:schedule>
<p:dialog id="eventDialog" widgetVar="eventDialog" header="EventDetails">
<p:panel id="eventDetails">
<h:outputLabel value="#{cmodel.selectedEvent.title}" />
</p:panel>
</p:dialog>
</h:form>
Backing Bean:
#ManagedBean(name = "cmodel")
#SessionScoped
public class CalendarModel implements Serializable {
private ScheduleModel scheduleModel;
private List<ScheduleEvent> allScheduledGames;
private DefaultScheduleEvent gameEvent;
public ScheduleEvent selectedEvent;
List<Game> allGames;
#PersistenceContext
private EntityManager em;
public CalendarModel() {
}
#PostConstruct
public void init() {
allScheduledGames = new ArrayList<ScheduleEvent>();
allGames = new ArrayList<Game>();
allGames = em.createNamedQuery("Game.findAll").getResultList();
/*create list of games to put into the ScheduleModel*/
for (int i = 0; i < allGames.size(); i++) {
gameEvent = new DefaultScheduleEvent(allGames.get(i).getOpponent() +
"\n\n\n" + allGames.get(i).getTimeOfGame(),
allGames.get(i).getDateOfGame(),
allGames.get(i).getDateOfGame());
if(allGames.get(i).getHomeAway().equals("away")){
gameEvent.setStyleClass("away");
} else{
gameEvent.setStyleClass("home");
}
gameEvent.setData(allGames.get(i));
allScheduledGames.add(gameEvent);
}/*end for*/
scheduleModel = new DefaultScheduleModel(allScheduledGames);
}/*end init()*/
public void onEventSelect (SelectEvent e) {
selectedEvent = new DefaultScheduleEvent();
selectedEvent = (ScheduleEvent) e.getObject();
}
In case anyone runs into the same issue - It was NetBeans. I upgraded to 7.3 and don't have the problem anymore. Although another has come up where itellisense doesn't recognize a hashmap from the backing bean, but that's for another question.

How save or update single inputText field using ajax listener

I spent already more time as is good about some saving or updating issue in inputtext field, i go right to the point:
i have basic single input text with some basic attributtes
<h:inputText id="name" value="#{salesController.selectedSalesName}" />
here is a getter for inputText value
public String getSelectedSalesName(){
for(DealerListView dealer : dealerList){
if(dealer.getDealerId() == getSelectedDealerId()){
return dealer.getName();
}
}
return "";
}
nested in there i use ajax tag
<f:ajax event="change" render="name" listener="#{salesController.updateSelectedSalesName()}" />
a here is back bean method for updating a input text field
public void updateSelectedSalesName() {
DealerData dealDat = BeanFactory.getHotelDAOService(DealerData.class).findOne(selectedDealerId);
dealDat.setName(name);
BeanFactory.getHotelDAOService(DealerData.class).update(dealDat);
}
whole result of this is stack trace which say
value="#{salesController.selectedSalesName}": Property 'selectedSalesName' not writable on type sk.hotel.web.controller.SalesController
I know that something changes is need for that getter method but try some combinations without result which make corect update of value to database.
(I dont use any commands buttons for submit,update only response on pressing Enter in that inputText field.)
I want some guide how can be modified this save/update process whether on back-bean or jsf layout
or maybe someone solved similar situation already,and can share his solution.
Thanks all of you for advice posts.
Regards and nice day
First, add a field:
String selectedSalesName;
Add a setter and setter:
public String getSelectedSalesName() {
return selectedSalesName;
}
public void setSelectedSalesName(String selectedSalesName) {
this.selectedSalesName = selectedSalesName;
}
Add a ajaxListener(AjaxBehaviurEvent event) to create a new Dealer or Update current Dealer
public void ajaxListener(AjaxBehaviorEvent event) {
Dao dao = BeanFactory.getHotelDAOService(DealerData.class)
if (selectedDealerId == null) {
DealarData dealerData= new DealerData();
dealerDate.setName(getSelectedSalesName());
dao.add(dealerData);
setDealer(dealerData);
} else {
DealerData dealDat = dao.findOne(selectedDealerId);
dealDat.setName(name);
dao.update(dealDat);
}
}
A setter to the current dealer
int selectedDealerId;
public void setDealer(DealerData dealer) {
selectedDealerId = dealer.getId();
selectedSalesName = dealer.getName();
}
And the xhtml page:
<h:inputText value="#{salesController.selectedSalesName}" id="idSalesInput">
<a4j:ajax event="keyup" listener="#{salesController.ajaxListener}"
execute="idSalesInput"/>
</h:inputText>
Change "keyup" for the event you want to listen.
When you press a key, the listener is called, and the value of idSalesInput is submitted (the setSelectedSalesName() method is called here, for this reason you got the Property 'selectedSalesName' not writable exception),and the listener create or update a new DealerData.
Have a nice Day and sorry for my bad english!
Binding value in your inputText is two way, when it is rendered than getter is called to calculate value, when it is submited (like in your AJAX event) setter is called for that property to set value in your backing bean. So JSF tries to call setSelectedSalesName(String value). JSF can't write your property, which means can't call setter.
See also:
AJAX listener not being fired for inside

JSF viewscope values not getting displayed in the view properly

I have a managed bean under ViewScope. It has an instance variable inside it.
MetaData object has a inputItem object List.
#ManagedBean
#ViewScoped
public class ConBean implements Serializable {
private MetaData metadata;
#PostConstruct
#SuppressWarnings("unchecked")
public void init() throws IOException {
this.metadata = new MetaData ();
}
public void proc(){
List<InputItem> inputs= new ArrayList<InputItem>();
inputs.add(***** code to populate the inputItem List);
//after populating, inputs added to the metadata
metadata.setInputs(inputs);
}
//getters & setters
}
in my JSF , input list is populated inside a UI repeat.
<div id="inputplaceholder">
<ui:repeat value="#{conBean.metaData.inputs}" var="content">
</ui:repeat>
</div>
the div inputplaceholder is periodically updated using a richfaces poll.
<a4j:poll id="poll" interval="12000" action="#{conBean.proc}"
execute="#form" render="inputplaceholder"/>
The problem that I have is even though inputItems are set to the metaData object correctly inside the proc() method, when the view is rendered/partially updated, it doesn't get highlighted in the UI. so partial update takes no effect. I tried moving
this.metadata = new MetaData ();
inside the proc method but had no luck.
any ideas and help is highly appreciated.
thanks ...
Did the partial render really take place? This is impossible. There is namely no JSF component with the ID inputplaceholder. You assigned it to a plain HTML <div> element. Replace it by a fullworthy JSF component:
<h:panelGroup layout="block" id="inputplaceholder">
Also, since you used a relative ID in the render attribute, it will only scan for components in the same parent naming container component. The <ui:repeat> is such one, however the component with the desired ID is placed outside it. You'd like to use an absolute ID instead. Assuming that it's inside a <h:form> with a fixed ID:
<h:form id="myform">
<h:panelGroup layout="block" id="inputplaceholder">
...
then you should be referencing it in the render attribute as follows
render=":myform:inputplaceholder"

Resources