collapse or expand p:accordionPanel programmatically - primefaces

What I am trying to achieve is?
After Load Button Clicked, If any one of the textfield is set, So in result the "accordion panel" filter should expand.
After Load Button Clicked, If all text fields are not set, So in result the "accordion panel" filter should collapse.
I have gone through accordion panel primefaces documentation but could not found it helpful.
http://www.primefaces.org/docs/vdl/3.5/primefaces-p/accordionPanel.html
I have gone through previously asked question on stackoverflow, the answer to this question also could not satisfy me to achieve my required result.
Expanding Accordion Panel in PrimeFaces with a RadioButton click
ManagedBean
package com.pk.test;
import javax.faces.bean.ManagedBean;
#ManagedBean(name="testBean")
public class AccordionTestBean {
private String name;
private String semester;
private String age;
private Boolean checkNameTextField = false;
public void save(){
System.out.println("Close Filter If any one field of form is set");
System.out.println("Name: "+getName());
System.out.println("Age: "+getAge());
System.out.println("Semester: "+getSemester());
if(getName()!= null){
setCheckNameTextField(true);
//if name textfield is set to a value, on save click filter will not collapse or close
}
else
setCheckNameTextField(false);
//if name textfield is set to a value, on save click filter will collapse
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSemester() {
return semester;
}
public void setSemester(String semester) {
this.semester = semester;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public Boolean getCheckNameTextField() {
return checkNameTextField;
}
public void setCheckNameTextField(Boolean checkNameTextField) {
this.checkNameTextField = checkNameTextField;
}
}
FrontEnd File
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:p="http://primefaces.org/ui">
<h:head>
</h:head>
<body>
<h:form id="formId">
<p:accordionPanel id="accordion" cache="false" activeIndex="-1"
style="margin-bottom:20px;width:330px;" widgetVar="acc">
<p:ajax event="tabClose" listener="#{testBean.checkNameTextField}" />
<p:tab title="Filter:"
titleStyle="width:330px;background-color:#DAEDF4">
<h:panelGrid columns="2">
<h:outputLabel value="Name" />
<h:inputText value="#{testBean.name}" />
<h:outputLabel value="Age" />
<h:inputText value="#{testBean.age}" />
<h:outputLabel value="Semester" />
<h:inputText value="#{testBean.semester}" />
</h:panelGrid>
<p:commandButton icon="ui-icon-save" value="Save"
action="#{testBean.save}"
onclick="PF('formId:accordion').hide();" />
</p:tab>
</p:accordionPanel>
</h:form>
</body>
</html>

I did'n understand what you are trying to do, but to expand/colapse an accordion panel you can use this
expand: PF('accordian-widgetVar').select(index)
collapse: PF('accordian-widgetVar').unselect(index)
where accordian-widgetVar is the value of the property widgetVar of your accordionPanel and index is the index of the tab that you want to expand/collapse
also you can execute that from a bean like this
RequestContext.getCurrentInstance().execute("PF('accordian-widgetVar').unselect(index)");

Related

Primefaces initial sort order for multisort dataTable in tabView

I have a page (page1.xhtml) with a tabView and a dataTable within one of the tabs. The dataTableuses lazy loading and should provide multisort mode.
Therefore I use a List<SortMeta> for the sortBy attribute of dataTable as found here (Initial sortorder for PrimeFaces datatable with multisort).
The List<SortMeta> is created in getPreSortOrder() but findComponent() for clientId "myForm:tabs:data:colName" always returns null!
In another constellation (page2.xhtml) where I have the dataTable not in a tabView findComponent() always returns the correct column component!
So the problem seems to be the combination with tabView?!
Any hints welcome - Thank you!
page.xhtml:
<html>
<f:metadata>
<f:viewAction action="#{model.loadData}"/>
</f:metadata>
<ui:composition template="/WEB-INF/template.xhtml">
<ui:define name="content">
<h:form id="myForm">
<p:panelGrid>...</p:panelGrid>
<p:tabView id="tabs">
<p:tab id="tab1">...</p:tab>
<p:tab id="tab2">...</p:tab>
<p:tab id="tab3">
<p:dataTable id="data" lazy="true"
value="#{model.personTableModel}" var="item"
sortMode="multiple" sortBy="#{model.tableMode.preSortOrder}">
<p:column id="colName" sortBy="#{item.name}"> // <-- findComponent for "myForm:tabs:data:colName" always returns null !!!
<h:outputText value="#{item.name}"/>
</p:column>
<p:column id="colAddress" sortBy="#{item.address}">
<h:outputText value="#{item.address}"/>
</p:column>
</p:dataTable>
</p:tab>
</p:tabView>
</h:form>
</ui:define>
</ui:composition>
</html>
page2.xhtml:
<html>
<f:metadata>
<f:viewAction action="#{model.loadData}"/>
</f:metadata>
<ui:composition template="/WEB-INF/template.xhtml">
<ui:define name="content">
<h:form id="myForm">
<p:panelGrid>...</p:panelGrid>
<p:outputPanel id="tables">
<p:fieldset>
<p:dataTable id="data" lazy="true"
value="#{model.personTableModel}" var="item"
sortMode="multiple" sortBy="#{model.tableMode.preSortOrder}">
<p:column id="colName" sortBy="#{item.name}"> // <-- findComponent for "myForm:data:colName" always component
<h:outputText value="#{item.name}"/>
</p:column>
<p:column id="colAddress" sortBy="#{item.address}">
<h:outputText value="#{item.address}"/>
</p:column>
</p:dataTable>
<p:fieldset>
</p:outputPanel>
</h:form>
</ui:define>
</ui:composition>
</html>
Model.java:
#Named // javax.inject.Named
#ViewScoped // javax.faces.view.ViewScoped
public class Model implements Serializable {
private static final String COL_NAME_CLIENT_ID = "myForm:tabs:data:colName";
#Inject PersonTableDataModel personTableDataModel; // with getter & setter
public void loadData() {
List<SortMeta> preSortOrder = getPreSortOrder(COL_NAME_CLIENT_ID, "name", SortOrder.ASCENDING);
personTableDataModel.setPreSortOrder(preSortOrder);
}
private List<SortMeta> getPreSortOrder(String columnId, String sortField, SortOrder sortOrder) {
UIViewRoot viewRoot = FacesContext.getCurrentInstance().getViewRoot();
UIComponent column = viewRoot.findComponent(columnId); // <-- ALWAYS RETURNS NULL
if (Objects.isNull(column)) {
return Collections.emptyList();
}
List<SortMeta> preSortOrder = new ArrayList<>();
SortMeta sm = new SortMeta();
sm.setSortBy((UIColumn) column);
sm.setSortField(sortField);
sm.setSortOrder(sortOrder);
preSortOrder.add(sm);
return preSortOrder;
}
}
PersonTableDataModel.java:
public class PersonTableDataModel extends TableModel<Person> {
}
TableModel.java:
public class TableModel<T> extends LazyDataModel<T> {
private List<SortMeta> preSortOrder; // with getter & setter
}
I am using Primefaces 6.1 on Wildfly 10.0.0.Final
EDIT:
I added a TabChange event listener changeTab() and traversed the UIComponents and at the end the correct clientId is written to the output?!
Model.java:
public void changeTab(TabChangeEvent event) {
TabView tabView = (TabView) event.getComponent();
logger.entry(tabView.getActiveIndex());
Tab tabProzesse = tabView.findTab("myForm:tabs:tab3");
if (Objects.nonNull(tabProzesse)) {
List<UIComponent> childs = tabProzesse.getChildren();
Optional<UIComponent> c = childs.stream().filter(child -> child.getClientId().equals("myForm:tabs:data")).findFirst();
if (c.isPresent() && c.get() instanceof DataTable) {
DataTable t = (DataTable) c.get();
Optional<UIColumn> optColName = t.getColumns().stream().filter(col -> col.getClientId().contains("colName")).findFirst();
optColName.ifPresent(colName -> {
logger.debugf("colName.clientId=%s", colName.getClientId()); // <-- output colName.clientId=myForm:tabs:data:colName
});
}
}
}
I fixed it by this work-around:
added tabChange event listener to tabView and update datatable data
added binding to initial sort column with id colName
set preSortOrder for tableModel in onTabChange listener
page.xhtml:
<p:tabView id="tabs">
<p:ajax event="tabChange" listener="#{model.onTabChange}" update="data"/>
<p:tab id="tab1">...</p:tab>
<p:tab id="tab2">...</p:tab>
<p:tab id="tab3">
<p:dataTable id="data" lazy="true"
value="#{model.personTableModel}" var="item"
sortMode="multiple"
sortBy="#{model.personTableModel.preSortOrder}">
<p:column id="colName" sortBy="#{item.name}" binding="#{mode.colName}">
</p:column>
</p:dataTable>
</p:tab>
</p:tabView>
Model.java:
private UIComponent colName;
public UIComponent getColName() {
return colName;
}
public void setColName(UIComponent colNameProzess) {
this.colName = colName;
}
public void onTabChange(TabChangeEvent event) {
TabView tabView = (TabView) event.getComponent();
UIComponent uiComponent = findComponent(tabView, colName.getId());
if (Objects.nonNull(uiComponent) && uiComponent instanceof org.primefaces.component.api.UIColumn) {
List<SortMeta> preSortOrder = getPreSortOrder(uiComponent, "name", SortOrder.ASCENDING);
personTableDataModel.setPreSortOrder(preSortOrder);
}
}
private List<SortMeta> getPreSortOrder(UIColumn column, String sortField, SortOrder sortOrder) {
List<SortMeta> preSortOrder = new ArrayList<>();
SortMeta sm = new SortMeta();
sm.setSortBy(column);
sm.setSortField(sortField);
sm.setSortOrder(sortOrder);
preSortOrder.add(sm);
return preSortOrder;
}
private UIComponent findComponent(UIComponent uiComponent, String id) {
FacesContext context = FacesContext.getCurrentInstance();
UIComponent base = Objects.nonNull(uiComponent) ? uiComponent : context.getViewRoot();
final UIComponent[] found = new UIComponent[1];
base.visitTree(VisitContext.createVisitContext(context), (context1, component) -> {
if (component.getId().equals(id)) {
found[0] = component;
return VisitResult.COMPLETE;
}
return VisitResult.ACCEPT;
});
return found[0];
}

Primefaces p:ajax and remoteCommand does not update growl messages

In the following example, I modify a datatable using p:ajax then use remoteCommand to update the table. That works. However, I would also like to update growl msgs in the event of an error or success. That doesn't work.
I see from the examples if a button calls an action, then calls remoteCommand, the growl msgs update. However, that won't give me what I need from the ajax cellEdit in a datatable.
How can I update the growl messages from a p:ajax command.
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui"
>
<h:head/>
<h:form id="formId">
<p:growl id="msgs" showDetail="true" />
<h:body>
<h:panelGrid>
<!-- Updates wordsId table but not msgs -->
<p:remoteCommand name="onCellEditRemote" update="wordsId msgs"/>
<p:dataTable id="wordsId" var="word" value="#{remoteMessageBean.words}" editable="true" editMode="cell">
<!-- does not update msgs -->
<p:ajax event="cellEdit" listener="#{remoteMessageBean.modifyWordOnCellEdit}" oncomplete="onCellEditRemote()" update="formId:msgs"/>
<p:column headerText="Modify" >
<p:outputLabel value="#{word}" />
</p:column>
<p:column headerText="Modify" >
<p:cellEditor>
<f:facet name="output"><h:outputText value=""/></f:facet>
<f:facet name="input">
<p:inputText id="modelInput" value="#{remoteMessageBean.modifyWord}"/>
</f:facet>
</p:cellEditor>
</p:column>
</p:dataTable>
</h:panelGrid>
<p:remoteCommand name="rc" update="msgs" />
<p:commandButton type="button" action="#{remoteMessageBean.buttonAction}" value="Doesnt Work" icon="ui-icon-refresh" update="msgs" />
<p:remoteCommand name="rc2" update="msgs" action="#{remoteMessageBean.buttonAction}" />
<p:commandButton type="button" onclick="rc2()" value="Works" icon="ui-icon-refresh" />
</h:body>
</h:form>
</html>
#ManagedBean
#SessionScoped
public class RemoteMessageBean {
private static Logger logger = Logger.getLogger(RemoteMessageBean.class);
private String modifyWord;
private List<String> words;
public RemoteMessageBean() {
words = new ArrayList<>();
words.add("word1");
words.add("word2");
words.add("word3");
}
public void modifyWordOnCellEdit(CellEditEvent event) {
logger.debug(event);
getWords().add(getModifyWord());
logger.debug("");
FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_ERROR, "adding " + getModifyWord(), null);
FacesContext.getCurrentInstance().addMessage(null, msg);
setModifyWord(null);
}
public void buttonAction() {
logger.debug("");
FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_ERROR, "buttonAction", null);
FacesContext.getCurrentInstance().addMessage(null, msg);
}
public String getModifyWord() {
return modifyWord;
}
public void setModifyWord(String modifyWord) {
this.modifyWord = modifyWord;
}
public List<String> getWords() {
return words;
}
}
I worked around the problem by creating and saving message in modifyWordOnCellEdit then calling displayMessageAction from remoteCommand to display it. Not exactly what I was hoping for but it works.
Jsf Page
<p:remoteCommand name="onCellEditRemote" update="wordsId" action="#{gameBean.displayMessageAction}"/>
Controller
public void displayMessageAction() {
if (getMessage() != null) {
FacesContext.getCurrentInstance().addMessage("growl", getMessage());
setMessage(null);
}
}
public void modifyWordOnCellEdit(CellEditEvent event) {
...
FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_ERROR, exception.getMessage(), null);
setMessage(msg);
}
Its will work add partialsubmit in p:ajax

PrimeFaces GMap control doesn't work when I migrate from 3.4 to 5.0

I have a great problem.
I have a project wrote in PrimeFaces 3.4 with JSF 2.1 and JAVA6. I'm implementing the porting from PF 3.4 to PF 5.0
but with PF 5.0 the component GMap doesn't work at all! When I load the page, GMap isn't rendered and it appears totally white.
Firebug says : Google is not defined ...
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<f:view
xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui"
contentType="text/html">
<h:head>
<script src="https://maps.google.com/maps/api/js?sensor=false" type="text/javascript"></script>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel="stylesheet" type="text/css" href="#{request.contextPath}/css/garantesStyles.css" />
<title>My App title</title>
</h:head>
<h:body >
<p:ajaxStatus onstart="PF('statusDialog').show();" onsuccess="PF('statusDialog').hide();"/>
<p:dialog modal="true" widgetVar="statusDialog" header="Attendere..."
draggable="false" closable="false">
<p:graphicImage value="/images/ajaxloadingbar.gif" />
</p:dialog>
<h:form id="formOggettoMappa">
<p:gmap widgetVar="oggettoMappa" id="oggettoMappa" center="#{mapUrbanBean.centerMap}"
zoom="#{mapUrbanBean.zoomFactor}" type="hybrid"
style="width:100%;height:600px" model="#{mapUrbanBean.puntiModel}" >
<p:ajax event="overlaySelect" listener="#{mapUrbanBean.onMarkerSelect}" />
</p:gmap>
</h:form>
This is the code about my bean
#ManagedBean(name="mapUrbanBean")
#SessionScoped
public class MapBean implements Serializable {
private static final long serialVersionUID = 1L;
private MapModel puntiModel;
private double centerX,centerY,zoomFactor;
private String centerMap;
public MapModel getPuntiModel() {
return puntiModel;
}
public void setPuntiModel(MapModel puntiModel) {
this.puntiModel = puntiModel;
}
public String getCenterMap() {
return centerMap;
}
public void setCenterMap(String centerMap) {
this.centerMap = centerMap;
}
public double getCenterX() {
return centerX;
}
public void setCenterX(double centerX) {
this.centerX = centerX;
}
public double getCenterY() {
return centerY;
}
public void setCenterY(double centerY) {
this.centerY = centerY;
}
public int getZoomFactor() {
return zoomFactor;
}
public void setZoomFactor(int zoomFactor) {
this.zoomFactor = zoomFactor;
}
#PostConstruct
public void init(){
this.data = new Date();
this.data2 = new Date();
popolaUltimiMappa();
}
public void popolaUltimiMappa(){
puntiModel= new DefaultMapModel();
LatLng coord = new LatLng(36.890257,30.707417);
puntiModel.addOverlay(new Marker(coord, "this marker","images/mapimg/"+img_a.get(i)));
this.centerX=36.890257;
this.centerY=30.707417;
this.zoomFactor=13;
this.centerMap= this.centerY+ "," +this.centerX;
}
}
This code works fine with PrimeFaces 3.4 but with PrimeFaces 5.0 it doesn't work.
I tried with Google but I found nothing.
Any idea????
Thank you in advance
EDIT: I saw that GMap control works (showing some layers) but any controls are disabled! I can't do anything, any pan movements, any zoom in or zoom out operations...
yes, same issue with me. but if you use ordinary javascript of google maps it will work, I think it will only work primefaces 5 on web application locally not on google app engine.

Primefaces contextmenu refresh when click on row of treetable

the situation is the following: I've got a treeTable with 3 different type of objects. The table contains the p:ajax with event="select". I wrote 3 different contextMenus, one for each type... and all works well.
My problem is that I want to enable/disable some of the menuItems; to do that I use the attribute "rendered" with condition based on properties of selected node.
All works, but only the second time I right-click on the same object (the first time the contextMenu isn't filtered).
Here is the code... (I'm including only one type of object for semplicity)
treeTable page:
<h:form id="form" prependId="false">
<p:treeTable value="#{documentsController.root}" var="document" id="docs"
selectionMode="single" selection="#{documentsController.selectedNode}">
<p:ajax event="select" process="#this" update=":form:menus"/>
<p:column headerText="#{msg['name']}">
<h:outputText value="#{document.name}" />
</p:column>
</p:treeTable>
<h:panelGroup id="menus">
<ui:include src="/menu/document_menu.xhtml"/>
</h:panelGroup>
<p:dialog id="document-rename-dialog" widgetVar="documentRenameDialog" header="#{msg.rename}">
<h:panelGrid id="doc-rename" columns="2">
<h:outputLabel for="name" value="#{msg.name}:" />
<h:inputText id="name" value="#{documentsController.name}"/>
</h:panelGrid>
<div class="spacer-10" />
<h:panelGroup layout="block">
<p:commandLink onclick="documentRenameDialog.hide();" value="#{msg.cancel}"/>
<p:commandLink actionListener="#{documentsController.renameDocument(documentsController.selectedNode.data)}"
process="#this :form:document-rename-dialog:doc-rename"
update=":form:docs"
oncomplete="documentRenameDialog.hide();"
value="#{msg.check}">
</h:panelGroup>
</common:dialog>
</h:form>
document_menu page:
<p:contextMenu id="contextMenuDocument" for="docs" nodeType="document">
<p:menuitem value="#{msg.rename}" process="#this docs" update=":form:document-rename-dialog:doc-rename"
actionListener="#{documentsController.setName(documentsController.selectedNode.data.name)}"
rendered="#{documentsController.canWrite}"
icon="ui-icon-pencil" oncomplete="documentRenameDialog.show();"/>
</p:contextMenu>
DocumentsController class:
#ManagedBean
#ViewScoped
public class DocumentsController {
private TreeNode root;
private TreeNode selectedNode;
private String name;
public TreeNode getSelectedNode() {
return selectedNode;
}
public void setSelectedNode(TreeNode selectedNode) {
this.selectedNode = selectedNode;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void renameDocument(ArterDocument selectedDocument) {
if(name != null && !name.equals("")) {
System.out.println("Document renamed in: "+name);
((MyDocument)selectedNode.getData()).setName(name);
}
else
addErrorMessage("Error renaming document.");
}
public static boolean canWrite() {
if(((MyDocument)selectedNode.getData()).isWriteable())
return true;
return false;
}
}
The MyDocument class is a simple class with a String (name) and a boolean (writeable).
Can anyone tell me how I can show filtered contextMenu at first shot?
Thank you!

primefaces p:gmap in composite component, the OverlaySelectEvent is null

Environment:
1, glassfish 3.1
2, primefaces 3.0.1
Requirement:
1, Develop a composite component named "corpInfoMap", which shows the locations of corporations in google map as "markers". when user click a marker, display the corporation's infomation in mapInfoWindow.
2, Develop an other composite component named "corpInfoMapDialog", which is a p:dialog contains the "corpInfoMap".
Problem:
The Map works excellent, both in page or in dialog. but when user click the marker in map:
The "OverlaySelectEvent"(event) which is passed into the listener method is NULL. So "event.getgetOverlay()" throws NullPonterException.
Code:
1 corpInfoMap.xhtml
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html
xmlns="http://www.w3.org/1999/xhtml"
xmlns:cc="http://java.sun.com/jsf/composite"
xmlns:p="http://primefaces.org/ui"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:f="http://java.sun.com/jsf/core"
>
<cc:interface displayName="单位地理信息">
<cc:attribute name="mapModel" required="true" displayName="地理信息Model,com.ui.fwjg.viewModel.CorporationMapModel类型" />
<cc:attribute name="selectedListener" required="true" method-signature="void method(org.primefaces.event.map.OverlaySelectEvent)" displayName="选择锚点的方法" />
</cc:interface>
<cc:implementation>
<f:view contentType="text/html">
<p:gmap zoom="#{cc.attrs.mapModel.zoom}"
type="HYBRID"
center="#{cc.attrs.mapModel.centerWd},#{cc.attrs.mapModel.centerJd}"
style="width:#{cc.attrs.mapModel.width}px;height:#{cc.attrs.mapModel.height}px;"
model="#{cc.attrs.mapModel.model}"
>
<p:ajax event="overlaySelect" listener="#{cc.attrs.selectedListener}"></p:ajax>
<p:gmapInfoWindow rendered="#{cc.attrs.mapModel.selectedMarker != null}" maxWidth="#{cc.attrs.mapModel.width / 2}">
<p:outputPanel style="text-align:center;display:block;margin:auto:" rendered="#{cc.attrs.mapModel.selectedMarker != null}">
<h:panelGroup style="width:100%;font-size:1.5em;line-height:2em;font-weight:bold;text-align:center;">
#{cc.attrs.mapModel.selectedMarker.data.dwmc}
</h:panelGroup>
<h:panelGroup layout="block" styleClass="com-ui-clearboth"></h:panelGroup>
<h:graphicImage rendered="#{not empty cc.attrs.mapModel.selectedMarker.data.dwsltFile}"
style="max-width:#{cc.attrs.mapModel.width / 2};display:block;margin:20px auto;"
url="/file.ui?f=#{cc.attrs.mapModel.selectedMarker.data.dwsltFile}"></h:graphicImage>
<h:outputText value="#{mapBean.marker.title}" />
<h:panelGroup layout="block" styleClass="com-ui-clearboth"></h:panelGroup>
<h:outputText rendered="#{not empty cc.attrs.mapModel.selectedMarker.dwjj}"
value="<p style="font-size:1em;line-height:1.5em;text-indent:2em;">"
escape="false"></h:outputText>
<h:outputText rendered="#{not empty cc.attrs.mapModel.selectedMarker.dwjj}" value="#{cc.attrs.mapModel.selectedMarker.dwjj}">
</h:outputText>
<h:outputText rendered="#{not empty cc.attrs.mapModel.selectedMarker.dwjj}" value="</p>" escape="false"></h:outputText>
</p:outputPanel>
</p:gmapInfoWindow>
</p:gmap>
</f:view>
</cc:implementation>
2 corpInfoMapDialog.xhtml
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html
xmlns="http://www.w3.org/1999/xhtml"
xmlns:cc="http://java.sun.com/jsf/composite"
xmlns:p="http://primefaces.org/ui"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:comuicommon="http://java.sun.com/jsf/composite/components/ui/common">
<!-- INTERFACE -->
<cc:interface displayName="单位地理信息窗口">
<cc:attribute name="mapModel" required="true" displayName="地理信息Model,com.ui.fwjg.viewModel.CorporationMapModel类型" />
<cc:attribute name="selectedListener" required="true" method-signature="void method(javax.faces.component.behavior.AjaxBehavior)" displayName="选择锚点的方法" />
<cc:attribute name="dialogId" default="corpInfoMapDialog" displayName="对话框的ID" />
</cc:interface>
<cc:implementation>
<p:dialog header="单位地理信息" widgetVar="#{cc.attrs.dialogId}" id="#{cc.attrs.dialogId}" width="#{cc.attrs.mapModel.width}">
<h:panelGroup rendered="#{cc.attrs.mapModel != null and cc.attrs.mapModel.model != null and (not empty cc.attrs.mapModel.model.markers)}" layout="block">
<comuicommon:corpInfoMap mapModel="#{cc.attrs.mapModel}" selectedListener="#{cc.attrs.selectedListener}"/>
</h:panelGroup>
<h:panelGroup rendered="#{not (cc.attrs.mapModel != null and cc.attrs.mapModel.model != null and (not empty cc.attrs.mapModel.model.markers))}"
layout="block" style="font-size:2em;text-align:center;">
该单位无地理信息。
</h:panelGroup>
</p:dialog>
</cc:implementation>
</html>
3 The Backing Beans(One of them):
#ManagedBean
#ViewScoped
public class JlltWssbDjjsbEditPage implements Serializable{
... // a lot of lines
private CorporationMapModel corporationMapModel;
#PostConstruct
public void init() {
corporationMapModel = new CorporationMapModel();
... // other codes, have no business with corporationMapModel.
}
// the OverlaySelectEvent listener method
// when user click the marker in map, this method is invoked, but the parameter "evnet" is null.
public void setSelectedMarker(OverlaySelectEvent event){
corporationMapModel.onMarkerSelect(event);
}
public CorporationMapModel getCorporationMapModel() {
return corporationMapModel;
}
public void setCorporationMapModel(CorporationMapModel corporationMapModel) {
this.corporationMapModel = corporationMapModel;
}
// reset the jsb, reset the corporationMapModel's properties(only it's properties, neither it nor the mapModel in it.)
public void setJsb(JlltWssbDjjsb jsb) {
this.jsb = jsb;
Corporation corporation = jsb == null ? null : (jsb.getWineInfo() == null ? null : jsb.getWineInfo().getCorporation());
corporationMapModel.resetModel(corporation);
setShowHistory(jsb != null);
initWineInfo();
}
... // a lot of lines, have no business with
}
4 CorporationMapModel.java
public class CorporationMapModel implements Serializable{
private List<Corporation> corporations; // 企业列表 corporation list
private MapModel model; // 地理信息Model primefaces map model
private String centerJd; // 地图中间位置-经度 lng
private String centerWd; // 地图中间位置-维度 lat
private String zoom; // 地图缩放级别 gmap zoom
private Marker selectedMarker; // 被选择的Marker selected marker(overlay)
private int width = 600; // the width(px) of the map
private int height = 480; // the height(px) of the map
public void resetModel(Corporation corporation) {
List<Corporation> corporations = new ArrayList<Corporation>();
if(corporation != null){
corporations.add(corporation);
}
setCorporations(corporations);
}
public void resetModel(List<Corporation> corporations) {
corporations = corporations == null ? new ArrayList<Corporation>() : corporations;
setCorporations(corporations);
}
private void calInfosByCorporations() {
if(model == null)
model = new DefaultMapModel();
model.getMarkers().clear();
if (corporations != null && corporations.size() > 0) {
for (Corporation corporation : corporations) {
CorporationMapInfo mapInfo = CorporationMapInfo.generateNewCorporationMapInfo(corporation);
if (mapInfo != null) {
model.addOverlay(mapInfo);
}
}
List<Marker> markers = model.getMarkers();
if (markers != null && markers.size() > 0) {
double maxWd = 0D;
double minWd = 0D;
double maxJd = 0D;
double minJd = 0D;
for (int i = 0; i < markers.size(); i++) {
Marker marker = markers.get(i);
if (i == 0) {
maxWd = marker.getLatlng().getLat();
minWd = marker.getLatlng().getLat();
maxJd = marker.getLatlng().getLng();
minJd = marker.getLatlng().getLng();
} else {
double wd = marker.getLatlng().getLat();
double jd = marker.getLatlng().getLng();
maxWd = maxWd < wd ? wd : maxWd;
maxJd = maxJd < jd ? jd : maxJd;
minWd = minWd > wd ? wd : minWd;
minJd = minJd > jd ? jd : minJd;
}
}
BigDecimal centerWd = new BigDecimal((maxWd + minWd) / 2D);
BigDecimal centerJd = new BigDecimal((maxJd + minJd) / 2D);
centerWd = centerWd.setScale(6, BigDecimal.ROUND_HALF_UP);
centerJd = centerJd.setScale(6, BigDecimal.ROUND_HALF_UP);
setCenterWd(centerWd.toPlainString());
setCenterJd(centerJd.toPlainString());
zoom = GoogleMapZoom.getZoom(maxWd, minWd, maxJd, minJd, width, height);
}
}
}
public void onMarkerSelect(OverlaySelectEvent event) {
selectedMarker = (Marker) event.getOverlay();
}
public List<Corporation> getCorporations() {
return corporations;
}
public void setCorporations(List<Corporation> corporations) {
corporations = corporations == null ? new ArrayList<Corporation>() : corporations;
this.corporations = corporations;
calInfosByCorporations();
}
public MapModel getModel() {
return model;
}
public String getCenterJd() {
return centerJd;
}
public void setCenterJd(String centerJd) {
this.centerJd = centerJd;
}
public String getCenterWd() {
return centerWd;
}
public void setCenterWd(String centerWd) {
this.centerWd = centerWd;
}
public String getZoom() {
return zoom;
}
public void setZoom(String zoom) {
this.zoom = zoom;
}
public Marker getSelectedMarker() {
return selectedMarker;
}
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
public void setModel(MapModel model) {
this.model = model;
}
public void setSelectedMarker(Marker selectedMarker) {
this.selectedMarker = selectedMarker;
}
}
5 js.xhtml("js" means "reduce", not "javascript"), the important part in this xhtml file:
<h:form id="dwMapForm">
<comuicommon:corpInfoMapDialog
mapModel="#{jlltWssbDjjsbEditPage.corporationMapModel}"
selectedListener="#{jlltWssbDjjsbEditPage.setSelectedMarker(org.primefaces.event.map.OverlaySelectEvent)}"
dialogId="dwMapDialog"
/>
</h:form>
what I've done:
1, I've googled a lot, but there are no answers.
2, I've debuged, I found that the event object has been generated by primefaces (at least, in the method of AjaxBehaviorRenderer.decode(FacesContext context, UIComponent component, ClientBehavior behavior), the event object is exists, not null.)
3, and in the method of JlltWssbDjjsbEditPage.setSelectedMarker(OverlaySelectEvent event), the event is null.
Thank you every one!
I hope I've make it clear.
Best regards!