I want to use a LazyDataModel List inside a SelectOneMenu, but the selectoneMenu doesn't show anything . this is my code
public void show() {
beneficiaries = new LazyDataModel<Fournisseur>() {
private static final long serialVersionUID = 1L;
private List<Fournisseur> list;
#Override
public List<Fournisseur> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String,Object> filters){
list = service.getAll((String)filters.get("benef.intitule"),first, pageSize);
this.setRowCount(service.count((String)filters.get("benef.intitule")));
return list;
}
#Override
public Object getRowKey(Fournisseur obj) {
return obj.getCpt();
}
#Override
public Fournisseur getRowData(String rowKey) {
Fournisseur o=null;
if(rowKey != null) {
for (Fournisseur obj : list) {
if(rowKey == obj.getCpt()) {
o = obj;
}
}
return o;
}else {
return null;
}
}
};
}
this is my html code
<p:selectOneMenu id="beneficiary" value="#
{documentController.doc.beneficiary}" converter="#
{beneficiaryConverter}" panelStyle="width:160px" required="true" >
<f:selectItem itemLabel="Selectionner" itemValue="" />
<f:selectItems value="#{beneficiaryController.beneficiaries}"
var="beneficiary" itemLabel="#{beneficiary.intitule}" itemValue="#
{beneficiary}" />
</p:selectOneMenu>
i've tested the list out side the selectOneMenu and it's work fine.
You are using PrimeFaces and want to allow the user to select one out of very many options. As Melloware mentioned, LazyDataModel is ment for use with DataTable or other components that support pagination this way ( e.g. DataGrid)
For your use case p:autoComplete seemes to be the best way to go.
dropdown="true" makes it look like a selectOneMenu, and you can limit the number of items show using maxResults="5".
<p:autoComplete dropdown="true" maxResults="5" value="#{autoCompleteView.txt6}"
completeMethod="#{autoCompleteView.completeText}" />
You'll need to write a custom autoComplete method that finds matches for given user search input:
public List<String> completeText(String query) {
List<String> results = new ArrayList<String>();
// fill the result matching the query from user input
return results;
}
Related
I have two combo boxes. The items of the second one are retrieved using the selected value of the first one. When the default empty value is selected in the first combo box, the second combo box is not rendered.
Everything works well except for one scenario :
select a value in the first combo box -> the second combo box appears
select a value in the second combo box
select the default empty value in the first combo box -> the second combo box disappears
select the same value that was selected at step 1 in the first combo box
The second combo box should appear with the empty default value selected, but instead displays the value that was selected at step 2.
If I select a different value at step 4, the second combo box is loaded correctly, with the default empty value selected.
The view :
<ui:composition template="/pages/include/templatePrincipal.xhtml"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui" xmlns:d="http://iec.composants"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core">
<ui:define name="pageActive">
<f:view>
<h:form>
<p:panel id="panelModifierUnParametreFonctionnel"
header="LISTE DES FE FILLES ORPHELINES">
<h:panelGrid columns="6">
<p:outputLabel
value="#{feFillesOrphelinesBean.labelComboRegion}" />
<p:selectOneMenu
value="#{feFillesOrphelinesBean.regionOption}"
valueChangeListener="#{feFillesOrphelinesBean.regionChanged}"
onchange="submit()">
<f:selectItems value="#{feFillesOrphelinesBean.listRegion}" />
</p:selectOneMenu>
<p:outputLabel
value="#{feFillesOrphelinesBean.labelComboCorps}"
rendered="#{feFillesOrphelinesBean.rendreComboCorps}" />
<p:selectOneMenu
value="#{feFillesOrphelinesBean.corpsOption}"
rendered="#{feFillesOrphelinesBean.rendreComboCorps}"
valueChangeListener="#{feFillesOrphelinesBean.corpsChanged}"
onchange="submit()">
<f:selectItems value="#{feFillesOrphelinesBean.listCorps}" />
</p:selectOneMenu>
</h:panelGrid>
</p:panel>
</h:form>
</f:view>
</ui:define>
</ui:composition>
The java bean :
public class FEFillesOrphelinesBean implements Serializable {
public final static String LABEL_COMBO_REGION = "ChaƮne fonctionnelle :";
public final static String LABEL_COMBO_CORPS = "Corps :";
private String labelComboRegion;
private String labelComboCorps;
private List<SelectItem> listRegion;
private Integer regionOption;
private List<SelectItem> listCorps;
private Integer corpsOption;
private Boolean rendreComboCorps;
public String init() {
this.chargerRegions();
this.chargerCorps();
this.setLabelComboRegion(LABEL_COMBO_REGION);
this.setLabelComboCorps(LABEL_COMBO_CORPS);
return "success";
}
public void chargerRegions() {
this.setListRegion(new ArrayList<>());
this.setRegionOption(new Integer(-1));
RegionAdmin[] tabRegions = ServiceFactory.getInstance().getGestionRegionSrv().findAll();
this.getListRegion().add(new SelectItem(new Integer(-1), " "));
for (RegionAdmin region : tabRegions) {
SelectItem regionItem = new SelectItem(region.getId(), region.getLib() + ": " + region.getLibelle());
this.getListRegion().add(regionItem);
}
}
public void chargerCorps() {
this.setListCorps(new ArrayList<>());
this.setCorpsOption(new Integer(-1));
if (this.getRegionOption().equals(new Integer(-1))) {
this.setRendreComboCorps(false);
} else {
Corps[] tabCorps = ServiceFactory.getInstance().getGestionCorpsSrv().findCorps(this.getRegionOption());
this.getListCorps().add(new SelectItem(new Integer(-1), " "));
for (Corps corps : tabCorps) {
SelectItem corpsItem = new SelectItem(corps.getId(), corps.getLib() + ": " + corps.getLibelle());
this.getListCorps().add(corpsItem);
}
this.setRendreComboCorps(true);
}
}
public void regionChanged(ValueChangeEvent event) {
Integer newRegionOption = (Integer) event.getNewValue();
this.setRegionOption(newRegionOption);
this.chargerCorps();
}
public void corpsChanged(ValueChangeEvent event) {
Integer newCorpsOption = (Integer) event.getNewValue();
this.setCorpsOption(newCorpsOption);
}
public String getLabelComboRegion() {
return labelComboRegion;
}
public void setLabelComboRegion(String labelComboRegion) {
this.labelComboRegion = labelComboRegion;
}
public String getLabelComboCorps() {
return labelComboCorps;
}
public void setLabelComboCorps(String labelComboCorps) {
this.labelComboCorps = labelComboCorps;
}
public List<SelectItem> getListRegion() {
return listRegion;
}
public void setListRegion(List<SelectItem> listRegion) {
this.listRegion = listRegion;
}
public Integer getRegionOption() {
return regionOption;
}
public void setRegionOption(Integer regionOption) {
this.regionOption = regionOption;
}
public List<SelectItem> getListCorps() {
return listCorps;
}
public void setListCorps(List<SelectItem> listCorps) {
this.listCorps = listCorps;
}
public Integer getCorpsOption() {
return corpsOption;
}
public void setCorpsOption(Integer corpsOption) {
this.corpsOption = corpsOption;
}
public Boolean getRendreComboCorps() {
return rendreComboCorps;
}
public void setRendreComboCorps(Boolean rendreComboCorps) {
this.rendreComboCorps = rendreComboCorps;
}
}
As you can see, the regionChanged method is called when the selected value of the first combo box changes, then it calls the chargerCorps method which set the corpsOption to the -1 default value. This means that in the scenario that I've described, the displayed selected value is not the same as the selected value in the bean, which can cause a lot of issues.
I have a Primefaces 6.0 DataTable working with a LazyDataModel bean. After I changed to the lazy implementation, the cell edition stopped working.
The reason for that is whenever I call my onCellEdit method, and try to get the clicked row contents by calling event.getRowkey() , I get a null object.
As per Primefaces Documentation I'm have a rowKey attribute to bind the tuple with the bean value, but it doesn't seems to work.
EDIT: I can update the value now, but the dataTable doesn't reload the cell UiElement. To see the changes i have to F5 the page.
Here is my ata.xhtml DATATABLE(Sanitized)
<p:tabView id="tab" value="#{setorMB.listaSetor}" var="tabView"
activeIndex="#{ataGerencialMB.activeTabIndex}">
<p:ajax event="tabChange" listener="#{ataGerencialMB.onTabChange}"
update="tab ,formListagemCapacitacao" />
<p:tab title="#{tabView.sigla}">
<p:dataTable id="dtCapacitacao"
value="#{ataGerencialMB.lazyModelAtaGerencial}"
var="gerencial"
lazy="true"
paginator="true"
rows="#{Config.NUM_ROWS}"
currentPageReportTemplate="#{Config.CURRENT_PAGE_REPORT_TEMPLATE}"
paginatorTemplate="#{Config.PAGINATOR_TEMPLATE}"
rowsPerPageTemplate="#{Config.ROWS_PER_PAGE_TEMPLATE}"
sortBy="#{gerencial.idAta}"
sortOrder="ascending"
reflow="true"
editable="true"
editMode="cell"
rowKey="#{gerencial.idAta}">
<p:ajax event="cellEdit"
listener="#{ataGerencialMB.onCellEdit}" oncomplete="onCellEdit()"/>
<p:column>
<p:rowToggler/>
</p:column>
<p:column headerText="Tipo Assunto" >
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{gerencial.tipo}"
rendered="true" />
</f:facet>
<f:facet name="input">
<p:inputTextarea id="tipo"
value="#{gerencial.tipo}"
style="width:96%" />
</f:facet>
</p:cellEditor>
</p:column>
</p:dataTable>
</p:tab>
</p:tabView>
Class that extends the LazyDataModel AtaGerencialLazyDataModel
public class AtaGerencialLazyDataModel extends LazyDataModel<AtaGerencialBean> {
AtaGerencialBusiness ataBusiness = new AtaGerencialBusiness();
Map<String, Object> customFilters = new HashMap<String, Object>();
private List<AtaGerencialBean> listaAtaGerencialBean = new ArrayList<AtaGerencialBean>();
public AtaGerencialLazyDataModel(){
this.setRowCount(ataBusiness.getAtaGerencialTotalCount(null));
}
public AtaGerencialLazyDataModel(SetorBean setor){
customFilters.put("setor", setor);
this.setRowCount(ataBusiness.getAtaGerencialTotalCount(customFilters));
}
#Override
public List<AtaGerencialBean> load(int first, int pageSize, String sortField,
SortOrder sortOrder, Map<String, Object> filters){
List<AtaGerencialBean> list = ataBusiness.fetchLazyAtaGerencial(first, pageSize, sortField, sortOrder, customFilters);
this.setRowCount(ataBusiness.getAtaGerencialTotalCount(customFilters));
setListaAtaGerencialBean(list);
setWrappedData(list);
return list;
}
#Override
public AtaGerencialBean getRowData(String rowKey){
try{
long id = Long.parseLong(rowKey);
for (AtaGerencialBean bean : listaAtaGerencialBean) {
if (bean.getIdAta() == id){
return bean;
}
}
}catch(Exception e){
System.out.println(e.getMessage());
}
return null;
}
#Override
public Object getRowKey(AtaGerencialBean p) {
return p.getIdAta();
}
public List<AtaGerencialBean> getListaAtaGerencialBean() {
return listaAtaGerencialBean;
}
public void setListaAtaGerencialBean(
List<AtaGerencialBean> listaAtaGerencialBean) {
this.listaAtaGerencialBean = listaAtaGerencialBean;
}
}
The onCellEdit method
#ManagedBean
#ViewScoped
public class AtaGerencialMB extends MB<AtaGerencialBean,
AtaGerencialBusiness> {
private LazyDataModel<AtaGerencialBean> lazyModelAtaGerencial;
#SuppressWarnings("unused")
public void onCellEdit(CellEditEvent event) {
try{
DataTable controladorTabela = (DataTable) event.getComponent();
//rowindex is fine, it brings the index of the edited row in the
datatable (from 0 onwards)
Integer rowIndex = event.getRowIndex();
String rowKey = event.getRowKey();
//rowKey is always null
System.out.println("rowKey value:" + rowKey);
AtaGerencialBean entity = (AtaGerencialBean) controladorTabela.getRowData(event.getRowKey());
this.setRegistroDefinido(entity);
super.atualizar();
}catch(NullPointerException ex){
System.out.println(ex.getMessage());
}
}
}
EDIT
I was able to circumvent the problem by NOT using the rowKey to retrieve the data and modifying the onCellEdit method to get the data from the Datamodel inside the Datatable.
I am not sure whether it is a good/bad practice, or if that's how you're supposed to retrieve the row when using LazyLoading.
Also, following #Kukeltje suggestion, I am now using PRIMEFACES 6.2
Modified onCellEdit method
#ManagedBean
#ViewScoped
public class AtaGerencialMB extends MB<AtaGerencialBean, AtaGerencialBusiness> {
private LazyDataModel<AtaGerencialBean> lazyModelAtaGerencial;
#SuppressWarnings("unused")
public void onCellEdit(CellEditEvent event) {
try{
DataTable controladorTabela = (DataTable) event.getComponent();
DataModel dm = (DataModel) controladorTabela.getValue();
AtaGerencialBean entity = (AtaGerencialBean) dm.getRowData();
this.setRegistroDefinido(entity);
super.atualizar();
}catch(NullPointerException ex){
System.out.println(ex.getMessage());
}
}
}
I was able to circumvent the problem by NOT using the rowKey to retrieve the data and modifying the onCellEdit method to get the data from the Datamodel inside the Datatable.
I am not sure whether it is a good/bad practice, or if that's how you're supposed to retrieve the row when using LazyLoading.
Also, following #Kukeltje suggestion, I am now using PRIMEFACES 6.2
Modified onCellEdit method
#SuppressWarnings("unused")
public void onCellEdit(CellEditEvent event) {
try{
DataTable controladorTabela = (DataTable) event.getComponent();
DataModel dm = (DataModel) controladorTabela.getValue();
AtaGerencialBean entity = (AtaGerencialBean) dm.getRowData();
this.setRegistroDefinido(entity);
super.atualizar();
}catch(NullPointerException ex){
System.out.println(ex.getMessage());
}
}
https://github.com/primefaces/primefaces/issues/2688
You may refer to this issue on github. You should enable selection for your datatable
My problem is about this primefaces tag:
<p:selectManyCheckbox id="datasourceGroup" value="#{sessionBean.datasourceGroups}" converter="datasourceGroupConverter">
<f:selectItems value="#{sesionBean.getAllDatasourceGroups()}" var="group" itemLabel="#{group.toString()}" itemValue="#{group}" />
</p:selectManyCheckbox>
It does not render any visible output (checkboxes) at all. From logging output i know that the 'sessionBean.getAllDatasourceGroups()' method is not even called once during page refresh. only the 'sessionBean.getDatasourcegroups()' getter for the 'datasourceGroups' property is called once.
And i can't figure out what the problem is. I have very similar usecases of <p:selectManyMenu> and <p:selectOneMenu> on the same page and they work fine. So i have a basic understanding of how this works...or so i thought :-)
here are the other relevant parts of the code for reference:
SessionBean:
#ManagedBean
#SessionScoped
public class SessionBean implements Serializable {
private List<DatasourceGroup> datasourceGroups = new ArrayList<>();
public List<DatasourceGroup> getDatasourceGroups() {
return datasourceGroups;
}
public void setDatasourceGroups(List<DatasourceGroup> datasourceGroups) {
this.datasourceGroups = datasourceGroups;
}
public List<DatasourceGroup> getAllDatasourceGroups() {
List<DatasourceGroup> list = Arrays.asList(DatasourceGroup.values());
return list;
}
}
DatasourceGroup Enum:
public enum DatasourceGroup {
KUNDEN (Permission.ZugriffKunden),
INKASSO (Permission.ZugriffInkasso),
INTERESSENTEN (Permission.ZugriffInteressenten),
WARN (Permission.ZugriffWarnadressen);
private Permission permissionNeeded;
DatasourceGroup(Permission permission) {
this.permissionNeeded=permission;
}
public Permission getPermissionNeeded() {
return permissionNeeded;
}
}
And the DatasourceGroupConverter:
#FacesConverter("datasourceGroupConverter")
public class DatasourceGroupConverter implements Converter {
#Override
public Object getAsObject(FacesContext fc, UIComponent uic, String value) {
if (Toolbox.isNullOrEmpty(value))
return null;
try {
return DatasourceGroup.valueOf(value);
} catch (IllegalArgumentException e) {
throw new ConverterException(new FacesMessage(FacesMessage.SEVERITY_ERROR, "Conversion Error:",
"'" + value + "' is not a valid datasource group name"));
}
}
#Override
public String getAsString(FacesContext fc, UIComponent uic, Object object) {
if(object != null && object instanceof DatasourceGroup) {
return ((DatasourceGroup)object).toString();
}
return null;
}
}
I'm using primefaces 6.0 by the way.
This question already has answers here:
How to query data for Primefaces dataTable using lazy loading and pagination
(2 answers)
Closed 5 years ago.
I'm working with PrimeFaces 6.0. I'm creating a data table which uses lazy loading. I have set this.setRowCount(count) in my load method. My paginator is not shown correctly though (it only shows disabled previous, next, begin, end buttons).
When I filter my table or change the sorting, then the paginator is showing pages. Also, when I run this JavaScript, the paginator is showing pages:
PF('myTable').clearFilters();
Any ideas on how to get the paginator working without applying hacks?
This is my table (the relevant attributes):
<p:dataTable value="#{controller.lazy}"
lazy="true"
var="subitem"
rowKey="#{subitem.id}"
paginator="true" paginatorPosition="bottom"
rows="10"
sortBy="#{subitem.emailAddress}" sortOrder="ascending"
widgetVar="myTable"
>
My lazy model (relevant parts):
public class LazyDataModel<T> extends org.primefaces.model.LazyDataModel<T> {
private final QueryBuilder<T> queryBuilder;
private final Class<T> type;
public LazyDataModel(final QueryBuilder<T> queryBuilder, final Class<T> type) {
this.queryBuilder = queryBuilder;
this.type = type;
}
private void updateRowCount() {
setRowCount(queryBuilder.count().intValue());
}
#Override
public List<T> load(int first, int pageSize, List<SortMeta> multiSortMeta, Map<String, Object> filters) {
if (filters != null) {
queryBuilder.addFilters(filters);
}
if (multiSortMeta != null) {
multiSortMeta.forEach(s -> queryBuilder.orderBy(s.getSortField(), s.getSortOrder() == SortOrder.ASCENDING));
}
updateRowCount();
TypedQuery<T> typedQuery = queryBuilder.createQuery();
typedQuery.setMaxResults(pageSize);
typedQuery.setFirstResult(first);
return typedQuery.getResultList();
}
#Override
public List<T> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String, Object> filters) {
List<SortMeta> multiSortMeta = null;
if (sortField != null && sortOrder != null) {
multiSortMeta = Arrays.asList(new SortMeta(null, sortField, sortOrder, null));
}
return load(first, pageSize, multiSortMeta, filters);
}
}
With Lazy datatable you need to set the row count using LazyDataModel#setRowCount(int n) also outside the load method, i.e. during the initialization of the bean.
See also:
How to query data for Primefaces dataTable using lazy loading and pagination
i have this listView and textBox:
<table>
<tr><td>Reciver:<table><tr>
<asp:ListView ID="showRecivers" runat="server"><td><%# Eval("name")%></td> </asp:ListView>
</tr></table>
<asp:TextBox ID="reciver" runat="server" OnTextChanged="style_Recivers" AutoPostBack="true"></asp:TextBox>
</td></tr></table>
the list the listview is bound to:
public List<Reciver> recivers = new List<Reciver>();
and the function style_Recivers:
protected void style_Recivers(object sender, EventArgs e)
{
string[] separator = new string[] { "," };
string[] reciversArray = reciver.Text.ToString().Split(separator, StringSplitOptions.None);
reciversArray = reciversArray.Distinct().ToArray();
for (int i = 0; i < reciversArray.Length; i++)
{
recivers.Add(new Reciver(reciversArray[i]));
}
this.showRecivers.DataSource = recivers;
this.showRecivers.DataBind();
}
and class Reciver:
public class Reciver
{
public string name;
public Reciver(string name)
{
this.name = name;
}
public string getName()
{
return this.name;
}
public void setName(string name)
{
this.name = name;
}
}
what my idea is, that when a couple of names eneted to the textBox with a , saperator, the style_Reciver function is activated and each name is shown in the ListView right away.
but it doesnt work, it gives me the error
ASP.NET runtime error:code blocks are not supported in this context
and marks this line:
<asp:ListView ID="showRecivers" runat="server"><td><%# Eval("name")%></td> </asp:ListView>
for starter. probably more thing wont work but this is the first thing.
how can i fix it? Thanks for the help
EDIT:
it works after i added <ItemTemplate>
now it gives me a different bug:
Reciver' does not contain a property with the name 'name'
whhat is the problem now?
The List View content here should be wrapped into ItemTemplate:
<asp:ListView ID="showRecivers" runat="server">
<ItemTemplate>
<td><%# Eval("name")%></td>
</ItemTemplate>
</asp:ListView>
Update. Also there is a problem with your class declaration. Here is how it should be declared in C# conventional way:
public class Reciver
{
public string _name;
public Reciver(string name)
{
this.name = name;
}
public string name
{
get { return this._name; }
set { this._name = value; }
}
}