如何通过 jee-7 中的 mdb-> websocket 更新数据 table 单元格? (db pk, client Id 映射)
Howto update a data table cell via mdb-> websocket in jee-7? (db pk, clientId mapping)
我有一个带有分页的 jsf-2.2 primefaces 数据table。一列显示网络组件的状态,在 table 加载时,我通过资源适配器异步查询外部服务。当加载数据 table 时,状态单元格显示为 "Status unknown"。有时,我会在消息驱动 Bean 中收到来自单个网络组件的状态数据包,如 json。然后我想通过 websocket 将此状态发送到浏览器以更新 table 单元格。 json 状态数据包包含网络组件的主要数据库密钥,但在浏览器的 javascript 端,我需要数据 table 单元格的 clientIds。 clientIds 的格式为 "switchTable:swths:2:switchActive",仅中间的索引不同。
我的第一个想法是写一个 facelet 并用网络组件的主键覆盖 id,但我认为这不是可行的方法。
是否有推荐的方法将 clientIds 映射到各个主键?此映射需要包括会话,因为有多个会话具有相同的 clientId。我想更新 table 单元格,我在 DOM 中找到的 document.getElementById 立即带有状态文本。
我想出了这个有趣问题的 2 个解决方案。
解决方案 1
- 定义隐藏的 table 列,其中包含 'ID' 文本,
- 通过遍历所有行并匹配 ID 列单元格的 'value',使用 javascript 查找数据 table 行和单元格
解决方案 2
- 利用 JSF2 命名空间
xmlns:pt="http://xmlns.jcp.org/jsf/passthrough"
到 'programatically' 设置 html id
列单元格元素的属性,
- 使用 javascript 的
document.getElementById
函数查找单元格元素
例子
xhtml 页数
<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"
xmlns:pt="http://xmlns.jcp.org/jsf/passthrough" >
<f:view contentType="text/html">
<h:head>
<h:outputScript library="primefaces" name="jquery/jquery.js" />
</h:head>
<h:body>
<p:dataTable id="dataTable" widgetVar="dataTableWidget" value="#{switchController.switches}" var="switch" paginator="true" rows="5">
<p:column headerText="id" style="display:none">
<h:outputText value="#{switch.id}"/>
</p:column>
<p:column headerText="Name">
<h:outputText value="#{switch.name}"/>
</p:column>
<p:column headerText="status">
<h:outputText value="#{switch.status}" pt:id="dataTable:switch:#{switch.id}:status"/>
</p:column>
</p:dataTable>
<p:commandButton value="Change status" type="button" onclick="changeStatusExample()"/>
</h:body>
</f:view>
</html>
Backing Bean(仅用于此示例)
public class SwitchController {
List<Switch> switches;
@PostConstruct
public void init() {
switches = new ArrayList<>();
for (int i = 1; i < 11; i++) {
switches.add(new Switch(i, "Switch " + i, "STATUS_UNKNOWN"));
}
}
public List<Switch> getSwitches() {
return switches;
}
public void setSwitches(List<Switch> switches) {
this.switches = switches;
}
}
其中 Switch
是具有 id
、name
和 status
字段的 POJO。
Javascript
// SOLUTION 1
function getTableCellByIdVer1(switchId, colNumber) {
//get table rows
var tableRows = PF('dataTableWidget').tbody[0].childNodes;
//loop through rows
for (i = 0; i < tableRows.length; i++) {
//get cells of current row
var cells = tableRows[i].cells;
//get value of hidden ID column cell
var id = cells[0].innerText;
if (id === switchId) {
return tableRows[i].cells[colNumber];
}
}
return null;
}
// SOLUTION 1
function changeSwitchStatusVer1(changedSwitch) {
var statusCell = getTableCellByIdVer1(changedSwitch.id, 2);
if (statusCell) {
//row exists...now we can change the status
statusCell.innerText = changedSwitch.status;
} else {
console.log('Row with switch id=' + changedSwitch.id + ' not found');
}
}
// SOLUTION 2
function changeSwitchStatusVer2(changedSwitch) {
//find cell element by html ID attribute given in xhtml
var elementId='dataTable:switch:' + changedSwitch.id + ':status';
var statusCell = document.getElementById(elementId);
if (statusCell) {
statusCell.innerText = changedSwitch.status;
} else {
console.log('Element with id=' + elementId + ' not found');
}
}
// EXAMPLE
function changeStatusExample() {
//simulating situation when websocket pushes info about changed switch to browser page
// SOLUTION 1
var changedSwitch = {id: '2', status: 'STATUS_ON'};
changeSwitchStatusVer1(changedSwitch);
// SOLUTION 2
//another switch status changed..using another approach to update table cell
changedSwitch = {id: '4', status: 'STATUS_OFF'};
changeSwitchStatusVer2(changedSwitch);
}
重要:请注意,只有当(更改的开关)ID 是当前 'visible' 数据 table 页面的一部分时,这两种解决方案才有效。
我有一个带有分页的 jsf-2.2 primefaces 数据table。一列显示网络组件的状态,在 table 加载时,我通过资源适配器异步查询外部服务。当加载数据 table 时,状态单元格显示为 "Status unknown"。有时,我会在消息驱动 Bean 中收到来自单个网络组件的状态数据包,如 json。然后我想通过 websocket 将此状态发送到浏览器以更新 table 单元格。 json 状态数据包包含网络组件的主要数据库密钥,但在浏览器的 javascript 端,我需要数据 table 单元格的 clientIds。 clientIds 的格式为 "switchTable:swths:2:switchActive",仅中间的索引不同。
我的第一个想法是写一个 facelet 并用网络组件的主键覆盖 id,但我认为这不是可行的方法。
是否有推荐的方法将 clientIds 映射到各个主键?此映射需要包括会话,因为有多个会话具有相同的 clientId。我想更新 table 单元格,我在 DOM 中找到的 document.getElementById 立即带有状态文本。
我想出了这个有趣问题的 2 个解决方案。
解决方案 1
- 定义隐藏的 table 列,其中包含 'ID' 文本,
- 通过遍历所有行并匹配 ID 列单元格的 'value',使用 javascript 查找数据 table 行和单元格
解决方案 2
- 利用 JSF2 命名空间
xmlns:pt="http://xmlns.jcp.org/jsf/passthrough"
到 'programatically' 设置 htmlid
列单元格元素的属性, - 使用 javascript 的
document.getElementById
函数查找单元格元素
例子
xhtml 页数
<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"
xmlns:pt="http://xmlns.jcp.org/jsf/passthrough" >
<f:view contentType="text/html">
<h:head>
<h:outputScript library="primefaces" name="jquery/jquery.js" />
</h:head>
<h:body>
<p:dataTable id="dataTable" widgetVar="dataTableWidget" value="#{switchController.switches}" var="switch" paginator="true" rows="5">
<p:column headerText="id" style="display:none">
<h:outputText value="#{switch.id}"/>
</p:column>
<p:column headerText="Name">
<h:outputText value="#{switch.name}"/>
</p:column>
<p:column headerText="status">
<h:outputText value="#{switch.status}" pt:id="dataTable:switch:#{switch.id}:status"/>
</p:column>
</p:dataTable>
<p:commandButton value="Change status" type="button" onclick="changeStatusExample()"/>
</h:body>
</f:view>
</html>
Backing Bean(仅用于此示例)
public class SwitchController {
List<Switch> switches;
@PostConstruct
public void init() {
switches = new ArrayList<>();
for (int i = 1; i < 11; i++) {
switches.add(new Switch(i, "Switch " + i, "STATUS_UNKNOWN"));
}
}
public List<Switch> getSwitches() {
return switches;
}
public void setSwitches(List<Switch> switches) {
this.switches = switches;
}
}
其中 Switch
是具有 id
、name
和 status
字段的 POJO。
Javascript
// SOLUTION 1
function getTableCellByIdVer1(switchId, colNumber) {
//get table rows
var tableRows = PF('dataTableWidget').tbody[0].childNodes;
//loop through rows
for (i = 0; i < tableRows.length; i++) {
//get cells of current row
var cells = tableRows[i].cells;
//get value of hidden ID column cell
var id = cells[0].innerText;
if (id === switchId) {
return tableRows[i].cells[colNumber];
}
}
return null;
}
// SOLUTION 1
function changeSwitchStatusVer1(changedSwitch) {
var statusCell = getTableCellByIdVer1(changedSwitch.id, 2);
if (statusCell) {
//row exists...now we can change the status
statusCell.innerText = changedSwitch.status;
} else {
console.log('Row with switch id=' + changedSwitch.id + ' not found');
}
}
// SOLUTION 2
function changeSwitchStatusVer2(changedSwitch) {
//find cell element by html ID attribute given in xhtml
var elementId='dataTable:switch:' + changedSwitch.id + ':status';
var statusCell = document.getElementById(elementId);
if (statusCell) {
statusCell.innerText = changedSwitch.status;
} else {
console.log('Element with id=' + elementId + ' not found');
}
}
// EXAMPLE
function changeStatusExample() {
//simulating situation when websocket pushes info about changed switch to browser page
// SOLUTION 1
var changedSwitch = {id: '2', status: 'STATUS_ON'};
changeSwitchStatusVer1(changedSwitch);
// SOLUTION 2
//another switch status changed..using another approach to update table cell
changedSwitch = {id: '4', status: 'STATUS_OFF'};
changeSwitchStatusVer2(changedSwitch);
}
重要:请注意,只有当(更改的开关)ID 是当前 'visible' 数据 table 页面的一部分时,这两种解决方案才有效。