Showing posts with label jsf. Show all posts
Showing posts with label jsf. Show all posts

27 December 2016

this is why I don't like prime* frameworks

Primefaces is a heavyweight framework, I don't prefer to use it on my next project.

However, as angular js is promising, I looked into primeng: http://www.primefaces.org/primeng/  hopefully to find it more lightweight than its parent/sibling; primefaces.

But I think still it is heavyweight framework that had to generate too much HTML to get simple staff done, here's the example HTML generated code for bootstrap PRIMARY button:
<button label="Primary" pbutton="" type="text" class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only">
<span class="ui-button-text ui-c">Primary</span>
</button>
What's the heck, why button of type text that have an internal span, and none of them bootstrap classes so I can easily customize easily later, but instead prime specific classes (I think same as primefaces classes)

Also, the autocomplete component:
<p-autocomplete field="name" placeholder="Countries" class="ng-valid ng-touched ng-dirty">
 <span class="ui-autocomplete ui-widget">
  <!--template bindings={}--><input autocomplete="off" pinputtext="" type="text" class="ui-autocomplete-input ui-inputtext ui-corner-all ui-state-default ui-widget" placeholder="Countries" size="30"><!--template bindings={}--><!--template bindings={}-->
  <div class="ui-autocomplete-panel ui-widget-content ui-corner-all ui-shadow" style="display: none; width: 100%; max-height: 200px; z-index: 1001; opacity: 1.055; top: 28px; left: 0px;">
   <ul class="ui-autocomplete-items ui-autocomplete-list ui-widget-content ui-widget ui-corner-all ui-helper-reset">
    <!--template bindings={}-->
   </ul>
  </div>
 </span>
</p-autocomplete>
Why? here's the corresponding generated code of ng2-bootstrap: http://valor-software.com/ng2-bootstrap/#/dropdowns:

<input class="form-control ng-valid ng-dirty ng-touched">
Yes, that's it.
I think I will not consider any prime* products unless this huge html code stop being generated!

13 April 2010

Using Converter with SelectOneMenu in JSF

Using Converter with SelectOneMenu in JSF

I were working in some use case that required me to use JSF Converters with SelectOneMenu component, I've searched for the solution, but really I ended messy without any helpful and "clean" result.

So, I decided to write this topic to be a clean guide on how to use Converters with Lists in general and SelectOneMenu in particular.

As you know, all input controls in html form accepts only character Strings, you cannot enter an Object in some textbox for example.
So, Converts in JSF enables you to convert from String to some Object and back from some Object to String.

Suppose you have a List of Object Faculty and you need to represent it in a SelectOneMenu control (dropdown list), one way is to create this SelectOneMenu and backed it to an integer value, and I prefer that way if your use case can goes with it.

Example,

here's the JSF snipet:

<h:selectOneMenu value="#{registerBean.faculty}">
<f:selectItems value="#{registerBean.facultyItems}" />
</h:selectOneMenu>



And here's the backing bean:

public class RegisterBean{
private String faculty;
private List<SelectItem> facultyItems;

// getter & setter for faculty
// ....

//setter for facultyItems;
...

//getter for facultyItems
public List<SelectItem> getFacultyItems(){
if (facultyItems == null){
facultyItems = new ArrayList<SelectItem>();
FacultyService fs = ServiceFactory.getFacultyService();
List<Faculty> facList = fs.getAllFaculties();
for (Faculty fac : facList){
facultyItems.add(new SelectItem(
fac.getId()
, fac.getName()); // value, label, the value to choose and label to appear fo the user
}
}
return facultyItems;
}
}


And then, when the use select the faculty, the id corrosponding to it is being assigned to the varaible faculty.
This is the best way I suggest if your use case that simple, Don't try to drill in the issue of Converting from Objects to String and vice versa if you can.
Note, here you mapped the integer Id to the String that contains the value of the html SELECT tag:

<select >
<option value="1">التجاره</option>
<option value="2">الأداب</option>
<option value="3">السياحه و الفنادق</option>
<option value="4">الحقوق</option>
<option value="5">العلوم</option>
<option value="6">الهندسه</option>
<option value="7">التربيه</option>
</select>


So, the getFaculty() property on the bean returns one value from 1 to 7, this that we assigned in the 7th line in the method getFacultyItems()


But if you have to do so, Here's the way.
Let's try to rewrite the above example by using Converters,
Suppose you want to back the SelectOneMenu directly to Faculty Object, the JSF Page will still as is -for now, but we need to modify the backing bean first:

public class RegisterBean{
private Faculty faculty;
private List<SelectItem> facultyItems;

// getter & setter for faculty
// ....

//setter for facultyItems;
...

//getter for facultyItems
public List<SelectItem> getFacultyItems(){
if (facultyItems == null){
facultyItems = new ArrayList<SelectItem>();
FacultyService fs = ServiceFactory.getFacultyService();
List<Faculty> facList = fs.getAllFaculties();
for (Faculty fac : facList){
facultyItems.add(new SelectItem(
fac // NOTE THIS CHANGE, we used Faculty object instead of its id property
, fac.getName()); // value, label, the value to choose and label to appear fo the user
}
}
return facultyItems;
}
}


So, we can get the Faculty object directly instead of getting its Id and then looking up it in the database.
That is not all the story, it is the start, just continue reading...

In the first example, we told the JSF to convert from/to int (the type of Id) to String (the value appears on the form), and JSF can handle this very well, but in the second example, we need to tell JSF to convert from/to Faculty to String.

To do so, we need to implement javax.faces.convert.Converter interface, here's the code:

package com.forat.web.converters;

import java.util.ResourceBundle;

import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.ConverterException;

import com.forat.model.Faculty;
import com.forat.web.util.StaticInitializer;

public class FacultyConverter implements Converter {

@Override
public Object getAsObject(FacesContext context, UIComponent component, String newValue) {
Faculty faculty = null;
try {
faculty = StaticInitializer.getPreLoadedFaculty(Integer.parseInt(newValue));
}catch(Throwable ex) {
ResourceBundle bundle = ResourceBundle.getBundle("messages");
FacesMessage msg = new FacesMessage(bundle.getString("faculty_convertion_message"));
msg.setSeverity(FacesMessage.SEVERITY_ERROR);
throw new ConverterException(msg);
}
return faculty;
}

@Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
String val = null;
try {
Faculty fac = (Faculty) value;
val = Integer.toString(fac.getId());
}catch(Throwable ex) {
ResourceBundle bundle = ResourceBundle.getBundle("messages");
FacesMessage msg = new FacesMessage(bundle.getString("faculty_convertion_message"));
msg.setSeverity(FacesMessage.SEVERITY_ERROR);
throw new ConverterException(msg);
}
return val;
}

}


The "getAsObject()" method is responsble for the conversion between the page and the backing bean (when the request submitted and to be precessed on the server.
The method "getAsString()" is responsble for the conversion between the Server and the html page (when the rendering process occure to display the value of the object)


When the request is recived by the Server (JSF ) we tell JSF in "getAsObject()" to:
faculty = StaticInitializer.getPreLoadedFaculty(Integer.parseInt(newValue));

take the value sent and get the corrosponding object from somewhere (the database for example).
notice the try/catch block, we have to throw ConverterException in case of conversion errors.

When the response to be rendered, in "getAsString()", we need to tell JSF to instead of display the entire object, just to display the unique identier of it (the id property)

Now we need to register this Converter, we can do this in many ways, for example by registering it in faces-conf.xml:

<converter>
<converter-id>com.forat.web.converters.Faculty</converter-id>
<converter-class>com.forat.web.converters.FacultyConverter</converter-class>
</converter>



And in the JSF page, we need to tell in the SelectOneMenu tag to use this conveter:
<h:selectOneMenu value="#{employee.faculty}">
<f:converter converterId="com.forat.web.converters.Faculty" />
<f:selectItems value="#{registerBean.facultyItems}" />
</h:selectOneMenu>


That's all, hope this post to be usful for you.