Thang Pham
Thang Pham

Reputation: 38695

Is this Primefaces bug or Mojarra/MyFaces bug

I cannot seems to be able to fire an event when I am within column of dataTable. Here is my simple demostration

<h:form id="form">
    <!--This section of p:tree here seems to be the reason causing the event not fired when click the command button-->
    <p:tree value="#{viewBean.root}" var="node" dynamic="true" cache="false"  
                selectionMode="checkbox"  selection="#{treeBean.selectedNode}">  

        <p:ajax event="expand" update=":form:messages" listener="#{viewBean.onNodeExpand}" />  
        <p:ajax event="collapse" update=":form:messages" listener="#{viewBean.onNodeCollapse}" />  
        <p:ajax event="select" update=":form:messages" listener="#{viewBean.onNodeSelect}" />  
        <p:ajax event="unselect" update=":form:messages" listener="#{viewBean.onNodeUnselect}" />  

        <p:treeNode>  
            <h:outputText value="#{node}" />  
        </p:treeNode>  
    </p:tree>
    <h:panelGroup id="mygroup">
            <p:dataTable id="mytable" value="#{viewBean.foodList}" var="item">
                <p:column>
                    #{item}
                </p:column>
                <p:column>
                    <p:commandButton value="delete" 
                                     action="#{viewBean.delete}"
                                     update=":form:mygroup">
                        <f:setPropertyActionListener target="#{viewBean.selectedFood}"
                                                     value="#{item}"/>
                    </p:commandButton>
                </p:column>
            </p:dataTable>
    </h:panelGroup>
</h:form>

and here is my managed bean

@ManagedBean
@ViewScoped
public class ViewBean {

    private TreeNode root;  

    private TreeNode selectedNode;  
    private List<String> foodList;

    private String selectedFood;

    @PostConstruct
    public void init(){

        foodList = new ArrayList<String>();
        foodList.add("Pizza");
        foodList.add("Pasta");
        foodList.add("Hamburger");

        root = new DefaultTreeNode("Root", null);  
        TreeNode node0 = new DefaultTreeNode("Node 0", root);  
        TreeNode node1 = new DefaultTreeNode("Node 1", root);  
        TreeNode node2 = new DefaultTreeNode("Node 2", root);  

        TreeNode node00 = new DefaultTreeNode("Node 0.0", node0);  
        TreeNode node01 = new DefaultTreeNode("Node 0.1", node0);  

        TreeNode node10 = new DefaultTreeNode("Node 1.0", node1);  
        TreeNode node11 = new DefaultTreeNode("Node 1.1", node1);  

        TreeNode node000 = new DefaultTreeNode("Node 0.0.0", node00);  
        TreeNode node001 = new DefaultTreeNode("Node 0.0.1", node00);  
        TreeNode node010 = new DefaultTreeNode("Node 0.1.0", node01);  

        TreeNode node100 = new DefaultTreeNode("Node 1.0.0", node10);  
    }

    public void delete(){

        foodList.remove(selectedFood);

    }
    //setter and getter

    public void onNodeExpand(NodeExpandEvent event) {  
       FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_INFO, "Expanded", event.getTreeNode().toString());  

       FacesContext.getCurrentInstance().addMessage(null, message);  
    }  

    public void onNodeCollapse(NodeCollapseEvent event) {  
       FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_INFO, "Collapsed", event.getTreeNode().toString());  

       FacesContext.getCurrentInstance().addMessage(null, message);  
    }  

    public void onNodeSelect(NodeSelectEvent event) {  
       FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_INFO, "Selected", event.getTreeNode().toString());  

       FacesContext.getCurrentInstance().addMessage(null, message);  
    }  

    public void onNodeUnselect(NodeUnselectEvent event) {  
        FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_INFO, "Unselected", event.getTreeNode().toString());  

        FacesContext.getCurrentInstance().addMessage(null, message);  
    }  
}

My problem seems to be that the event is not fired, meaning delete never get invoked.

I have look around, and know that Mojarra have ton of issues with nested UIData components, so I tried Mojarra 2.1.4, still did not solved the problem. I tried Myfaces 2.1.5, still does not work!!! Is this a Primefaces bugs? I even use h:panelGroup as a wrapper for update but it still does not work.

EDIT: It turn out that the p:tree above the dataTable is the root cause of the event not fired when clicking the commandButton. If I remove the p:tree then it work immediately. Note that the p:tree itself work great, as I click on the checkout, event fired on my managed bean.

Upvotes: 0

Views: 4214

Answers (1)

BalusC
BalusC

Reputation: 1109570

It's a bug in your own code.

<partial-response>
  <error>
    <error-name>class javax.el.ELException</error-name>
    <error-message><![CDATA[/index.xhtml @15,84 selection="#{viewBean.selectedNode}": Cannot convert [Lorg.primefaces.model.TreeNode;@fd9b4d of type class [Lorg.primefaces.model.TreeNode; to interface org.primefaces.model.TreeNode]]></error-message>
  </error>
</partial-response>

The concrete exception message suggests that the <p:tree selection> is expected to refer a property of type TreeNode[] and not TreeNode (note the [ prefix on the class identifier in the message which indicates an array type). So, fix it accordingly:

<p:tree selection="#{treeBean.selectedNodes}">

with

private TreeNode[] selectedNodes;

Regardless, you've both the <p:tree> and <p:dataTable> inside the one and same "god" form. So any action in either of them will submit everything on the other component as well. If the tree and the table are in no way related to each other, then they should each be placed in its own <h:form>. Or, you must add a process attribute to the command links/buttons to process only the containing component of interest, e.g. process="mytable" on the button inside the table.

Upvotes: 5

Related Questions