I have this datatable which I implemented with Primefaces's LazyDataModel.
Everything works fine except for the initial load when I open the page for the first time or refresh.
The load method get called 6-7 times.
When I change page, filter or sort it works correctly, load is only called once.
Since I perform calls to the database I would like to prevent it to be called more then needed.
I have the following:
XHTML:
<p:outputPanel id="documentsPanel">
<h:form id="documentsForm">
<p:dataTable id="documentsTable"
widgetVar="documentsTable"
var="doc"
value="#{MyManagedBean.model}"
paginator="true" rows="20"
paginatorTemplate="{FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {CurrentPageReport}"
currentPageReportTemplate="{totalRecords} #{c.NumberOfRequestFound}"
lazy="true">
...
</p:dataTable>
</h:form>
</p:outputPanel>
Java:
public class DocumentEncodingDataModel extends LazyDataModel<SelectableDocumentToBeEncodedDTO> {
#Override
public List<SelectableDocumentToBeEncodedDTO> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String, Object> filters) {
....
}
#Override
public int getRowCount() {
return super.getRowCount();
}
#Override
public SelectableDocumentToBeEncodedDTO getRowData(String rowKey) {
log.debug("getRowData");
if (!StringUtils.isBlank(rowKey)) {
for (SelectableDocumentToBeEncodedDTO doc : currentDocumentsToBeEncoded) {
if (doc.getDocumentToBeEncoded().getId().toString().equals(rowKey)) {
return doc;
}
}
}
return null;
}
#Override
public Object getRowKey(SelectableDocumentToBeEncodedDTO doc) {
return doc.getDocumentToBeEncoded().getId();
}
}
Primefaces version: 6.2
JSF version: 2.1
It's easy to show the selected row value in a dialog from a p:contextMenu. However, is there an easy way to show the column value (e.g. "2:b") or to get the column index on which the right-click happend?
<p:dataTable id="dt" value="#{['a','b','c']}" var="x" selection="#{bean.x}"
widgetVar="dtv" selectionMode="single" rowKey="#{x}">
<p:column>1:#{x}</p:column>
<p:column>2:#{x}</p:column>
</p:dataTable>
<p:contextMenu for="dt">
<p:menuitem value="Show" update="di" oncomplete="PF('wv').show()" />
</p:contextMenu>
<p:dialog id="di" widgetVar="wv">X=#{bean.x}</p:dialog>
Using: PF6.0 on JavaEE 7
Just idea...
Xhtml
I added two <h:inputHidden/> components and JavaScript function applySelectedCell which is called before context menu is shown.
<h:form prependId="false">
<script type="text/javascript">
function applySelectedCell(event) {
var cell = $(event.target);
if (!cell.is('td')) {
cell = cell.closest('td');
}
var row = cell.closest('tr');
var selectedCell = row.children().index(cell);
$('#selectedCell').val(selectedCell);
$('#selectedHtmlValue').val(cell.text());
}
</script>
<h:inputHidden id="selectedCell" value="#{bean.selectedCell}"/>
<h:inputHidden id="selectedHtmlValue" value="#{bean.selectedHtmlValue}"/>
<p:dataTable id="dt" value="#{['a','b','c']}" var="x" selection="#{bean.x}"
widgetVar="dtv" selectionMode="single" rowKey="#{x}">
<p:column>1:<div style="background: yellow;">#{x}</div></p:column>
<p:column>2:#{x}</p:column>
</p:dataTable>
<p:contextMenu for="dt" beforeShow="applySelectedCell(event);">
<p:menuitem value="Show" update="di" oncomplete="PF('wv').show()" />
</p:contextMenu>
<p:dialog id="di" widgetVar="wv">
<div>Cell value (Bean) = #{bean.selectedBeanValue}</div>
<div>Cell value (HTML) = #{bean.selectedHtmlValue}</div>
</p:dialog>
</h:form>
Backing bean
#ViewScoped
#Named
public class Bean implements Serializable {
private String x = "a";
private Integer selectedCell;
private String selectedHtmlValue;
public String getX() {
return x;
}
public void setX(String x) {
this.x = x;
}
public Integer getSelectedCell() {
return selectedCell;
}
public void setSelectedCell(Integer selectedCell) {
this.selectedCell = selectedCell;
}
public String getSelectedHtmlValue() {
return selectedHtmlValue;
}
public void setSelectedHtmlValue(String selectedHtmlValue) {
this.selectedHtmlValue = selectedHtmlValue;
}
public String getSelectedBeanValue() {
if (selectedCell != null) {
return (selectedCell + 1) + ":" + x;
} else {
return x;
}
}
}
I´m a begginer in Primefaces.... And I tried to make the example DragDrop - Native Primefaces
I´ll posted all the clases and xhtml files involved for this example.
I can drag any columns but it´s not working the droping property....
You can see an image showing the trouble in this link https://lh3.googleusercontent.com/clMOtntqI99ltjXGYpzUGt-8yg4N8ahtQQIBT5leNA=w314-h207-p-no
The fist file is dndColumns.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: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">
<h:head>
<title>dndColumns</title>
</h:head>
<body>
<h:form id="form">
<p:remoteCommand name="updateColumns" actionListener="#{tableBean.onColumnDrop}"
update="cars" oncomplete="initDND()"/>
<p:tree id="tree" value="#{tableBean.availableColumns}" var="column">
<p:treeNode>
<h:outputText value="#{column}" />
</p:treeNode>
<p:treeNode type="column" icon="ui-icon-grip-dotted-vertical">
<h:outputText value="#{column.property}" />
</p:treeNode>
</p:tree>
<p:dataTable id="cars" var="car" value="#{tableBean.carsSmall}">
<p:columns value="#{tableBean.columns}" var="column">
<f:facet name="header">
<h:outputText style="float:left;display:block;height:12px;width:10px;border:0 none;"
styleClass="droppoint dropleft" />
<h:outputText style="float:right;display:block;height:12px;width:10px;border:0 none;"
styleClass="droppoint dropright" />
<h:outputText value="#{column.header}" />
</f:facet>
<h:outputText value="#{car[column.property]}" />
</p:columns>
</p:dataTable>
<script type="text/javascript">
function initDND() {
$('.ui-treenode-leaf').draggable({
helper: 'clone',
scope: 'treetotable',
zIndex: ++PrimeFaces.zindex
});
$('.ui-datatable .droppoint').droppable({
activeClass: 'ui-state-active',
hoverClass: 'ui-state-highlight',
tolerance: 'pointer',
scope: 'treetotable',
drop: function(event, ui) {
var property = ui.draggable.find('.ui-treenode-label').text(),
droppedColumnId = $(this).parents('th:first').attr('id'),
dropPos = $(this).hasClass('dropleft') ? 0 : 1;
treeToTable([
{name: 'property', value: property}
,{name: 'droppedColumnId', value: droppedColumnId}
,{name: 'dropPos', value: dropPos}
]);
}
});
$('.ui-datatable th').draggable({
helper: 'clone',
scope: 'tabletotree',
helper: function() {
var th = $(this);
return th.clone().css('width', th.width());
}
});
$('.ui-tree').droppable({
helper: 'clone',
scope: 'tabletotree',
activeClass: 'ui-state-active',
hoverClass: 'ui-state-highlight',
tolerance: 'touch',
drop: function(event, ui) {
tableToTree([
{name: 'colIndex', value: ui.draggable.index()}
]);
}
});
}
$(function() {
initDND();
});
</script>
<hr/>
<p:menu>
<p:submenu label="Resources">
<p:menuitem value="Demo" url="http://www.primefaces.org/showcase-labs/ui/dndColumns.jsf" />
</p:submenu>
</p:menu>
</h:form>
</body>
</html>
The second file is TableBean.java
package org.sagarpa.src.managedBean;
import java.io.Serializable;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.logging.Logger;
import javax.faces.context.FacesContext;
import org.primefaces.model.DefaultTreeNode;
import org.primefaces.model.TreeNode;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
// import org.primefaces.examples.domain.Car;
import org.sagarpa.src.bean.Car;
#ManagedBean
#SessionScoped
public class TableBean implements Serializable {
private final static List<String> VALID_COLUMN_KEYS = Arrays.asList("model", "manufacturer", "year", "color");
private final static String[] colors;
private final static String[] manufacturers;
private String columnTemplate = "model manufacturer year";
static {
colors = new String[10];
colors[0] = "Black";
colors[1] = "White";
colors[2] = "Green";
colors[3] = "Red";
colors[4] = "Blue";
colors[5] = "Orange";
colors[6] = "Silver";
colors[7] = "Yellow";
colors[8] = "Brown";
colors[9] = "Maroon";
manufacturers = new String[10];
manufacturers[0] = "Mercedes";
manufacturers[1] = "BMW";
manufacturers[2] = "Volvo";
manufacturers[3] = "Audi";
manufacturers[4] = "Renault";
manufacturers[5] = "Opel";
manufacturers[6] = "Volkswagen";
manufacturers[7] = "Chrysler";
manufacturers[8] = "Ferrari";
manufacturers[9] = "Ford";
}
private List<Car> carsSmall;
private List<Car> carsLarge;
private List<ColumnModel> columns = new ArrayList<ColumnModel>();
private TreeNode availableColumns;
public TableBean() {
carsSmall = new ArrayList<Car>();
populateRandomCars(carsSmall, 9);
createDynamicColumns();
createAvailableColumns();
}
private void populateRandomCars(List<Car> list, int size) {
for(int i = 0 ; i < size ; i++)
list.add(new Car(getRandomModel(), getRandomYear(), getRandomManufacturer(), getRandomColor()));
}
public List<Car> getCarsSmall() {
return carsSmall;
}
private int getRandomYear() {
return (int) (Math.random() * 50 + 1960);
}
private String getRandomColor() {
return colors[(int) (Math.random() * 10)];
}
private String getRandomManufacturer() {
return manufacturers[(int) (Math.random() * 10)];
}
private String getRandomModel() {
return UUID.randomUUID().toString().substring(0, 8);
}
public List<ColumnModel> getColumns() {
return columns;
}
private void createAvailableColumns() {
availableColumns = new DefaultTreeNode("Root", null);
TreeNode root = new DefaultTreeNode("Columns", availableColumns);
root.setExpanded(true);
TreeNode model = new DefaultTreeNode("column", new ColumnModel("Model", "model"), root);
TreeNode year = new DefaultTreeNode("column", new ColumnModel("Year", "year"), root);
TreeNode manufacturer = new DefaultTreeNode("column", new ColumnModel("Manufacturer", "manufacturer"), root);
TreeNode color = new DefaultTreeNode("column", new ColumnModel("Color", "color"), root);
}
public TreeNode getAvailableColumns() {
return availableColumns;
}
public void createDynamicColumns() {
String[] columnKeys = columnTemplate.split(" ");
columns.clear();
for(String columnKey : columnKeys) {
String key = columnKey.trim();
if(VALID_COLUMN_KEYS.contains(key)) {
columns.add(new ColumnModel(columnKey.toUpperCase(), columnKey));
}
}
}
public void treeToTable() {
Map<String,String> params = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();
String property = params.get("property");
String droppedColumnId = params.get("droppedColumnId");
String dropPos = params.get("dropPos");
String[] droppedColumnTokens = droppedColumnId.split(":");
int draggedColumnIndex = Integer.parseInt(droppedColumnTokens[droppedColumnTokens.length - 1]);
int dropColumnIndex = draggedColumnIndex + Integer.parseInt(dropPos);
//add to columns
this.columns.add(dropColumnIndex, new ColumnModel(property.toUpperCase(), property));
//remove from nodes
TreeNode root = availableColumns.getChildren().get(0);
for(TreeNode node : root.getChildren()) {
ColumnModel model = (ColumnModel) node.getData();
if(model.getProperty().equals(property)) {
root.getChildren().remove(node);
break;
}
}
}
public void tableToTree() {
Map<String,String> params = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();
int colIndex = Integer.parseInt(params.get("colIndex"));
//remove from table
ColumnModel model = this.columns.remove(colIndex);
//add to nodes
TreeNode property = new DefaultTreeNode("column", model, availableColumns.getChildren().get(0));
}
static public class ColumnModel implements Serializable {
private String header;
private String property;
public ColumnModel(String header, String property) {
this.header = header;
this.property = property;
}
public String getHeader() {
return header;
}
public String getProperty() {
return property;
}
}
}
And the third and last file is Car.java
package org.sagarpa.src.bean;
// import java.util.Date;
public class Car {
private String model;
private int year;
private String manufacturer;
private String color;
public Car(String model, int year, String manufacturer, String color) {
this.model = model;
this.year = year;
this.manufacturer = manufacturer;
this.color = color;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
public String getManufacturer() {
return manufacturer;
}
public void setManufacturer(String manufacturer) {
this.manufacturer = manufacturer;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}
The problem exists when I want to drag any component because its can´t drop on the table or on the Columns area rectangle.
Please.... Could you help me to complete the code ??? Any sugestion ???
Regards...
I YET solved my problem....
Only make a change into the fist file is dndColumns.xhtml
We need to replace this line:
<p:remoteCommand name="updateColumns" actionListener="#{tableBean.onColumnDrop}" update="cars" oncomplete="initDND()"/>
for other these two lines:
<p:remoteCommand name="treeToTable" actionListener="#{tableBean.treeToTable}" update="tree cars" oncomplete="initDND()"/>
<p:remoteCommand name="tableToTree" actionListener="#{tableBean.tableToTree}" update="tree cars" oncomplete="initDND()"/>
And test it again.....
WONDERFUL....!!!!!!
I'll post the complete dndColumns.xhtml 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: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">
<h:head>
<title>dndColumns</title>
</h:head>
<body>
<h1 class="title ui-widget-header ui-corner-all">DragDrop - Native</h1>
<p>This sample demonstrates how to integrate low level jquery apis with PrimeFaces. Tree component displays the available
columns which are draggable. Column headers have drop targets and dropping a treenode onto one of these adds the related property column to the datatable.
Column headers can also be moved back to the tree.</p>
<h:form id="form">
<p:remoteCommand name="treeToTable" actionListener="#{tableBean.treeToTable}" update="tree cars" oncomplete="initDND()"/>
<p:remoteCommand name="tableToTree" actionListener="#{tableBean.tableToTree}" update="tree cars" oncomplete="initDND()"/>
<p:tree id="tree" value="#{tableBean.availableColumns}" var="column">
<p:treeNode>
<h:outputText value="#{column}" />
</p:treeNode>
<p:treeNode type="column" icon="ui-icon-grip-dotted-vertical">
<h:outputText value="#{column.property}" />
</p:treeNode>
</p:tree>
<br />
<p:dataTable id="cars" var="car" value="#{tableBean.carsSmall}">
<p:columns value="#{tableBean.columns}" var="column">
<f:facet name="header">
<h:outputText style="float:left;display:block;height:20px;width:10px;border:0 none;" styleClass="droppoint dropleft" />
<h:outputText style="float:right;display:block;height:20px;width:10px;border:0 none;" styleClass="droppoint dropright" />
<h:outputText value="#{column.header}" />
</f:facet>
<h:outputText value="#{car[column.property]}" />
</p:columns>
</p:dataTable>
<script type="text/javascript">
function initDND() {
$('.ui-treenode-leaf').draggable({
helper: 'clone',
scope: 'treetotable',
zIndex: ++PrimeFaces.zindex
});
$('.ui-datatable .droppoint').droppable({
activeClass: 'ui-state-active',
hoverClass: 'ui-state-highlight',
tolerance: 'pointer',
scope: 'treetotable',
drop: function(event, ui) {
var property = ui.draggable.find('.ui-treenode-label').text(),
droppedColumnId = $(this).parents('th:first').attr('id'),
dropPos = $(this).hasClass('dropleft') ? 0 : 1;
treeToTable([
{name: 'property', value: property}
,{name: 'droppedColumnId', value: droppedColumnId}
,{name: 'dropPos', value: dropPos}
]);
}
});
$('.ui-datatable th').draggable({
helper: 'clone',
scope: 'tabletotree',
helper: function() {
var th = $(this);
return th.clone().css('width', th.width());
}
});
$('.ui-tree').droppable({
helper: 'clone',
scope: 'tabletotree',
activeClass: 'ui-state-active',
hoverClass: 'ui-state-highlight',
tolerance: 'touch',
drop: function(event, ui) {
tableToTree([
{name: 'colIndex', value: ui.draggable.index()}
]);
}
});
}
$(function() {
initDND();
});
</script>
<hr/>
<p:menu>
<p:submenu label="Resources">
<p:menuitem value="Demo" url="http://www.primefaces.org/showcase-labs/ui/dndColumns.jsf" />
</p:submenu>
</p:menu>
</h:form>
</body>
</html>
I am trying to toggle between a simple "click the row to select" table and a "multi-select Checkbox in the first column table". I have a check box outside the table to change the state of the table. For the simple table (no check boxes in the first column) a selectionMode must be set in the p:datatable tag; either to "single" or "multiple". In this state everything works fine.
If the state is changed so that the multi-select column is rendered, the click event seems to be consumed by selecting the selecting the row. In general when using this multi-select check box table the selectionMode would not be set; hence the mouse event would change the state of the check box.
How do I "unset" the selectionMode. Here are the things that did not work:
table.setSelectionMode(null) - this breaks the selection (so does setting to "")
table.getAttributes().get("javax.faces.component.UIComponentBase.attributesThatAreSet") then removing the selectionMode (it isn't in the set attributes).
My xhtml looks like:
<h:form id="addForm">
<p:panel toggleable="false" closable="false" widgetVar="remarksPanel"
id="remarksPanel" style="margin-bottom:5px; overflow:auto;">
<p:selectBooleanCheckbox value="#{multipleSelectBean.bulkEdit}">
<p:ajax update="addForm:remarksTable"
listener="#{multipleSelectBean.editModeChanged}" />
</p:selectBooleanCheckbox>
<h:outputText value=" Bulk Edit" />
<p:dataTable var="remark" id="remarksTable" rowIndexVar="rowNum"
value="#{multipleSelectBean.remarkList}" rowKey="#{remark.id}"
selectionMode="multiple"
selection="#{multipleSelectBean.selectedRemarks}">
<p:column rendered="#{multipleSelectBean.bulkEdit}"
selectionMode="multiple" style="width:18px" />
<p:column headerText="Remark">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{remark.remark}" />
</f:facet>
<f:facet name="input">
<p:inputText style="width:98%" id="remark"
value="#{remark.remark}" />
</f:facet>
</p:cellEditor>
</p:column>
</p:dataTable>
</p:panel>
</h:form>
My Bean Looks Like:
package gov.gsa.krichards.sandbox;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
import org.primefaces.component.datatable.DataTable;
import org.primefaces.event.SelectEvent;
#ManagedBean
#SessionScoped
public class MultipleSelectBean implements Serializable {
private static final long serialVersionUID = 1L;
private final static String[] categoryList;
private List<Remark> remarkList = new ArrayList<Remark>();
private Remark[] selectedRemarks = null;
private String words = "Mauris interdum, turpis nec euismod c aliquet fermentum nisl, in tristique arcu tincidunt nec.";
private boolean bulkEdit = false;
private boolean initialized = false;
static {
categoryList = new String[4];
categoryList[0] = "Cat5";
categoryList[1] = "Cat4";
categoryList[2] = "Cat3-UTP";
categoryList[3] = "BNC";
}
public MultipleSelectBean() {
Random r = new Random();
for (int i = 0; i < 10; i++) {
String cat = categoryList[r.nextInt(4)];
int len = words.length();
int begIndex = r.nextInt(len / 2);
int endIndex = begIndex + r.nextInt(len - begIndex);
Remark rem = new Remark(i, cat, words.substring(begIndex, endIndex));
remarkList.add(rem);
}
}
public void editModeChanged() {
System.out.println("changed to " + bulkEdit);
}
public void setBulkEdit(boolean arg) {
DataTable table = (DataTable) FacesContext.getCurrentInstance()
.getViewRoot().findComponent("addForm:remarksTable");
bulkEdit = arg;
if (bulkEdit) {
table.setSelectionMode("single");
} else {
table.setSelectionMode("multiple");
}
}
public boolean isBulkEdit() {
return bulkEdit;
}
public List<Remark> getRemarkList() {
return remarkList;
}
public void setRemarkList(List<Remark> remarkList) {
this.remarkList = remarkList;
}
public String[] getCategoryList() {
return categoryList;
}
public Remark[] getSelectedRemarks() {
if (selectedRemarks == null || selectedRemarks.length == 0)
return null;
return selectedRemarks;
}
public void setSelectedRemarks(Remark[] selectedRemarks) {
this.selectedRemarks = selectedRemarks;
}
}
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!