I have a code:
<h:panelGroup>
<p:panel>
<p:commandButton value="Go" style="background:#25A6E1;color:#fff;font-family:'Helvetica Neue',sans-serif;font-size:10px;border-radius:4px;"
actionListener="#{customCalender.searchUserofList}" update="picklist">
<f:attribute name="trigram" value="#{customCalender.listTrig}"/>
<f:attribute name="firstName" value="#{customCalender.listFname}"/>
<f:attribute name="lastName" value="#{customCalender.listLname}"/>
<f:attribute name="teamName" value="#{customCalender.selectedTeam}"/>
</p:commandButton>
</p:panel>
</h:panelGroup>
<h:panelGroup id="picklist" rendered="#{not empty customCalender.searchList}">
<p:pickList value="#{customCalender.searchList}" var="user" itemLabel="#{user}" itemValue="#{user}"/>
</h:panelGroup>
and the searchList generates on button click in the method searchUserofList().
I declared searchList as:
private DualListModel searchList;
public DualListModel<String> getSearchList() {
return searchList;
}
public void setSearchList(DualListModel<String> searchList) {
this.searchList = searchList;
}
and its being defined in method searchUserofList method like:
List<EmpBean> list = new ArrayList<EmpBean>();
list = getSearchResult("people",trigram,firstName,lastName,teamName);
Iterator<EmpBean> iterator = list.iterator();
List<String> userList = new ArrayList<String>();
List<String> userTarget = new ArrayList<String>();
while(iterator.hasNext()){
String userName = iterator.next().getStrUserid();
System.out.println("Name :: "+userName);
userList.add(userName);
}
searchList = new DualListModel<String>(userList, userTarget);
But when button clicked it gets the list but the picklist with the values are not shown.
How can I make that correct to show the picklist?Please suggest.
You can't update dynamically a component that is not rendered, you should move your rendered attribute so your component always exists.
<h:panelGroup id="picklist">
<p:pickList rendered="#{not empty customCalender.searchList}" value="#{customCalender.searchList}" var="user" itemLabel="#{user}" itemValue="#{user}"/>
</h:panelGroup>
Related
i'm having some questions here. I will appreciate all of your helps.
I'm making some dynamic multilevel menu in primefaces, and i did it. There are parents, sub menus, and the menu items.
I want to give some CRUD action for each component via context menu, so I can edit the value/text for each level just with right-click.
I make the menu with bean called MenussBean.java, and you can see it below (just the correspond code).
public Submenu subMenus(Submenu parentMenus,String i, int id)
{
if(i==""&&parentMenus==null)
{
subList = menusdao.getRootMenu();
for(int a=0;a<subList.size();a++){
parentMenus = new Submenu();
parentMenus.setLabel(subList.get(a).getMenu());
model.addSubmenu(parentMenus);
i=subList.get(a).getMenu();
subMen = null;
id = a+1;
subList2 = subKategori(id);
for(Menus k:subList2){
if(String.valueOf(parentMenus.getLabel().toString()).equals(i)){
subMen = new Submenu();
subMen.setId("_"+k.getId());
subMen.setLabel(k.getMenu());
parentMenus.getChildren().add(subMen);
subMenus(subMen,k.getMenu(),k.getId());
}
}
}
}else{
subMen = null;
subList2 = subKategori(id);
for(Menus k:subList2){
if(String.valueOf(parentMenus.getLabel().toString()).equals(i)){
subList3=subKategori(k.getId());
if(subList3.size()==0)
{
UIParameter uiParam = new UIParameter();
UIParameter menuParam = new UIParameter();
UIParameter idParentParam = new UIParameter();
uiParam.setName("idParam");
uiParam.setValue(k.getId());
menuParam.setName("menuParam");
menuParam.setValue(k.getMenu());
idParentParam.setName("idParentParam");
idParentParam.setValue(k.getId_parent());
MenuItem mi = new MenuItem();
mi.setId("_"+k.getId());
Application app = FacesContext.getCurrentInstance().getApplication();
MethodExpression methodExpr = app.getExpressionFactory().createMethodExpression
(FacesContext.getCurrentInstance().getELContext(), "#{menussBean.onItemClick}", null ,new Class[]{ javax.faces.event.ActionEvent.class});
mi.addActionListener(new MethodExpressionActionListener(methodExpr));
mi.setOncomplete("");
mi.setValue(k.getMenu());
mi.setTarget("_self");
mi.setTitle(k.getLink());
mi.setAjax(false);
mi.getChildren().add(uiParam);
mi.getChildren().add(menuParam);
mi.getChildren().add(idParentParam);
mi.setProcess("#all");
parentMenus.getChildren().add(mi);
}
else if (subList3.size()!=0)
{
subMen = new Submenu();
subMen.setId("_"+k.getId());
subMen.setLabel(k.getMenu());
parentMenus.getChildren().add(subMen);
subMenus(subMen,k.getMenu(),k.getId());
}
}
}
}
return parentMenus;
}
public List<Menus> subKategori(int i)
{
arayList=new ArrayList<Menus>();
for(Menus k:getList()){
if(k.getId_parent()==i){
arayList.add(k);
}
}
return arayList;
}
public static List<Menus> getList() {
return list;
}
This is the value-getter method:
public void onItemClick() {
FacesContext context = FacesContext.getCurrentInstance();
idItem = context.getExternalContext().getRequestParameterMap().get("idParam");
menuItem = context.getExternalContext().getRequestParameterMap().get("menuParam");
idParentItem = context.getExternalContext().getRequestParameterMap().get("idParentParam");
}
And I want to use context menu to give the CRUD operations, so the user can right-click on the component he wants to edit. Here is my xhtml files.
<h:form>
<p:panelMenu id="panel" style="width:400px;font-size:12px"
model="#{menussBean.model}" var="detail" selectionMode="single" ajax="true"
widgetVar = "panelMen" styleClass="myMeineClass">
</p:panelMenu>
<p:contextMenu for="panel" style="font-size:12px">
<p:menuitem value="View" icon="ui-icon-search"
oncomplete="menuDialog.show()" update="display">
<f:param name="id_barangbaru" value="#{detail}" />
</p:menuitem>
<p:menuitem value="Add" icon="ui-icon-plus" />
<p:menuitem value="Edit" icon="ui-icon-pencil" />
<p:menuitem value="Delete" icon="ui-icon-close" />
</p:contextMenu>
<p:dialog header="Menu Detail" widgetVar="menuDialog"
resizable="false" width="200" showEffect="clip" hideEffect="fold"
id="dialog" appendToBody="true" modal="true">
<h:panelGrid id="display" columns="2" cellpadding="4" style="font-size:12px">
<h:outputText value="ID:" />
<h:outputText value="#{menussBean.idItem}"
style="font-weight:bold" />
<h:outputText value="Label:" />
<h:outputText value="#{menussBean.menuItem}"
style="font-weight:bold" />
<h:outputText value="Parent:" />
<h:outputText value="#{menussBean.idParentItem}"
style="font-weight:bold" />
</h:panelGrid>
</p:dialog>
</h:form>
Right now, I'm still getting the value into the context menu output text, but it needs to be left-clicked first. I need to pass the value directly just with right-click.
So, how can I get the value with actionListener with right-click? Please help...
I want to show the screenshot but I'm new here, so I haven't got any reputation.
In my JSF application, I use a rich:dataTable as follows:
<rich:dataTable id="itemTable" value="#{backingBean.itemsList}" var="i" >
<rich:column> <f:facet name="header">ItemValue</f:facet>
<h:inputText id="myId" value="#{i.value}" style="width: 30px" />
</rich:column> </rich:dataTable>
<h:commandButton id="saveB" value="Save" action="#{backingBean.doSave()}" />
Bean code of doSave:
public String doSave() {
Iterator<Item> = itemsList.iterator();
while(iter.hasNext()) {
//do something
}
}
In the doSave()-Method, i need to know the row index of the current Item, is there a way to achieve this?
While Richfaces extended data tables support a selection management, Richfaces datatables don't.
What I found the easiest way to do to retrieve a somehow selected item from a list, is to add an icon to every row. For this, put the command-Button into the data table itself:
<rich:dataTable id="itemTable" value="#{backingBean.itemsList}" var="i" >
<rich:column>
<h:inputText id="myId" value="#{i.value}" />
<h:commandButton id="saveB" action="#{backingBean.doSave}" />
</rich:column>
</rich:dataTable>
In the bean code, provide the method doSave but with an additional parameter ´ActionEvent´
public String doSave(ActionEvent ev) {
Item selectedItem = null;
UIDataTable objHtmlDataTable = retrieveDataTable((UIComponent)ev.getSource());
if (objHtmlDataTable != null) {
selectedItem = (Item) objHtmlDataTable.getRowData();
}
}
private static UIDataTable retrieveDataTable(UIComponent component) {
if (component instanceof UIDataTable) {return (UIDataTable) component;}
if (component.getParent() == null) {return null;}
return retrieveDataTable(component.getParent());
}
You see, that the ActionEvent ev provides you with the source element (UIComponent)ev.getSource(). Traverse through it until you hit the UIDataTable element and use it's row data.
Possible way two is to justgive the element as parameter with the function call:
<rich:dataTable id="itemTable" value="#{backingBean.itemsList}" var="i" >
<rich:column>
<h:inputText id="myId" value="#{i.value}" />
<h:commandButton id="saveB" action="#{backingBean.doSave(i)}" />
</rich:column>
</rich:dataTable>
and in the bean
public String doSave(Item item) {
// do stuff
}
That's not as clean, but should work with the EL, too. Hope, it helps...
I have a selectOneMenu and a dataTable. When I change the selected value, dataTable will repopulate.
A one of column of the dataTable is an inputText. The problem is that the inputText field doesn't call the getter, but caches the previous value.
I want to either call the getter by force or set inputText to not be cached.
How do I get rid of this problem?
<h:body>
<f:view>
<h:form id="headForm">
<ice:selectOneMenu id="item"
value="#{outerBean.selectedItem}"
valueChangeListener="#{outerBean.itemListValueChanged}"
style="width: 158px;" required="true"
label="Supplier Id" partialSubmit="true">
<f:selectItems value="#{outerBean.itemList}" />
</ice:selectOneMenu>
<ice:dataTable id="pdet" value="#{outerBean.nestedClassList}" var="nestedObject" rendered="true">
<ice:column>
<f:facet name="header">Order Number</f:facet>
<ice:outputText value="#{nestedObject.orderNumber}" />
</ice:column>
<ice:column>
<f:facet name="header">Qty</f:facet>
<ice:inputText value="#{nestedObject.qty}" id="qty" label="'Qty' FOR 'Order Number':#{nestedObject.orderNumber} "
partialSubmit="true"
valueChangeListener="#{nestedObject.qtyChanged}"
validator="#{nestedObject.validateQty}">
</ice:inputText>
</ice:column>
</ice:dataTable>
</h:form>
</h:view>
public class OuterBean{
private List<String> itemList = new ArrayList<String>();
private String selectedItem;
private List<NestedClass> nestedClassList = new ArrayList<NestedClass>();
public OuterBean(){
//init values
}
public void itemListValueChanged(ValueChangeEvent e){
selectedItem = (String)e.getNewValue();
//reset the dataTable record list
nestedClassList = getRandomRecords();
}
//---getters-setters-----//
private class NestedClass{
private int orderNumber;
private int qty;
NestedClass(){
orderNumber = generateOrderNumber();
qty = getRandomQty();
}
//-----qtyChangedListener----//
//-----qtyValidator----------//
//-----getters-setters-------//
}
}
I don't see where you are chainging nestedObject.qty in itemListValueChanged
The component will not rerender unless it is changed .
Partial Submit in Icefaces will only update the components whose value have changed.
You can make Partial Submit false on selectonemenu or you can reinitialize the value of the inputText in itemListValueChanged.
I have a h:datatable showing a list of rows, and the fields of each row are input fields.
I render an "Add Row" button before the table, and a "Remove Row" button on each row of the table.
The baking bean is viewScoped, and the buttons add/remove elements from the java list in the backing bean, and then return to the same view.
I set the immediate attribute to "true" in the buttons in order to not validate the input fields when I add or remove a row.
Everything works ok but one thing: the values of the input fileds are cleared. I thought that the view kept the values beacuse the bean is viewScoped.
How can I achieve adding/removing rows without triggering validations and keeping the values that were already typed by the user in the form?
My view:
<h:form>
<h:commandButton value="Añadir Fila" immediate="true" action="#{tablaController.addRowAction}" />
<h:dataTable value="#{tablaController.lista}" var="fila" cellpadding="0" cellspacing="0" border="1">
<f:facet name="header">TABLA</f:facet>
<h:column>
<f:facet name="header"><h:outputLabel value="NOMBRE" /></f:facet>
<h:inputText id="nom" value="#{fila.nombre}" />
<h:message for="nom" class="msjError" />
</h:column>
<h:column>
<f:facet name="header"></f:facet>
<h:commandButton value="Quitar Fila" immediate="true" action="#{tablaController.removeRowAction(fila)}" />
</h:column>
</h:dataTable>
</h:form>
My backing bean:
#ManagedBean(name="tablaController")
#ViewScoped
public class TablaController {
private List<Fila> lista;
...
public TablaController() { }
...
#PostConstruct
public void init() {
this.lista = new ArrayList<Fila>();
for (int i=0; i<5; i++) {
Fila fila = new Fila();
fila.setNombre("");
this.lista.add(i,fila);
}
}
...
public String addRowAction () {
Fila fila = new Fila();
fila.setNombre("");
this.lista.add(fila);
return "";
}
public String removeRowAction (Fila f) {
boolean exito = this.lista.remove(f);
return "";
}
...
}
UPDATE --> MY SOLUTION:
I write here my solution if someone is interested.
The problem is that I use immediate="true" to skip validations, but this makes to skip the update_model_values too, so that the values entered by the user in the form are lost after clicking the add/remove buttons and re-redenring the page.
As I use "JSR-303 bean validation", my solution was to skip validations using the f:validateBean to enable/disable them. Depending on the button I click, if I want the validations to execute, I enable the bean validation (for example in a "submit" button), and if I want to skip them, I disable bean validation (like in the add/remove row buttons). But anyway the update_model_values always executes, so the values are not lost.
Here's the view:
<h:form>
<f:validateBean disabled="#{!empty param['disableValidation']}">
<h:commandButton value="Añadir Fila" action="#{tablaController.addRowAction}">
<f:param name="disableValidation" value="true" />
</h:commandButton>
<h:dataTable value="#{tablaController.lista}" var="fila" cellpadding="0" cellspacing="0" border="1">
<f:facet name="header">TABLA</f:facet>
<h:column>
<f:facet name="header"><h:outputLabel value="NOMBRE" /></f:facet>
<h:inputText id="nom" value="#{fila.nombre}" />
<h:message for="nom" class="msjError" />
</h:column>
<h:column>
<f:facet name="header"></f:facet>
<h:commandButton value="Quitar Fila" action="#{tablaController.removeRowAction(fila)}">
<f:param name="disableValidation" value="true" />
</h:commandButton>
</h:column>
</h:dataTable>
<h:commandButton value="Submit" action="#{tablaController.saveData}" />
</f:validateBean>
</h:form>
The backing bean:
#ManagedBean(name="tablaController")
#ViewScoped
public class TablaController {
private List<Fila> lista;
...
public TablaController() { }
...
#PostConstruct
public void init() {
this.lista = new ArrayList<Fila>();
for (int i=0; i<5; i++) {
Fila fila = new Fila();
fila.setNombre("fila "+i);
this.lista.add(i,fila);
}
}
...
public String addRowAction () {
Fila fila = new Fila();
fila.setNombre("");
this.lista.add(fila);
return "";
}
public String removeRowAction (Fila f) {
this.lista.remove(f);
return "";
}
...
public String saveData () {
...
//processes the valid data
//for example, calls to a service method to store them in a database
...
return "";
}
...
}
I set the immediate attribute to "true" in the buttons in order to not validate the input fields when I add or remove a row.
immediate="true" is the wrong tool for the job. It should be used to prioritize validation, not to enable/disable validation. The difference is rather huge as you encountered yourself.
You want to trigger validation conditionally. In case of e.g. required="true" that'd be as easy as
<h:inputText ... required="#{saveButtonPressed}" />
where #{saveButtonPressed} evaluates true when the save button is pressed. E.g. when its client ID is present in request parameter map.
In case of JSR 303 bean validation, that'd be a matter of
<f:validateBean disabled="#{not saveButtonPressed}">
<h:inputText ... />
</f:validateBean>
or with OmniFaces <o:validateBean> which allows controlling that on a per-command basis.
<h:commandButton id="add" ...>
<o:validateBean disabled="true" />
</h:commandButton>
I had exactly the same problem. In short, you can NOT use immediate for action that update data table(UIData) or facelet repeat. Short explanation:submitted values are not kept for re-display if inputs in UIData do not go through validation. Long explanation can be found here: long explanation and a related bug in Mojarra
How can I add in commandbutton inside datatable?
<hx:dataTableEx value="#{searchData.searchFriends}" var="s">
<hx:columnEx>
<f:facet name="header">
<h:outputText value="First Name" />
</f:facet>
<hx:requestLink action="#{pc_Search.doAddFriendAction}">
<h:outputText value="Add as Friend" />
<f:param name="friendId" value="#{s.memberId}" />
</hx:requestLink>
</hx:columnEx>
</hx:dataTableEx>
To get the data at backend
String friendId = (String)getRequestParam().get("friendId");
But once I change the requestlink to command button the friedId = null? any idea how can i pass value using command button
Wrap the datatable value in a DataModel. Then you can obtain the selected row by DataModel#getRowData().
public class Bean {
private List<Friend> friends;
private DataModel friendsModel;
public Bean () {
friends = getItSomehow();
friendsModel = new ListDataModel(friends);
}
public void addAsFriend() {
Friend selectedFriend = (Friend) friendsModel.getRowData();
// ...
}
}
with
<h:dataTable value="#{bean.friendsModel}" var="friend">
<h:column>
<h:commandButton value="Add as friend" action="#{bean.addAsFriend}" />
</h:column>
</h:dataTable>
Should work as good with IBM Faces Client Framework (those hx: components).