PrimeFaces selectOneMenu displayed value not resetting - primefaces

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.

Related

How to use LazyDataModel List in a selectOneMenu

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;
}

RowKey of DataTable is null when calling onCellEdit

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

selectCheckboxMenu primefaces return empty List

I'm trying to get selected values from a selectCheckboxMenu using PrimeFaces 5.3 and JSF 2, but always the selection list is empty.
This is the HTML part:
<p:selectCheckboxMenu id="cours" value="#{etudiantController.checkedCours}"
converter="#{coursConverter}" label="Liste cours available" multiple="true"
panelStyle="width:250px">
<f:selectItems value="#{etudiantController.coursEtudiant}" var="coursEtd"
itemLabel="#{coursEtd.libelleCours}" itemValue="#{coursEtd.idCours}" />
</p:selectCheckboxMenu>
Bean part:
private List<Cours> checkedCours;
for(Cours coursToAdd : checkedCours){
System.out.println("enter ... !!!");
coursService.addCours(coursToAdd);
}
Converter :
public class CoursConverter implements Converter {
public Object getAsObject(FacesContext context, UIComponent component, String value) {
if (value != null && !value.isEmpty()) {
return component.getAttributes().get(value);
}
return null;
}
public String getAsString(FacesContext context, UIComponent component, Object value) {
if (value == null) {
return "";
}
if (value instanceof Cours) {
Cours cours = (Cours) value;
String name = cours.getLibelleCours();
return name;
} else {
throw new ConverterException(new FacesMessage(value + " est un Cours non valide"));
}
} }
The problem here is that it never enter in the block.
Any help?
Thank you.
Try setting an Id to your converter and calling it using that id
#FacesConverter("coursConverter")
public class CoursConverter implements Converter {
...
}
--
<p:selectCheckboxMenu id="cours" value="#{etudiantController.checkedCours}"
converter="coursConverter" label="Liste cours available" multiple="true"
panelStyle="width:250px">
<f:selectItems value="#{etudiantController.coursEtudiant}" var="coursEtd"
itemLabel="#{coursEtd.libelleCours}" itemValue="#{coursEtd.idCours}" />

Primefaces: Cloning of Diagram Element does not work properly

i want to add multiple elements on an existing diagram in primefaces but it overwrites the created one all the time. It creates the first one and after that it keeps overwriting whenever i drop a new element on the diagram.
I'm using the panel via drag'n drop to add new element to the diagram.
See below my code (diagram.xhtml):
<h:form id="elementForm">
<p:panel id="epnl" header="Draggable Panel">
<h:outputText value="New Workflow Task" />
</p:panel>
<p:draggable for="epnl" helper="clone" />
<p:outputPanel id="selectedElements" style="height:600px">
<p:diagram id="diagramV" value="#{diagramFlowChartView.model}"
style="height:600px" styleClass="ui-widget-content" />
</p:outputPanel>
<p:droppable for="diagramV" widgetVar="dropWV">
<p:ajax listener="#{diagramFlowChartView.onElementDrop}"
update="elementForm, selectedElements, diagramV" />
</p:droppable>
</h:form>
<script type="text/javascript">
//<![CDATA[
PrimeFaces.widget.Droppable.prototype.bindDropListener = function() {
var _self = this;
this.cfg.drop = function(event, ui) {
if (_self.cfg.onDrop) {
_self.cfg.onDrop.call(_self, event, ui);
}
if (_self.cfg.behaviors) {
var dropBehavior = _self.cfg.behaviors['drop'];
if (dropBehavior) {
var ext = {
params : [ {
name : _self.id + '_dragId',
value : ui.draggable.attr('id')
}, {
name : _self.id + '_dropId',
value : _self.cfg.target
}, {
name : ui.draggable.attr('id') + '_left',
value : ui.position.left
}, {
name : ui.draggable.attr('id') + '_top',
value : ui.position.top
} ]
};
console.log(ui);
dropBehavior.call(_self, ext);
}
}
};
}
// ]]>
</script>
The related Bean (FormChartView.java):
#ManagedBean(name = "diagramFlowChartView")
#RequestScoped
public class FlowChartView {
private DefaultDiagramModel model;
private Element elm = new Element("", "25em", "10em");
private List<Element> elements = new ArrayList<Element>();
public void onElementDrop(DragDropEvent ddEvent) {
String dargId = ddEvent.getDropId();
System.out.println("dargId = " + dargId);
Map<String, String> params = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();
String left = params.get(dargId + "_left");
String top = params.get(dargId + "_top");
elment = new Element("Test", left, top);
elment.setId(UUID.randomUUID().toString());
System.out.println("elm.id = " + elm.getId());
model.addElement(elm);
}
#PostConstruct
public void init() {
model = new DefaultDiagramModel();
elm = new Element("", "25em", "10em");
model.setMaxConnections(-1);
FlowChartConnector connector = new FlowChartConnector();
connector.setPaintStyle("{strokeStyle:'#C7B097',lineWidth:3}");
model.setDefaultConnector(connector);
Element start = new Element("Fight for your dream", "20em", "6em");
start.addEndPoint(new BlankEndPoint(EndPointAnchor.BOTTOM));
start.addEndPoint(new BlankEndPoint(EndPointAnchor.LEFT));
start.setDraggable(true);
start.setStyleClass("background-color: #98AFC7");
Element trouble = new Element("Do you meet some trouble?", "20em", "18em");
trouble.addEndPoint(new BlankEndPoint(EndPointAnchor.TOP));
trouble.addEndPoint(new BlankEndPoint(EndPointAnchor.BOTTOM));
trouble.addEndPoint(new BlankEndPoint(EndPointAnchor.RIGHT));
trouble.setDraggable(true);
Element giveup = new Element("Do you give up?", "20em", "30em");
giveup.addEndPoint(new BlankEndPoint(EndPointAnchor.TOP));
giveup.addEndPoint(new BlankEndPoint(EndPointAnchor.LEFT));
giveup.addEndPoint(new BlankEndPoint(EndPointAnchor.RIGHT));
Element succeed = new Element("Succeed", "50em", "18em");
succeed.addEndPoint(new BlankEndPoint(EndPointAnchor.LEFT));
succeed.setStyleClass("ui-diagram-success");
Element fail = new Element("Fail", "50em", "30em");
fail.addEndPoint(new BlankEndPoint(EndPointAnchor.LEFT));
fail.setStyleClass("ui-diagram-fail");
model.addElement(start);
model.addElement(trouble);
model.addElement(giveup);
model.addElement(succeed);
model.addElement(fail);
elements.add(start);
elements.add(trouble);
elements.add(giveup);
elements.add(succeed);
elements.add(fail);
model.connect(createConnection(start.getEndPoints().get(0), trouble.getEndPoints().get(0), null));
model.connect(createConnection(trouble.getEndPoints().get(1), giveup.getEndPoints().get(0), "Yes"));
model.connect(createConnection(giveup.getEndPoints().get(1), start.getEndPoints().get(1), "No"));
model.connect(createConnection(trouble.getEndPoints().get(2), succeed.getEndPoints().get(0), "No"));
model.connect(createConnection(giveup.getEndPoints().get(2), fail.getEndPoints().get(0), "Yes"));
}
public DefaultDiagramModel getModel() {
return model;
}
public void setModel(DefaultDiagramModel model) {
this.model = model;
}
public Element getElment() {
return elment;
}
public void setElment(Element elment) {
this.elment = elment;
}
public List<Element> getElements() {
return elements;
}
public void setElements(List<Element> elements) {
this.elements = elements;
}
private Connection createConnection(EndPoint from, EndPoint to, String label) {
Connection conn = new Connection(from, to);
conn.getOverlays().add(new ArrowOverlay(20, 20, 1, 1));
if(label != null) {
conn.getOverlays().add(new LabelOverlay(label, "flow-label", 0.5));
}
return conn;
}
}
My fault.
This is caused by the element list to be reinitialized each time an (ajax)request was made. Which in turn was caused by the bean scope being #RequestScoped
Changing #RequestScoped to #ViewScoped solved the issue.

Validation error value is not valid: primefaces [duplicate]

This question already has answers here:
Validation Error: Value is not valid
(3 answers)
Closed 6 years ago.
Please help me to find the solution.
this is the xhtml code:
<p:selectOneMenu value="#{activteBean.act.activiteFamille}"
converter="familleAct"
var="f" required="Une famille est obligatoire" >
<f:selectItems value="#{activteBean.actFamList}" var="famille" itemLabel="# {famille.dsgFam}" itemValue="#{famille}"/>
<p:column>#{f.refFam}</p:column>
<p:column>#{f.dsgFam}</p:column>
</p:selectOneMenu>
here is my converter:
#FacesConverter(forClass=ActiviteFamille.class,value="familleAct" )
public class ActiviteFamilleConverter implements Converter {
#Override
public Object getAsObject(FacesContext arg0, UIComponent arg1, String code) {
if (code.trim().equals("")) {
return null;
} else {
ActiviteFamilleDao actFamDao = new ActiviteFamilleDao();
List<ActiviteFamille> actFamList = actFamDao.findAll();
for (ActiviteFamille af : actFamList) {
if (af.getRefFam().equals(code)) {
return af;
}
}
}
return null;
}
#Override
public String getAsString(FacesContext arg0, UIComponent arg1, Object value) {
if (value == null || value.equals("")) {
return "";
} else {
return String.valueOf(((ActiviteFamille) value).getRefFam());
}
}
}
The managed bean:
#ManagedBean(name = "activteBean")
#ViewScoped
public class ActivteBean implements Serializable {
private Activite act = new Activite();
private ActiviteDao actDao = new ActiviteDao();
private List<Activite> actList;
private boolean init;
private ActiviteFamilleDao actFamDao = new ActiviteFamilleDao();
private List<ActiviteFamille> actFamList;
public boolean isInit() {
act = new Activite();
actList = actDao.findAll();
actFamList=actFamDao.findAll();
return init;
}
....
}
and thank you for your help.
This can happen if the equals() method for ActiveFamille is not implemented properly.
The error message indicates that the selected (and converted) value does not match any of the elements in your list activteBean.actFamList.
Try to debug and set a break point into the equals() method of ActiveFamille and try to find out why it does not match.