Toggle Image on select in JSF extendedDataTable - jsf-2

I am trying to get an image to swap back and forth based on if a row is selected in an extenedDataTable. I am able to display the image in the non-active state but can't figure out how to toggle it. Here is the table definition code:
<rich:extendedDataTable style="width: 800px; height: 150px;"
rowClasses="Row0,Row1" value="#{myBean.exceptions}" var="exception"
selectionMode="single" id="Table" selection="#{myBean.exceptionSelection}">
<a4j:ajax event="selectionchange" listener="#{myBean.rowListener}" render=""/>
Here is the column whose image I want to toggle. The idea is to change to an image called filledRadioButton in the same directory:
<rich:column id="selected_col" label="Selection">
<f:facet name="header">
<a4j:commandLink value="Selection" render="table"/>
</f:facet>
<h:graphicImage value="../resources/img/emptyRadioButton.jpg"/>
</rich:column>
Thanks

You can use the dataTable's ajaxKeys attribute to specifically reference a row (or rows) for ajax update. So to effect this :
Bind the ajaxKeys attribute of your data table to a Set<Integer> in your backing bean. This set will hold unique id type values that will refer to specific entities in your datatable to be updated in an ajax response.
Add the id attribute of the <h:graphicImage/> you wish to update via ajax to the render list of your <a4j:ajax/>. Set the value of the image to a dynamic expression so you can switch it out in the backing bean
<a4j:ajax event="selectionchange" listener="#{myBean.rowListener}" render="indicatorImg"/>
<h:graphicImage id="indicatorImg" value="#{myBean.desiredImagePath}"/>
Wire your ajax listener to add the id of the selected entity to the ajaxKeys Set and modify the desiredImagePath property as you see fit.
public void rowListener(AjaxBehaviourEvent evt){
//I assume you're already managing your selection properly
//Change the value of the desiredImagePath here too.
ajaxKeysSet.add(mySelection.getId()); //if you want to update multiple rows
OR
ajaxKeysSet = Collections.singleton(mySelection.getId()); //save a single id for ajax update
}

Related

Prime Faces InputText inside an ordered list

I have a requirement in primefaces to have an inputText inside an orderlist and on changing the inputText want to reflect it in the object model. But i suppose there is a bug or some kind of problem as whenever I submit the form there is a null pointer error. It says that the object is unreachable. The weird part is that it does show the correct data (ie. gets the data) but is unable to set it.
<p:orderList value="#{artifactController.uploadedFiles}"
var="uploadedFile" itemValue="#{uploadedFile}"
controlsLocation="left" id="artifactList"
converter="customUploadedFileConverter"
selection="#{artifactController.selectedUploadedFile}"
selectionMode="single">
<p:column style="width:25%">
<p:graphicImage
value="/faces/pages/image#{uploadedFile.imagePath}?mimeType=#{uploadedFile.mimeType}"
width="100" height="50">
</p:graphicImage>
</p:column>
<p:column style="width:75%;">
<p:inputText value = #{uploadedFile.fileName} ></p:inputText>
</p:column>
</p:orderList>
The Controller has all the setters and getters in place.
The input text shows the data while retrieving but fails to update the value in the controller. Isn't it supposed to work like that (similar to dataTable). It gives uploadedFile is unreachable error.

can't refresh a selectOneMenu

first excuse my english if it's not correct ...
I've a probleme with a primeface's component, I'm trying to refresh a p:selectOneMenu from a p:commandButton, but it's doesn't work (it 's work on another xhtml page, but not here and I can't understand why ...)
First I select an item from an p:autocomplete which update a backingbean's attribute ( for example : userChoose ).
then the p:commandButton is able to call his listener and add userChoose to a list, but i can't refresh the selectOneMenu that display the list. I have to use another p:commandButton to refresh the list.
My form is included into a p:tabMenu in another xhtml page.
<p:autoComplete id="acPojo" value="#{forumBean.user}"
completeMethod="#{autoCompleteBean.completeUser}"
converter="#{userConverter}" forceSelection="true"
var="usr" itemLabel="#{usr.loginUtilisateur}" itemValue="#{usr}">
<p:column>
<h:outputText value="#{usr.loginUtilisateur}"/>
</p:column>
</p:autoComplete>
<p:commandButton value="ajouter" process="acPojo #this "
udpate=":tabView:formSujet:listeUser" actionListener="#{forumBean.addUser}"/>
<p:selectOneMenu value="#{forumBean.user}" converter="#{userConverter}" var="us" id="listeUser"
itemValue="#{us}" itemLabel="#{us.loginUtilisateur}">
<f:selectItems value="#{forumBean.newSujet.listeUserAllowed}" var="User"
itemValue="#{User}" itemLabel="#{User.loginUtilisateur}" />
<p:column>
<h:outputText value="#{us.loginUtilisateur}"/>
</p:column>
<p:ajax process="#this" />
</p:selectOneMenu>
<p:commandButton id="refreshAdmin" icon="ui-icon-arrowrefresh-1-w"
update=":tabView:formSujet:listeUser" />
Thanks for help.
From your code:
udpate=":tabView:formSujet:listeUser"
This has at least 2 (potential) mistakes. The right attribute name is update, not udpate. The one on your other button has however the right attribute name.
It that still doesn't work, then the other potential mistake is that the client ID tabView:formSujet:listeUser does not exist in HTML DOM tree (and thus JavaScript/jQuery is unable to find and replace it). That can happen if the <p:tabView> is dynamic (i.e. you're using <p:tabView value="#{bean.tabs}" var="tab">, because it prepents the tab index number in the final client ID like so tabView:0:formSujet:listeUser if it's the 1st tab.
But, after all, as both the dropdownlist and the commandbutton are in the same NamingContainer parent, you don't need an absolute client ID at all. Just the relative client ID should suffice:
update="listeUser"
Fix that on your both buttons.
See also:
How to find out client ID of component for ajax update/render? Cannot find component with expression "foo" referenced from "bar"

Initial sortorder for PrimeFaces datatable with multisort

I am trying to implement multisort on Primeface datatable. We are using Primefaces v3.5. I have created a new load method in the LazyLoadClass that takes the List of SortMeta> parameter.
But I am having issues in the initial load of the table. The List of SortMeta> is null when the load method is called. I have also tried without specifying the initial sortBy and sortOrder for the datatable. In both the cases the result is the same.
Seeing that we have this new class SortMeta to support multisort, I suspect that the way to specify the initial sort field and order would have also changed. But I couldn't find any example anywhere to point the difference. The manual 3.5 doesn't mention any difference.
Why we could be getting the List of SortMeta> as null? Any pointers on example code where multisort is used with Lazyload?
I was able to get this to work.
Essentially we need to provide the UIColumn in the SortMeta object for it to work. For the initial sort at render time, I had to find the component in my bean and assign that to the sortMeta.
Below is my code in the view xhtml
<p:dataTable id="transDataTable" var="trans"
value="#{myBean.transModel}" paginator="true" rows="50"
paginatorAlwaysVisible="false" lazy="true"
sortMode="multiple" sortBy="#{myBean.preSortOrder}"
resizableColumns="true">
<p:column headerText="User" sortBy="#{trans.user.name}" >
#{trans.user.name}
</p:column>
<p:column headerText="Company" sortBy="#{trans.companyName}">
#{trans.companyName}
</p:column>
<p:column headerText="Join Date" id="joinDateTime"
sortBy="#{trans.joinDateTime}" >
<h:outputText value="#{trans.joinDateTime}" />
</p:column>
</p:dataTable>
Here is my bean code called on #PostConstruct
/*
* method to build initial sort order for multisort
*/
private void buildSortOrder() {
UIViewRoot viewRoot = FacesContext.getCurrentInstance().getViewRoot();
UIComponent column = viewRoot.findComponent("transDataTable:joinDateTime");
SortMeta sm1 = new SortMeta();
sm1.setSortBy((UIColumn)column);
sm1.setSortField("joinDateTime");
sm1.setSortOrder(SortOrder.DESCENDING);
preSortOrder.add(sm1);
}
I am not sure this is the right way to do this, but it works. I am usually uncomfortable when we have to use the ids from view in the bean code, as that can introduce bugs when people are not careful.
Thanks #CagatayCivici for the quick hint.

Select Item from many menu

Ok I have a simple many menu in wich I call a listener
<p:selectManyMenu style="width: 100%;" id="cmbsectores" valueChangeListener="#{mbcompletado.removeItem}">
<f:selectItems value="#{mbcompletado.sectores}"/>
<f:ajax update="#this"/>
</p:selectManyMenu>
I am looking the way I can use the ValueChangeEvent pass as parameter to detect which item was selected??
So I can use my business logic!
Do i need to use ajax tag? I found an itemSelect event in primeface, framework which I am using, but it only works on charts components!
Thanks in advance
Since you are already using PrimeFaces use p:ajax instead of f:ajax. The event is already set to the appropriate event (valueChanged).
To detect the selected values of the selectManyMenu the value attribute is necessary:
<p:selectManyMenu style="width: 100%;" id="cmbsectores"
value="#{mbcompletado.selectedSectores}">
<f:selectItems value="#{mbcompletado.sectores}"/>
<p:ajax/>
</p:selectManyMenu>
You can remove the valueChangeListener listener altogether.
For a more complete example see SelectManyMenu.
EDIT:
In your backing bean mbcompletado.selectedSectores should point to a collection of the same type like your mbcompletado.sectores. For example, if your sectores is a List of TypeA, selectedSectores should be also a List of the same type (TypeA).
Similar backing-bean structure can be found in the following example SelectManyCheckbox.
You need the <f:ajax listener> (or in this case better <p:ajax listener>) method instead. The ValueChangeListener serves an entirely different purpose and should only be used when you're really interested in both the old and new value, not when you're only interested in the new value.
E.g.
<p:selectManyMenu value="#{bean.selectedSectors>
<f:selectItems value="#{bean.availableSectors}"/>
<p:ajax listener="#{bean.selectedSectorsChanged}" />
</p:selectManyMenu>
with
private List<String> selectedSectors;
private List<String> availableSectors;
public void selectedSectorsChanged() {
System.out.println("Selected sectors are: " + selectedSectors); // Look, JSF has already set it.
// ...
}
See also:
When to use valueChangeListener or f:ajax listener?

How to render an element whose id is automatically generated in JSF?

I have primefaces'datatable placed on primefaces tabView..
I m using filtering on it. As new values are updated in the grid, I want to re-render the filters.
The filter id is generated as: tabViewId:ActiveTabIndex:DatatableID:ColumnName_filter.
On value change of input text, I want to re-render the filter.
<p:column width="40">
<h:inputText id="vendorInputTxt" value="#{articlePromo.proveedor}"
styleClass="inputTextStyle">
<f:ajax event="change" render=":categoryTabView:0:promotionDetail_dataTable:vendorColumnHeader_filter"
listener="#{promotionDetailManagedBean.onProveedorChange}" />
</h:inputText>
</p:column>
But it gives the error, contains an unknown id ':categoryTabView:0:promotionDetail_dataTable:vendorColumnHeader_filter' - cannot locate it in the context of the component vendorInputTxt
What is the right way to render the filter again?
Thanks,
Shikha
try a js call oncomplete to: widget_<dataTableId>.filter(); where the dataTableId is the id given to the dataTable.

Resources