Jsf f:setPropertyActionListener未在p:dataTable中调用
我跟随PrimeFacesDataGrid showcase完成了我的datatable。我想为datatable的每一行显示一个edit imagebutton,单击后我想显示一个编辑对话框表单 问题是在commandlink单击时未触发setSelectedChannel方法,因此当对话框尝试访问selecteChannel字段时出现此错误:Jsf f:setPropertyActionListener未在p:dataTable中调用,jsf,jsf-2,primefaces,datatable,Jsf,Jsf 2,Primefaces,Datatable,我跟随PrimeFacesDataGrid showcase完成了我的datatable。我想为datatable的每一行显示一个edit imagebutton,单击后我想显示一个编辑对话框表单 问题是在commandlink单击时未触发setSelectedChannel方法,因此当对话框尝试访问selecteChannel字段时出现此错误: javax.el.PropertyNotFoundException: /WEB-INF/includes/channels.xhtml @54,91
javax.el.PropertyNotFoundException: /WEB-INF/includes/channels.xhtml @54,91 value="#{channelBean.selectedChannel.name}": Target Unreachable, 'selectedChannel' returned null
这是我的xhtml包含页面:
<ui:composition
xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<h:form id="channelForm">
<p:dataTable var="channel" value="#{channelBean.channels}">
<p:column headerText="Name">
<h:outputText value="#{channel.name}" />
</p:column>
<p:column headerText="Field 1">
<h:outputText value="#{channel.field1}" />
</p:column>
<p:column headerText="Field 2">
<h:outputText value="#{channel.field2}" />
</p:column>
<p:column headerText="ApiWriteKey">
<h:outputText value="#{channel.apiWriteKey}" />
</p:column>
<p:column headerText="Edit">
<p:commandLink update=":channelForm:panelEditCh" oncomplete="PF('dlg2').show();" title="Edit">
<h:outputText styleClass="ui-icon ui-icon-search" style="margin:0 auto;" />
<f:setPropertyActionListener value="#{channel}" target="#{channelBean.selectedChannel}" />
</p:commandLink>
</p:column>
</p:dataTable>
<p:dialog id="dialogNewChannel" header="New Channel" widgetVar="dlg1" modal="false" >
<h:panelGrid columns="2" style="margin-bottom:10px" cellpadding="5">
<p:outputLabel for="channelName" value="Channel name:" />
<p:inputText id="channelName" value="#{channelBean.name}" />
<p:outputLabel for="channelDesc" value="Channel description:" />
<p:inputText id="channelDesc" value="#{channelBean.description}" />
<p:outputLabel for="channelField1" value="Channel field 1:" />
<p:inputText id="channelField1" value="#{channelBean.field1}" />
<p:outputLabel for="channelField2" value="Channel field 2:" />
<p:inputText id="channelField2" value="#{channelBean.field2}" />
</h:panelGrid>
<p:commandButton id="saveButton" value="Save" action="#{channelBean.saveChannel}" update="channelForm" ajax="true" />
<p:commandButton value="Cancel" type="button" action="#{channelBean.resetForm}" onclick="PF('dlg1').hide();" />
</p:dialog>
<p:dialog id="dialogEditChannel" header="Edit Channel" widgetVar="dlg2" modal="false" >
<h:panelGrid id="panelEditCh" columns="2" style="margin-bottom:10px" cellpadding="5">
<p:outputLabel for="channelNameEdit" value="Channel name:" />
<p:inputText id="channelNameEdit" value="#{channelBean.selectedChannel.name}" />
<p:outputLabel for="channelDescEdit" value="Channel description:" />
<p:inputText id="channelDescEdit" value="#{channelBean.selectedChannel.description}" />
<p:outputLabel for="channelField1Edit" value="Channel field 1:" />
<p:inputText id="channelField1Edit" value="#{channelBean.selectedChannel.field1}" />
<p:outputLabel for="channelField2Edit" value="Channel field 2:" />
<p:inputText id="channelField2Edit" value="#{channelBean.selectedChannel.field2}" />
</h:panelGrid>
<p:commandButton id="saveButtonEdit" value="Save" action="#{channelBean.saveChannel}" update="channelForm" ajax="true" />
<p:commandButton value="Cancel" type="button" action="#{channelBean.resetForm}" onclick="PF('dlg2').hide();" />
</p:dialog>
<p:spacer></p:spacer>
<p:spacer></p:spacer>
<p:commandButton value="New Channel" type="button" onclick="PF('dlg1').show();" />
<!-- <p:blockUI block="dialogNewChannel" trigger="saveButton">
<p:graphicImage name="images/ajax-loader-large.gif"/>
</p:blockUI>
-->
</h:form>
和ManagedBean:
@ManagedBean
@ViewScoped
public class ChannelBean implements Serializable {
/**
*
*/
private static final long serialVersionUID = -1668407926998690759L;
private String idChannel;
private String apiWriteKey;
private String name;
private String description;
private String userId;
private String field1;
private String field2;
private Channel selectedChannel;
private List<Channel> channels= new ArrayList<Channel>() ;
@PostConstruct
public void populateChannelList(){
refreshList();
}
public void refreshList(){
HttpSession session = Util.getSession();
int idUser=-1;
if(session!=null &&session.getAttribute("idUser")!=null){
idUser=(int) session.getAttribute("idUser");
}
channels=ChannelDAO.getChannels(idUser);
}
public void saveChannel(){
....
}
public void resetForm(){
idChannel="";
apiWriteKey="";
name="";
description="";
userId="";
field1="";
field2="";
}
public String getIdChannel() {
return idChannel;
}
public void setIdChannel(String idChannel) {
this.idChannel = idChannel;
}
public String getApiWriteKey() {
return apiWriteKey;
}
public void setApiWriteKey(String apiWriteKey) {
this.apiWriteKey = apiWriteKey;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getField1() {
return field1;
}
public void setField1(String field1) {
this.field1 = field1;
}
public String getField2() {
return field2;
}
public void setField2(String field2) {
this.field2 = field2;
}
public List<Channel> getChannels() {
return channels;
}
public void setChannels(List<Channel> channels) {
this.channels = channels;
}
public Channel getSelectedChannel() {
return selectedChannel;
}
public void setSelectedChannel(Channel selectedChannel) {
this.selectedChannel = selectedChannel;
}
}
@ManagedBean
@视域
公共类ChannelBean实现了可序列化{
/**
*
*/
私有静态最终长SerialVersionId=-16684079269989690759L;
专用字符串idChannel;
私有字符串apiWriteKey;
私有字符串名称;
私有字符串描述;
私有字符串用户标识;
私有字符串字段1;
私有字符串字段2;
专用频道选择频道;
私有列表通道=新的ArrayList();
@施工后
public void populateChannelList(){
刷新列表();
}
公共空刷新列表(){
HttpSession session=Util.getSession();
int idUser=-1;
if(session!=null&&session.getAttribute(“idUser”)!=null){
idUser=(int)session.getAttribute(“idUser”);
}
channels=ChannelDAO.getChannels(idUser);
}
公共void存储通道(){
....
}
公共表格(){
idChannel=“”;
apiWriteKey=“”;
name=“”;
description=“”;
userId=“”;
字段1=“”;
字段2=“”;
}
公共字符串getIdChannel(){
返回通道;
}
公共无效setIdChannel(字符串idChannel){
this.idChannel=idChannel;
}
公共字符串getApiWriteKey(){
返回apiWriteKey;
}
公共void setApiWriteKey(字符串apiWriteKey){
this.apiWriteKey=apiWriteKey;
}
公共字符串getName(){
返回名称;
}
公共void集合名(字符串名){
this.name=名称;
}
公共字符串getDescription(){
返回说明;
}
公共void集合描述(字符串描述){
this.description=描述;
}
公共字符串getUserId(){
返回用户标识;
}
public void setUserId(字符串userId){
this.userId=userId;
}
公共字符串getField1(){
返回字段1;
}
公共无效集合字段1(字符串字段1){
此字段1=字段1;
}
公共字符串getField2(){
返回字段2;
}
公共无效集合字段2(字符串字段2){
this.field2=field2;
}
公共列表getChannels(){
返回通道;
}
公共频道(列出频道){
这个。通道=通道;
}
公共频道getSelectedChannel(){
返回所选频道;
}
公共无效设置选定频道(频道选定频道){
this.selectedChannel=selectedChannel;
}
}
您在哪里初始化了selectedChannel
(专用频道selectedChannel;
)?此外,从底层Servlet API公开一个HttpSession
实例是完全没有必要的。我认为这应该可以做到,我的做法与primefaces showcase中的做法完全相同:我尝试使用第一个频道列表初始化selectChannel,现在它可以工作了!非常感谢。但我不知道primefaces showcase如何工作。。。。我还有一个问题要问你,如何在不使用会话的情况下检索userId?你可以使用ExternalContext
检索会话映射,例如map sessionMap=FacesContext.getCurrentInstance().getExternalContext().getSessionMap()改为使用code>并将userId
放入该映射中,但您最好选择自己的会话范围bean,在该bean中使用getter(以及setter,如果需要)声明map
。公开底层Servlet API是一种代码味道。