I am using NetBeans for a Web Application in Java EE.
I have one controller for an absence entity class (absenceController) and one controller for an employee entity class (employeeController).
I am able to get to the employee creation page via any page controlled by absenceController:
<h:commandLink action="#{absenceController.prepareCreate}"
value="#{bundle.ListAbsenceCreateLink}"/>
I am able to get to the absence creation page via any page controlled by employeeController:
<h:commandLink action="#{employeeController.prepareCreate}"
value="#{bundle.ViewEmployeeCreateLink}" />
When I want to set up a new absence instance, I need the employee to be set in advance so I am trying to reach the absence creation page from an employee view page (called Tasks.xhtml), sending the employee instance as a parameter.
In MVC .NET I would have used an Html.ActionLink a bit like this:
Html.ActionLink("Report Absence for employee"
, "Create"
, "Absence"
, new { employeeid = employee.Id } // <- I would only be able to send the id
, null)
In Java, this is the closest I've got:
<h:commandLink action="/absence/create"
value="#{bundle.TasksEmployeeCreateAbsenceLink}" >
<f:setPropertyActionListener target="#{absenceController.selected.employee}"
value="#{employeeController.selected}" />
</h:commandLink>
The folder structure is shown below:
I know the action tag is not correct, but is there some way to change it to get the desired result please?
One way of achieving what I needed was to use navigation rules. (As in the comments, there are better way of achieving this since JSF 2.x)
I added the following to faces-config.xml (within <application></application> section):
<navigation-rule>
<from-view-id>/employee/Tasks.xhtml</from-view-id>
<navigation-case>
<from-action>absence/create</from-action>
<from-outcome>absence/create</from-outcome>
<to-view-id>/absence/Create.xhtml</to-view-id>
</navigation-case>
</navigation-rule>
I am using JSF 2.2, so all I needed to do was use the correct case in Create:
<h:commandLink action="/absence/Create"
value="#{bundle.TasksEmployeeCreateAbsenceLink}" >
<f:setPropertyActionListener target="#{absenceController.selected.employee}"
value="#{employeeController.selected}" />
</h:commandLink>
Related
In my application I want to display a <h:dataTable> with managed bean properties. Currently this table is created from a List<Folder>. Now I want to change the Folder to something more dynamic. That's because I don't want to change the Folder class if I decide to add another field later. I would just have to add another entry in the Map<String, Object> instead of introducing a new field in Folder.
So, is it possible to bind a List<Map<String, Object>> to the <h:dataTable>?
Is it possible to bind a List of HashMaps to the jsf component h:dataTable?
That's only possible if you generate the necessary <h:column> tags with a view build time tag such as JSTL <c:forEach>.
Here's a concrete kickoff example, assuming that your environment supports EL 2.2:
<h:dataTable value="#{bean.listOfMaps}" var="map">
<c:forEach items="#{bean.listOfMaps[0].keySet().toArray()}" var="key">
<h:column>
#{map[key]}
</h:column>
</c:forEach>
</h:dataTable>
(if your environment doesn't support EL 2.2, you'd need to provide another getter which returns the map key set as a String[] or List<String>; also keep in mind that a HashMap is by nature unordered, you might want to use LinkedHashMap instead to maintain insertion order)
When you're using Mojarra version older than 2.1.18, the disadvantage is that the #{bean} has to be request scoped (not view scoped). Or at least, the <c:forEach items> should refer a request scoped bean. A view scoped bean would otherwise be recreated on every single HTTP request as the <c:forEach> runs during view build time, when the view scope isn't availabe yet. If you absolutely need a view scoped bean for the <h:dataTable>, then you can always create a separate request scoped bean exclusively for <c:forEach items>. The solution would be to upgrade to Mojarra 2.1.18 or newer. For some background information, see also JSTL in JSF2 Facelets... makes sense?
JSF component libraries such as PrimeFaces may offer a <x:columns> tag which makes this more easy, such as <p:dataTable> with <p:columns>.
<p:dataTable value="#{bean.listOfMaps}" var="map">
<p:columns value="#{bean.listOfMaps[0].keySet().toArray()}" var="key">
#{map[key]}
</p:columns>
</p:dataTable>
I'm trying to pass a parameter between a JSF page to another, from a bean to another. I know it is a common question, infact I've tried several approaches before writing it down.
To do that I have put both the beans in session scope and added in the first bean the following:
<p:commandButton value="Submit" type="submit"
actionListener="#{sourceBean.save}" action="success">
<f:setPropertyActionListener
target="#{targetBean.foo}" value="#{sourceBean.foo}" />
</p:commandButton>
The problem is that I don't want these beans to be in session scope but in view scope.
So I tried to put in my first page:
<p:commandButton value="Submit" type="submit"
actionListener="#{sourceBean.save}" action="success">
<f:param name="foo" value="#{sourceBean.foo}"/>
</p:commandButton>
And in the second page:
<f:metadata>
<f:viewParam id="foo" name="foo" value="#{targetBean.foo}"
/>
</f:metadata>
The problem is that the passed String is null so, obviously, I get an error form the Converter.
I think I'm missing something in the configuration of my managed beans. Do I have to link target and source bean in someway?
At this moment I have this configuration:
<managed-bean>
<managed-bean-name>targetBean</managed-bean-name>
<managed-bean-class>guiBeans.TargetBean</managed-bean-class>
<managed-bean-scope>view</managed-bean-scope>
</managed-bean>
<managed-bean>
<managed-bean-name>sourceBean</managed-bean-name>
<managed-bean-class>guiBeans.SourceBean</managed-bean-class>
<managed-bean-scope>view</managed-bean-scope>
</managed-bean>
Another question: In my app, the value foo.id, that I use during the conversion, is set autonatically by the database when I save the object so when I call:
actionListener="#{sourceBean.save}"
The converter gets the id and turns it into a String (and viceversa, if needed).
So, I wanted to know if in JSF is first called the actionListener or the function that sets the parameters .
Could be this the reason why I get a null String? Thanks a lot.
The <f:param> is evaluated during rendering of the form, not during submitting of the form. Your problem suggests that the #{sourceBean.foo} value is only been set during submitting the form and thus not available during rendering of the form.
You'd basically need to replace action="success" by action="#{bean.action}" with
public String action() {
return "success?foo=" + foo.getId();
}
Or, if you're using navigation cases
<navigation-case>
<from-outcome>success</from-outcome>
<to-view-id>/some.xhtml</to-view-id>
<redirect>
<view-param>
<name>foo</name>
<value>#{sourceBean.foo.id}</value>
</view-param>
</redirect>
</navigation-case>
Unrelated to the concrete problem, the <f:param> doesn't support the converter attribute at all. You'd have to access the desired property directly (which is id in the above example).
I'm trying to do something simple in JSF but I can't get it working for some reason.
What I want is to post information with a form from a page reached with a GET parameter and keep this GET parameter whenever I submit the form.
<f:metadata>
<f:viewParam name="someId" value="#{someController.something}" converter="#{someConverter}" />
</f:metadata>
This is the way I choose to bind the GET parameter, this is working fine when I'm doing the GET request.
On the very same page I have a
<h:form>
<!-- (... various input ...) -->
<h:commandLink action="#{someController.create}" value="Create" />
</h:form>
When I submit it, even if data are right, I never get my "something" not to be null.
The use case is easy, I have a one to many relation and I want to access the "one" with the id as a GET parameter and list the "many" on the page and below the listing the form allows me to add a new element in the "many" list.
I'd like to make it work (of course) and be the cleaner possible,
Could someone tell me what's the best way to achieve this?
Thanks!
Either make the SomeController bean #ViewScoped so that the bean lives as long as you're interacting with the same view,
#ManagedBean
#ViewScoped
public class SomeController {
// ...
}
or use <f:param> in UICommand components to pass GET parameters through
<h:commandLink>
<f:param name="someId" value="#{param.someId}" />
</h:commandLink>
I have a table of Items, and in each row there is a link that forwards to the edit item page. To load data in the edit page I need the managed bean in request scope (if I put it in view scope I loose data in the forward).
To use ajax in the edit page I need the managed bean in view Scope due to some values I must keep. If I were working with JSF 1.0 and RichFaces I would do it with request scope and a4j:keepalive.
How do I get this funcionality with PrimeFaces and JSF 2.0 or how can I redefine the interface to get this?
Ok, finally based on the post below this is what worked for me:
CommandButton in the Items table:
<o:commandButton id="editButton"
action="#{itemTableMB.editItem(item.id)}" styleClass="botonTabla">
<h:graphicImage styleClass="imagenBotonTabla" url="/resources/images/icons/pencil.png"/>
</o:commandButton>
Action in the managed bean:
public String editItem(Integer id){
return "/pages/items/edit.xhtml?faces-redirect=true&id="+id;
}
edit.xhtml:
<f:metadata>
<f:viewParam id="id" name="id" value="#{itemMB.item.id}" required="true">
</f:viewParam>
<f:event type="preRenderView" listener="#{itemMB.loadItem}" />
</f:metadata>
Listener in itemMB:
public void loadItem(){
this.item = this.itemManager.get(this.item.getId());
}
To load data in the edit page I need the managed bean in Request scope (If I put it in view scope I loose data in the forward).
Are you using a navigation rule (or implicit navigation) without a redirect?
One solution would be to put backing beans of both the "table of items"-page and the "edit item"-page in view scope, and then go from the first to the second one directly via a GET request (e.g. using <h:link>) or a POST/redirect with a request parameter representing the row on which the user clicked.
Use <f:viewParam> on the second page to conveniently convert the request parameter back to an entity representing the item being edited.
If you were indeed using navigation without redirect, then this has the additional benefit that you won't suffer from the notorious 'one-URL-behind-problem', which can be rather confusing to users of your application and be a nightmare for support.
<h:commandButton value="Add Order" action="#{orderBasket.addItems(param['orderItemId'])}"/>
I can't get the above to work...when you click on the button the param seems to get set to null. Is there a way around this?
Is there another way of passing the URL params into the action method? I'm using Spring EL resolver which limits my ability to pass in the parameters into beans as I'm not using faces-config.
First, I think you could use JSF better, a lot of problems would be much simpler. It looks that you are using JSF as a request/response framework, like Struts. JSF is an object oriented component framework, you should use it this way to get the best of it.
I'll try to solve your problem, but I'm missing some information on what you are doing.
If you have a list of books that you can order, let's say they are displayed in a datatable (you could use ui:repeat instead) :
<h:dataTable value="#{bookController.books}" var="book">
<h:column>
<h:outputText value="#{book.title}" />
</h:column>
<h:column>
<h:commandButton value="Add Order" action="#{orderBasket.addItems(book)}" />
</h:column>
</h:dataTable>
In orderBasket backing bean, you simply take a Book (or whatever) as parameter. You don't need to handle the request/response cycle, certainly not in your views.
You can use f:ajax tag if you need to display that in your shopping cart immediately.
Let me know if you need more explanation (backing beans source or else).