jsf selectonemenu selectitems from an enum - jsf

Ok, I think I've seen all the matches about this in StackOverflow and other Internet sites. My code is as follows:
Class:
public enum pruebaEnum{PRUEBA1, PRUEBA2, PRUEBA3};
private pruebaEnum prueba;
private pruebaEnum[] pruebaList;
public pruebaEnum getPrueba() {
return prueba;
}
public void setPrueba(pruebaEnum prueba) {
this.prueba = prueba;
}
public pruebaEnum[] getPruebaList() {
return pruebaEnum.values();
}
public void setPruebaList(pruebaEnum[] pruebaList) {
this.pruebaList = pruebaList;
}
JSF code:
<t:selectOneMenu id="categorization" value="#{BookManual.prueba}">
<t:selectItems Value="#{BookManual.pruebaList}"/>
</t:selectOneMenu>
The fact is I only get an empty dropbox. I don't know what I am doing wrong....

Attribute names are case sensitive. You used Value, but it's value.
By the way, you don't need a setter for <f:selectItems>. Get rid of it to save dead code and unnecessary future confusions because it's never invoked.

Related

Automatically set value of a managed bean variable with JSF

I would like to pass an value to a managed bean under the hood. So I have this managed bean:
#ManagedBean(name = "mbWorkOrderController")
#SessionScoped
public class WorkOrderController {
// more attributes...
private WorkOrder workOrderCurrent;
// more code here...
public WorkOrder getWorkOrderCurrent() {
return workOrderCurrent;
}
public void setWorkOrderCurrent(WorkOrder workOrderCurrent) {
this.workOrderCurrent = workOrderCurrent;
}
}
It holds a parameter workOrderCurrent of the custom type WorkOrder. The class WorkOrder has an attribute applicant of type String.
At the moment I am using a placeholder inside my inputtext to show the user, what he needs to type inside an inputText.
<p:inputText id="applicant"
value="#{mbWorkOrderController.workOrderCurrent.applicant}"
required="true" maxlength="6"
placeholder="#{mbUserController.userLoggedIn.username}" />
What I want to do, is to automatically pass the value of mbUserController.userLoggedIn.username to mbWorkOrderController.workOrderCurrent.applicant and remove the inputText for applicant completely from my form.
I tried to use c:set:
<c:set value="#{mbUserController.userLoggedIn.username}" target="#{mbWorkOrderController}" property="workOrderCurrent.applicant" />
But unfortunatelly I get a javax.servlet.ServletException with the message:
The class 'WorkOrderController' does not have the property 'workOrderCurrent.applicant'.
Does anybody have an advice?
The class 'WorkOrderController' does not have the property 'workOrderCurrent.applicant'.
Your <c:set> syntax is incorrect.
<c:set value="#{mbUserController.userLoggedIn.username}"
target="#{mbWorkOrderController}"
property="workOrderCurrent.applicant" />
You seem to be thinking that the part..
value="#{mbWorkOrderController.workOrderCurrent.applicant}"
..works under the covers as below:
WorkOrderCurrent workOrderCurrent = mbWorkOrderController.getWorkOrderCurrent();
workOrderCurrent.setApplicant(applicant);
mbWorkOrderController.setWorkOrderCurrent(workOrderCurrent);
This isn't true. It works under the covers as below:
mbWorkOrderController.getWorkOrderCurrent().setApplicant(applicant);
The correct <c:set> syntax is therefore as below:
<c:set value="#{mbUserController.userLoggedIn.username}"
target="#{mbWorkOrderController.workOrderCurrent}"
property="applicant" />
That said, all of this isn't the correct solution to the concrete problem you actually tried to solve. You should perform model prepopulating in the model itself. This can be achieved by using #ManagedProperty to reference another bean property and by using #PostConstruct to perform initialization based on it.
#ManagedBean(name = "mbWorkOrderController")
#SessionScoped
public class WorkOrderController {
#ManagedProperty("#{mbUserController.userLoggedIn}")
private User userLoggedIn;
#PostConstruct
public void init() {
workOrderCurrent.setApplicant(userLoggedIn.getUsername());
}
// ...
}
Perhaps you could explain the context a bit more, but here's another solution. If you're navigating from another page, you can pass some identifier of work WorkOrder in the URL, like this http://host:port/context/page.xhtml?workOrderId=1.
Then, you can set the identifier in the managed bean like this:
<h:html>
<f:viewParam name="workOrderId" value="#{mbWorkOrderController.id}"/>
</h:html>
You'll have to add a new property to your bean:
public class WorkOrderController {
private long id;
public long getId() { return id; }
public void setId(long id) { this.id = id; }
// ...
}
And then, after the property has been set by JSF, you can find the work order in a lifecycle event:
<h:html>
<f:viewParam name="workOrderId" value="#{mbWorkOrderController.id}"/>
<f:event type="preRenderView" listener="#{mbWorkOrderController.findWorkOrder()}"/>
</h:html>
public class WorkOrderController {
private long id;
public long getId() { return id; }
public void setId(long id) { this.id = id; }
public void findWorkOrder() {
this.workOrderCurrent = null /* some way of finding the work order */
}
// ...
}
This strategy has the advantage of letting you have bookmarkable URLs.

Disable one checkbox out of many in <h:selectManyCheckbox where checkboxes come from a LinkedHashMap [duplicate]

I need your help in disabling and enabling an item from the selectManyCheckbox component in a jsf page. First of all, the selectManyCheckbox component is showing three chechboxes which are (Loan - Health - Transfer). The list will be populated from a bean which it has the code:
private List<hrCertificate> hrCertificatesList = new ArrayList<hrCertificate>();
//Getter and Setter
Private String loanFlag="";
#PostConstruct
public void init() {
this.hrCertificatesList.add(new hrCertificate(("Loan"), "LC"));
this.hrCertificatesList.add(new hrCertificate(("Health"), "HI"));
this.hrCertificatesList.add(new hrCertificate(("Trasnfer"), "TE"));
}
In the same bean, I will be running a SQL statement that will return either Yes or No and that value I am adding it to the loanFlag variable.So if the flag="Y", I need to enable the loan checkbox so the user can select it else I need to disable it from the selectManyCheckbox. The issue is that I am facing difficulties in applying the logic to disable and to enable the item selectManyCheckboxwhere in the above code I am listing and enabling them all the time.
The code for the selectManyChexkbox:
<p:selectManyCheckbox id="hrCertificates" value="#{user.selectedHRCertificates}" layout="pageDirectio>
<f:selectItems value="#{user.hrCertificatesList}"
var="hrCertificate" itemLabel="#{hrCertificate.hrCertificateName}"
itemValue="#{hrCertificate.hrCertificateCode}"/>
</p:selectManyCheckbox>
So how to apply the logic
Could you edit your hrCertificate class to add a disabled boolean field? If yes, then you can add itemDisabled="#{hrCerticate.disabled}" to your f:selectItems which should be the easiest solution.
Another option would be to use a Map<hrCertificate, Boolean> instead of a List<hrCertificate>.
private Map<hrCertificate, Boolean> hrCertificatesMap = new HashMap<hrCertificate, Boolean>();
#PostConstruct
public void init() {
hrCertificatesMap.put(new hrCertificate(("Loan"), "LC"), null);
hrCertificatesMap.put(new hrCertificate(("Health"), "HI"), null);
hrCertificatesMap.put(new hrCertificate(("Trasnfer"), "TE"), null);
}
// Then when you're done with your SQL query, update your Map to add the corresponding boolean values...
.xhtml
<p:selectManyCheckbox id="hrCertificates" value="#{user.selectedHRCertificates}" layout="pageDirectio>
<f:selectItems value="#{user.hrCertificatesMap.keySet().toArray()}" var="hrCertificate" itemLabel="#{hrCertificate.hrCertificateName}" itemValue="#{hrCertificate.hrCertificateCode}" itemDisabled="#{user.hrCertificatesMap.get(hrCertificate)}" />
</p:selectManyCheckbox>
First, note that a property does not retire an actual attribute backing it, you only need a getter. So you can have:
public class MyBean implements Serializable {
private FilterEnum certFilter = FilterEnum.NO_FILTER;
private List<Certificate> certificates;
... // including certificates initialization.
public FilterEnum getCertFilter() {
return this.certFilter;
}
public void setCertFilter(FilterEnum certFilter) {
this.certFilter = certFilter;
}
public List<Certificate> getCertificates() {
// I am sure there is a cooler way to do the same with streams in Java 8
ArrayList<Certificate> returnValue = new ArrayList<>();
for (Certificate certificate : this.certificates) {
switch (this.certFilter) {
case FilterEnum.NO_FILTER:
returnValue.add(certificate);
break;
case FilterEnum.ONLY_YES:
if (certificate.isLoan) {
returnValue.add(certificate);
}
break;
case FilterEnum.ONLY_NO:
if (!certificate.isLoan) {
returnValue.add(certificate);
}
break;
}
}
return returnValue;
}
}
If you insist that you want to do the filter "in the .xhtml", you can combine c:forEach from JSTL with <f:selectItem> (note item, not items), but it will make your xhtml more complicated and may cause issues if you want to use Ajax with it.

Access static property in JSF

I have a static List of Select Items in one of my backing beans:
private static List<SelectItem> countries = new ArrayList<SelectItem>();
with the following getters and setters:
public static List<SelectItem> getCountries() {
return countries;
}
public static void setCountries(List<SelectItem> countries) {
LoadSelectItemsBean.countries = countries;
}
I am having trouble with accessing the static List through my XHTML page. The code I have tried is as follows:
<ace:simpleSelectOneMenu id="countryField"
value="#{generalCarrierDataViewBean.carrierBean.countryId}">
<f:selectItems value="#{loadSelectItemsBean.countries}" />
<ace:ajax />
</ace:simpleSelectOneMenu>
The problem line is:
<f:selectItems value="#{loadSelectItemsBean.countries}" />
The exception which results is:
javax.el.PropertyNotFoundException: /pages/GeneralCarrierData.xhtml #394,64 value="#{loadSelectItemsBean.states}": Property 'states' not found on type com.oag.reference.util.LoadSelectItemsBean
Can anbody advise on how to correctly reference a static property from a backing bean?
Thanks
Properties are per definition not static. So getters and setters can simply not be static, although they can in turn reference a static variable. But the outside world does not see that.
You've 3 options:
Remove the static modifier from the getter. The whole setter is unnecessary, you can just remove it.
public List<SelectItem> getCountries() {
return countries;
}
Create an EL function if you really insist in accessing static "properties" (functions). Detail can be found in this answer: How to create a custom EL function to invoke a static method?
Turn the whole List<SelectItem> thing into an enum and make use of OmniFaces <o:importConstants>. Detail can be found in this answer: How to create and use a generic bean for enums in f:selectItems?
Just create a non-static method that returns the static property:
// here you have a static String
private static String static_str;
public static String getStatic_str() {
return static_str;
}
// in jsf page: #{myClass.str}
public String getStr() {
return static_str;
}

How to add multiple instances of JSF 2 managed beans to Java Collection?

I'm trying to wrap my head around some basic JSF 2 concepts. For instance, if I have a managed bean, Bean1:
#ManagedBean
public class Bean1 {
private String foo;
private String bar;
}
and the values for foo and bar are obtained from a JSF web form. On each submit of the web form, I want to store an instance of Bean1 in a Java Collection of another bean:
#ManagedBean
public class Bean2 {
private List<Bean1> beanList;
}
What is the correct way to achieve this? Thanks.
BalusC is 100% per cent right, but (as he warns) his answer will be useless. The important point here is that you do not need nor want the second bean to be managed at all. It is your model, not your GUI. You probably wanted something like:
#ManagedBean
#ViewScoped
class PeopleHolder {
private List<Person> people = new ArrayList<Person>();
// not managed at all:
private Person currentPerson;
// just the getter, no need for a setter
public Person getCurrentPerson() { return currentPerson; }
#PostConstruct
public init(){ currentPerson = new Person(); }
public void addCurrentPersonToList() {
people.add(currentPerson);
init();
}
// just for test:
public List<People> getPeople() { return people; }
}
and now a form:
<h:form>
<h:inputText value="#{peopleHolder.currentPerson.name}" />
<h:inputText value="#{peopleHolder.currentPerson.lastName}" />
<h:commandButton action="#{peopleHolder.addCurrentPersonToList}" />
</h:form>
Make Bean2 a managed property of Bean1 so that you have access to its beanList property.
#ManagedBean
public class Bean1 {
private String foo;
private String bar;
#ManagedProperty("#{bean2}")
private Bean2 bean2;
public void submit() {
bean2.getBeanList().add(this);
// ...
}
// ...
}
(please note that this way just the reference is stored, not a clone of the Bean1's state or something!)
Needless to say that this is a design smell. There are likely better ways to achieve the concrete functional requirement which you've had in mind while asking the question but didn't tell anything about. In the future try to ask how to solve the functional requirement instead of how to achieve a solution (which may not be the right solution after all).

JSF 2 reusing the validation defined in the JPA entities?

Let's start with an example :
In my JPA entity
public class User {
#Pattern("^([0-9a-zA-Z]([-.\w]*[0-9a-zA-Z])*#([0-9a-zA-Z][-\w]*[0-9a-zA-Z]\.)+[a-zA-Z]{2,9})$", message="invalidEmailResourceBundleKey")
private String email;
#Min(5, message="minimumResourceBundleKey")
private int age;
...
}
In my JSF Bean
public class UserBean {
private User user;
// do i have to redefine it here, since it's already a part of the user ?
##Pattern("^([0-9a-zA-Z]([-.\w]*[0-9a-zA-Z])*#([0-9a-zA-Z][-\w]*[0-9a-zA-Z]\.)+[a-zA-Z]{2,9})$")
public String getEmail() {
return user.getEmail();
}
public void setEmail(String s) {
user.setEmail(s);
}
// do i have to redefine it here, since it's already a part of the user ?
#Min(5, message="minimumResourceBundleKey")
public int getAge() {
return user.getAge();
}
public void setAge(int age) {
user.setAge(age);
}
}
Is it possible to reuse the the validations for the entities for the JSF beans that actually delegates the method calls to the entities, so that i dont have to redefine the bean validations on the JSF beans ?
Can i even extend the reusing to the level of the error message in resource bundle, and whether the message can be parameterized with {0} etc like the usual ? I wonder if there's any example on the web for this, since i've been unable to find none.
Please share your thoughts on this ..
Thank you !
You don't need to redefine them if you don't unnecessarily flatten the bean properties. Just have a getUser() instead.
public class UserManager {
private User user;
public User getUser() {
return user;
}
}
And bind to the properties of the JPA entity directly.
<h:inputText value="#{userManager.user.email}" />
<h:inputText value="#{userManager.user.age}" />
Unrelated to the concrete problem, your email regex will fail for internationalized domain names (IDN) which are introduced last year. I'd fix the regex to not only accept latin characters. See also this answer for an example.

Resources