Java – How to click on row and pass variable using managed bean

java, jsf, jsf-2

I have a example with h:datatable which is used to open a new page when the user clicks on a table row. Unfortunately this example uses the http header to pass argument to the opened page. My question is can this be implemented but with passing the argument into the background not with the header?

This is the complete source code:

This is the JSF page:

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE html><html xmlns="http://www.w3.org/1999/xhtml"      xmlns:h="http://java.sun.com/jsf/html"      xmlns:f="http://java.sun.com/jsf/core">    <head>        <title>test</title>        <script type="text/javascript">            function addOnclickToDatatableRows() {                //gets all the generated rows in the html table                var trs = document.getElementById('myForm:dataTable').getElementsByTagName('tbody')[0]                .getElementsByTagName('tr');                //on every row, add onclick function (this is what you're looking for)                for (var i = 0; trs.length > i; i++) {                    trs[i].onclick = new Function("rowOnclick(this)");                }            }            function rowOnclick(tr) {                //                var childNodes = tr.childNodes;                //                for(var i = 0; childNodes.length > i; i++) {                //                                    //                }                var elements = tr.cells[0].childNodes;                for(var i = 0; elements.length > i; i++) {                    if ((typeof elements[i].id !== "undefined") &amp;&amp;                    (elements[i].id.indexOf("lnkHidden") > -1)) {                      //opne in a new window//  window.open(elements[i].href);                        location.href=elements[i].href                        break;                    }                }                return false;            }        </script>    </head>    <body onload="addOnclickToDatatableRows();">        <h:form id="myForm">            <h1>Click on table row example</h1>            <h:dataTable id="dataTable" var="data" value="#{datatableBean.lstData}" border="1">                <h:column>                    <f:facet name="header">                        <h:outputText value="ID" />                    </f:facet>                    <h:outputText value="#{data.id}" />                    <h:outputLink id="lnkHidden" value="AnotherPage.xhtml"                                  style="display:none">                        <f:param name="id" value="#{data.id}" />                    </h:outputLink>                </h:column>                <h:column>                    <f:facet name="header">                        <h:outputText value="Value1" />                    </f:facet>                    <h:outputText value="#{data.value}" />                </h:column>                <h:column>                    <f:facet name="header">                        <h:outputText value="Value2" />                    </f:facet>                    <h:outputText value="#{data.value}" />                </h:column>            </h:dataTable>        </h:form>    </body></html>

This is the managed bean:

    package edu.home;    import edu.home.model.Data;    import java.util.ArrayList;    import java.util.List;    import javax.faces.bean.ManagedBean;    import javax.faces.bean.ViewScoped;    @ManagedBean    @ViewScoped    public class DatatableBean {        private List<Data> lstData;        /**         * Creates a new instance of datatableBean         */        public DatatableBean() {            lstData = new ArrayList<Data>();            lstData.add(new Data(1, "Hello World"));            lstData.add(new Data(2, "Hello 123"));            lstData.add(new Data(3, "Hello abv"));            lstData.add(new Data(4, "Hello qaz"));        }        /**         * @return the lstData         */        public List<Data> getLstData() {            return lstData;        }        /**         * @param lstData the lstData to set         */        public void setLstData(List<Data> lstData) {            this.lstData = lstData;        }    }This is the class Data:package edu.home.model;public class Data {    private int id;    private String value;    public Data(int id, String value) {        this.id = id;        this.value = value;    }    /**     * @return the id     */    public int getId() {        return id;    }    /**     * @param id the id to set     */    public void setId(int id) {        this.id = id;    }    /**     * @return the value     */    public String getValue() {        return value;    }    /**     * @param value the value to set     */    public void setValue(String value) {        this.value = value;    }}

I'm sure that this is possible but I can thing of a way to pass the argument into the appropriate way.

Best wishes

EDIT
I understand that the h:outputLink must be changed this way:

<h:column>    <f:facet name="header">        <h:outputText value="ID" />    </f:facet>    <h:outputText value="#{data.id}" />    <h:commandLink id="lnkHidden" value="AnotherPage.xhtml"                    style="display:none">        <f:param name="id" value="#{data.id}" />    </h:commandLink></h:column> 

But I don't understand how the managed bean must be changed. Maybe I suppose if AnotherPage.xhtml can access the managed bean of DataTable.xhml and take the value that I want to pass? But maybe then I need to change the javaScript?

Best Solution

You try using and render your table by yourself.

Here is my sample. Modify it according to your requirement. I used JSF 2.0

<h:form id="nextPage">    <table>        <ui:repeat var="row" value="#{shoppingCartMB.shoppingItems}">            <tr onclick="clickedMe('#{row.productId}');">                <td>#{row.productId}</td>            </tr>        </ui:repeat>    </table>    <script>        function clickedMe(id)        {            // Please modify following URL base on ur requirment..             // Following is just for sample..            location.href="#{request.contextPath}/product/" + id;        }    </script></h:form>

Here is some of pretty-config.xml

<url-mapping id="productMB-loadProductDetail">    <pattern value="/product/#{ productMB.productId }" />    <view-id value="/pages/product-detail.jsf" />          <action>#{productMB.loadProductDetail}</action>  </url-mapping>

There inside productMB (managed bean) 's loadProductDetail() , you put another redirect(..).

Something like this..

response.sendRedirect(request.getContextPath() + "/product-info");

in pretty config again..

You have to put config for above url..

<url-mapping id="product-info">    <pattern value="/product-info" />    <view-id value="/pages/product-info.jsf" /></url-mapping>

In my app, I did something like that to hide some URL.

Hope this help.

Here is my sample source code and my understanding.. I uploaded in zip file to 4shared.comhttp://www.4shared.com/zip/ctPZ4Dbj/URL_Hidding.html