Using ZK Spreadsheet JSF Component

From Documentation


Using ZK Spreadsheet JSF Component



Stop.png This article is out of date, please refer to http://books.zkoss.org/wiki/ZK_Spreadsheet_Essentials for more up to date information.


Available in ZK Spreadsheet EE only

ZK Spreadsheet can be embedded in JSF 2.0 applications much the same way as JSF native components.First specify ZK Spreadsheet component namespace URI http://www.zkoss.org/jsf/zss declaration along with other JSF namespace declarations as shown below

<html xmlns="http://www.w3.org/1999/xhtml"
   xmlns:ui="http://java.sun.com/jsf/facelets"
   xmlns:h="http://java.sun.com/jsf/html"
   xmlns:f="http://java.sun.com/jsf/core"
   xmlns:zk="http://www.zkoss.org/jsf/zss">
   .
   .
   .
   </html>

and embed ZK Spreadsheet in a JSF 2.0 facelet using spreadsheet tag as shown below

       <zk:spreadsheet src="Temiesheet1.xls" apply="${spreadsheetController}" />

ZK spreadsheet JSF component tag supports all the properties that are supported by ZK Spreasdsheet ZUL component tag. Below is another example of using some more spreadsheet component tag properties

         <zk:spreadsheet id="myspreadsheet" src="Timesheet1.xls" maxrows="100" maxcolumns="20" width="100%" height="100%" apply="${spreadsheetController}"></zk:spreadsheet>

XHTML

Let's see it in Action in the demo below.

and here is the complete source code for zsscomp.xhtml file.

<html xmlns="http://www.w3.org/1999/xhtml"
   xmlns:ui="http://java.sun.com/jsf/facelets"
   xmlns:h="http://java.sun.com/jsf/html"
   xmlns:f="http://java.sun.com/jsf/core"
   xmlns:zk="http://www.zkoss.org/jsf/zss">    
   <h:head>
        <title>ZK Spreadsheet in JSF Demo</title>
    </h:head>
    <h:body>
        <h:form>
            <h:outputText value="Cell"></h:outputText>
            <h:inputText id="cellReference" value="${myBean.cellReference}"></h:inputText>
            
            <h:commandButton id="show" value="Show" actionListener="${myBean.showCellValue}">
            	<f:ajax render="cvalue" execute="@all"></f:ajax>
            </h:commandButton>
            
            <h:outputText value="Value"></h:outputText>
            <h:inputText id="cvalue" value="${myBean.cvalue}"></h:inputText>
            
            <h:commandButton id="set" value="Set" onclick="jsf.ajax.request(this, event, {execute:'@all'}); return false;" actionListener="${myBean.setCellText}">
            </h:commandButton>
            
            <zk:spreadsheet id="myspreadsheet" src="Timesheet1.xls" maxrows="100" maxcolumns="20" width="100%" height="100%" 
                     binding="${myBean.myBeanSpreadsheet}" apply="${myBean}">
             </zk:spreadsheet>

        </h:form>
    </h:body>
 </html>

Example above has two inputText JSF components with respective outputText labels for Cell and Value. It also has three commandButton components Show, Set & Print to Pdf followed by ZK Spreadsheet JSF component.

Retrieving ZK Spreadsheet data

In the demo above I demonstrated two use cases. First use case is to get value for a specific ZK spreadsheet cell as indicated by Cell input text boxes and display it in the cvalue input textbox when Show command button is clicked. Here is the piece of code from index.xhtml that makes it work.

        ...
        <h:form>
            <h:outputText value="Cell"></h:outputText>
            <h:inputText id="cellReference" value="${myBean.cellReference}"></h:inputText>
            
            <h:commandButton id="show" value="Show" actionListener="${myBean.showCellValue}">
            	<f:ajax render="cvalue" execute="@all"></f:ajax>
            </h:commandButton>
            
            <h:outputText value="Value"></h:outputText>
            <h:inputText id="cvalue" value="${myBean.cvalue}"></h:inputText>
            ... 

        </h:form>
        ...

As you can see cellReference inputText component is value bound to cellReference property of MyBean backing bean. Clicking commandButton Show invokes backing bean method showCellValue. Another important thing to note is I have used component binding of JSF to bind ZK Spreadsheet JSF component to myBeanSpreasheet property of MyBean as shown below.

<zk:spreadsheet id="myspreadsheet" src="Timesheet1.xls" maxrows="100" maxcolumns="20" width="100%" height="100%" 
             binding="${myBean.myBeanSpreadsheet}" apply="${myBean}">
</zk:spreadsheet>

... and here is the code for MyBean method showCellValue.

public void showCellValue(ActionEvent e) {
        Range range = Ranges.range(myBeanSpreadsheet.getSpreadsheet().getSelectedSheet(), cellReference);
        FormatText ft = range.getFormatText();
        if (ft != null && ft.isCellFormatResult()) {
                setCvalue(ft.getCellFormatResult().text);
        } else {
                final RichTextString rstr = range == null ? null : range.getRichEditText();
                setCvalue(rstr != null ? rstr.getString() : "");
        }
}

So here I brief a little bit the process sequence of this use case

  1. End user enters cell reference value in cellReference input textbox.
  2. End user clicks Show commandButton which causes f:ajax to initiate an ajax request.
  3. execute="@all" causes JSF to transfer end user entered value for cellReference input textbox to cellReference properties of MyBean backing bean.
  4. actionListener for commandButton Show is invoked i.e. showCellValue method
  5. showValueCell updates backing bean property cvalue with the value of ZK Spreadsheet cell indentified by cellReference retrieved using ZK Spreadsheet APIs such as Ranges.range, Range.getFormatText etc
  6. render="cvalue" rerenders cvalue inputTextbox component and populates it with the updated cvalue backing bean property value.

Setting ZK Spreadsheet data and properties

Second use case is to set value entered in cvalue inputText component into a specific ZK spreadsheet cell as indicated by Cell input text boxes. Here is the piece of code from index.xhtml that make it work

<h:commandButton id="set" value="Set" onclick="jsf.ajax.request(this, event, {execute:'@all'}); return false;" actionListener="${myBean.setCellText}">
</h:commandButton>

Clicking commandButton Set invokes MyBean method setCellText by initiating an Ajax request using jsf.ajax.request introduced in JSF 2.0. Let's take a look at setCellText method.

public void setCellText(ActionEvent e) throws IOException {

        ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
        ServletContext svlctx = (ServletContext) ec.getContext();
        HttpServletRequest request = (HttpServletRequest) ec.getRequest();
        HttpServletResponse response = (HttpServletResponse) ec.getResponse();

        Bridge bridge = Bridge.start(svlctx, request, response,
                        myBeanSpreadsheet.getSpreadsheet().getDesktop());
        try {
                
                final Range range = Ranges.range(myBeanSpreadsheet.getSpreadsheet().getSelectedSheet(), cellReference);
                range.setEditText(cvalue);
                
                //Send back bridge.getResult() with the response writer (eval)
                PartialResponseWriter responseWriter = FacesContext.getCurrentInstance().getPartialViewContext().getPartialResponseWriter();
                responseWriter.startDocument();
                responseWriter.startEval();
                responseWriter.write(bridge.getResult());
                responseWriter.endEval();
                responseWriter.endDocument();
                responseWriter.flush();
                responseWriter.close();
        
        } finally {
                bridge.close();
        }
}

As you can see since this is an Ajax action event of JSF I initiate Bridge [1] that allows me to start a ZK execution and update ZK component(s) state. Bridge also has convenient method to retrieve javascript required to update ZK Component client side. Since this is happening in JSF Ajax channel I use JSF PartialResponseWriter to send back javascript retrieved from Bridge to update ZK Spreadsheet client side and have it evaluated at the client by JSF jsf.ajax.response.

So here I brief a little bit the process sequence of this use case

  1. End user enters cell reference value in cellReference input textbox.
  2. End user clicks Set commandButton which causes jsf.ajax.request to initiate an ajax request.
  3. {execute:'@all'} parameter to jsf.ajax.request causes JSF to transfer end user entered value for cell reference & value input textboxes to cellReference & cvalue properties of MyBean backing bean.
  4. actionListener for commandButton Set is invoked i.e. setCellText method
  5. setCellText uses Bridge to start a ZK execution and updates ZK Spread cell value. It also constructs partial response to be processed by jsf.ajax.response to update ZK Spreadsheet at the client
  6. On receiving partial response jsf.ajax.response evaluates javascript and ZK Spreadsheet cell is updated with value entered by user in cvalue inputTextbox.

In similar way i.e. using component binding of JSF developers can gain access to ZK Spreadsheet component and use Bridge & ZK Spreadsheet APIs to access/modify its data and visual properties.


  1. A new feature ZK Developer's Reference: Integeration in ZK 5.0.5 release that allows to start execution in foreign Ajax channel

View complete source of XHTML zsscomp.xhtml

View complete source of user defined bean MyBean.java

Version History

Last Update : 2013/08/22


Version Date Content
     


All source code listed in this book is at Github.


Last Update : 2013/08/22

Copyright © Potix Corporation. This article is licensed under GNU Free Documentation License.