148
WaveMaker Application Developer’s Guide VERSION 3.2

WaveMaker User Guide

Embed Size (px)

Citation preview

WaveMaker Application Developer’s Guide

VERSION 3.2

II

WaveMaker Copyright

©4/16/08 WaveMaker Software. All rights reserved. WaveMaker, WaveMaker Visual AJAX Studio, WaveMaker Studio, LiveLayout and the WaveMaker logo are trademarks of WaveMaker Software, which may be registered in some jurisdictions. WaveMaker may have copyrights, trademarks, and other intellectual property rights in and to the contents of this document. This document grants no License to such copyrights, trademarks and other intellectual property rights. All other brands and product names are trademarks or registered trademarks of their respective holders. Information supplied by WaveMaker Software is believed to be accurate and reliable. WaveMaker Software assumes no responsibility for errors in this material. WaveMaker Software reserves the right, without notice, to make changes in product design or specifications.

III

Notices

The following software may be included in WaveMaker.AcegiThe end-user documentation included with a redistribution, if any, must include the following acknowledgement: "This product includes software developed by the Acegi Security System for Spring Project (http://acegisecurity.org)." Alternately, this acknowledgement may appear in the software itself, if and wherever such third-party acknowledgements normally appear. The names "Acegi", "Acegi Security System" and "Acegi Security System for Spring" must not be used to endorse or promote products derived from this software without prior written permission. For written permission, please contact [email protected] Ant. Copyright 1999-2006 The Apache Software Foundation. This product includes software developed by The Apache Software Foundation (http://www.apache.org/). This product includes also software developed by:

• the W3C consortium (http://www.w3c.org) ,• the SAX project (http://www.saxproject.org)

The <sync> task is based on code Copyright (c) 2002, Landmark Graphics Corp that has been kindly donated to the Apache Software Foundation.Apache Commons - beanutils, collectionsThis product includes software developed by The Apache Software Foundation (http://www.apache.org/).Apache Jakarta Commons IOCopyright 2001-2007 The Apache Software Foundation. This product includes software developed by The Apache Software Foundation (http://www.apache.org/).Apache Jakarta Commons FileUploadCopyright 2002-2006 The Apache Software Foundation. This product includes software developed by The Apache Software Foundation (http://www.apache.org/).Apache Jakarta Commons LangCopyright 2001-2007 The Apache Software FoundationThis product includes software developed by The Apache Software Foundation (http://www.apache.org/). Apache Commons LoggingCopyright 2003-2007 The Apache Software Foundation. This product includes software developed by The Apache Software Foundation (http://www.apache.org/).JsonView.java The version distributed with WaveMaker is derived from the standard distribution. Source code is available at dev.wavemaker.com.Apache log4jCopyright 2007 The Apache Software Foundation. This product includes software developed at The Apache Software Foundation (http://www.apache.org/).SpringThis product includes software developed by the Apache Software Foundation (http://www.apache.org). The end-user documentation included with a redistribution, if any, must include the following acknowledgement: "This product includes software developed by the Spring Framework Project (http://www.springframework.org)." Alternatively, this acknowledgement may appear in the software itself, if and wherever such third-party acknowledgements normally appear.The names "Spring" and "Spring Framework" must not be used to endorse or promote products derived from this software without prior written permission. For written permission, please contact [email protected] or [email protected] product includes software developed by The Apache Software Foundation (http://www.apache.org/). Java Management Extensions (JMX) support is provided by the MX4J package, which is open source software. The original software and related information is available at http://mx4j.sourceforge.net.The Windows Installer is built with the Nullsoft Scriptable Install System (NSIS), which is open source software. The original software and related information is available at http://nsis.sourceforge.net.Java compilation software for JSP pages is provided by Eclipse, which is open source software. The original software and related information is available at http://www.eclipse.org.Apache XML Commons ResolverCopyright 2006 The Apache Software Foundation. This product includes software developed at The Apache Software Foundation http://www.apache.org/ . Portions of this code are derived from classes placed in the public domain by Arbortext on 10 Apr 2000. See:http://www.arbortext.com/customer_support/updates_and_technical_notes/catalogs/docs/README.htmXmlSchemaThis product includes software developed by The Apache Software Foundation (http://www.apache.org/). Please read the different LICENSE files present in the licenses directory of this distribution. Portions Copyright 2006 International Business Machines Corp.

IV

Antlr2This product includes Antlr2, http://antlr2.org/.DojoCopyright (c) 2005-2007, The Dojo Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.Neither the name of the Dojo Foundation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.HibernateThis product includes Hibernate. Source code is available at http://www.hibernate.org/.JAXBDistributed under CDDL v1 or GPL v2, a copy of these license is provided with this distribution. The version distributed with WaveMaker is derived from the standard distribution. Source code is available at dev.wavemaker.com. The standard distribution is available at https://jaxb.dev.java.net/.JAX-WSDistributed under CDDL v1 or GPL v2, a copy of these license is provided with this distribution. The standard distribution is available at https://jax-ws.dev.java.net/.JDOMThis product includes software developed by the JDOM Project (http://www.jdom.org/)." Copyright (C) 2000-2004 Jason Hunter & Brett McLaughlin. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

• Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer.• Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the disclaimer that follows

these conditions in the documentation and/or other materials provided with the distribution.• The name "JDOM" must not be used to endorse or promote products derived from this software without prior written permission.

For written permission, please contact <request_AT_jdom_DOT_org>.• Products derived from this software may not be called "JDOM", nor may "JDOM" appear in their name, without prior written

permission from the JDOM Project Management <request_AT_jdom_DOT_org>.In addition, we request (but do not require) that you include in the end-user documentation provided with the redistribution and/or in the software itself an acknowledgement equivalent to the following: "This product includes software developed by the JDOM Project (http://www.jdom.org/)." Alternatively, the acknowledgment may be graphical using the logos available at http://www.jdom.org/images/logos.THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE JDOM AUTHORS OR THE PROJECT CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.This software consists of voluntary contributions made by many individuals on behalf of the JDOM Project and was originally created by Jason Hunter <jhunter_AT_jdom_DOT_org> and Brett McLaughlin <brett_AT_jdom_DOT_org>. For more information on the JDOM Project, please see <http://www.jdom.org/>. NSISThe Windows Installer is built with the Nullsoft Scriptable Install System (NSIS), which is open source software. The original software and related information is available at http://nsis.sourceforge.net.HSQLDBCopyright (c) 1995-2000 by the Hypersonic SQL Group. All rights reserved. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.Neither the name of the Hypersonic SQL Group nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR

V

IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE HYPERSONIC SQL GROUP, OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

VI

CONTENTS

Overview. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1Installing WaveMaker Studio . . . . . . . . . . . . . . . . . . . . . . . . . . 3Building Pages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5

Getting Started With Page Design . . . . . . . . . . . . . . . . . . . . . . . 5The WaveMaker Tutorial . . . . . . . . . . . . . . . . . . . . . . . . 5The WaveMaker Studio Page Designer . . . . . . . . . . . . . . 6

Design Toolbar . . . . . . . . . . . . . . . . . . . . . . . . . . 7Palette . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7Page Builder . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10Model Tree . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11Property Editor . . . . . . . . . . . . . . . . . . . . . . . . . . 12Keyboard Shortcuts . . . . . . . . . . . . . . . . . . . . . . . 13

Designing Pages In WaveMaker . . . . . . . . . . . . . . . . . . . 14The layoutBox . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15Tying Widgets to Data and Services . . . . . . . . . . . . . . . . 15Live Layout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

Working with Widgets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17Selecting Widgets. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17Arranging Widgets within a Container (Box Property) . . . . 18Setting Widget Size . . . . . . . . . . . . . . . . . . . . . . . . . . . 19

Flex . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19Styling Widgets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20Binding Widgets to Data . . . . . . . . . . . . . . . . . . . . . . . . 21

Bind to displayValue or dataValue? . . . . . . . . . . . . 21

VIII

Binding to Expressions . . . . . . . . . . . . . . . . . . . . . 21Binding to Variables. . . . . . . . . . . . . . . . . . . . . . . 21

About Pages and Layers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21Scoping. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22Loading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22Navigation Between Pages and Layers . . . . . . . . . . . . . . 23

Whole Screen Navigation . . . . . . . . . . . . . . . . . . . 25Displaying Subpages . . . . . . . . . . . . . . . . . . . . . . 25Tab or Accordion Navigation . . . . . . . . . . . . . . . . . 26

Common Widgets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27The Accordion Widget . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27The AutoForm Widget . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28

Getting the DataSet . . . . . . . . . . . . . . . . . . . . . . . . . . . 28Using the DataOutput . . . . . . . . . . . . . . . . . . . . . . . . . . 28Using AutoForm as a “Detail” Widget . . . . . . . . . . . . . . . 29Creating SubForms . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29AutoForm Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . 29AutoForm Styles. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31

The Bevel Widget . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31Bevel Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31

The Button Widget. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31Button Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32Button Events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32

The Content Widget . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33How to Use the Content Widget . . . . . . . . . . . . . . . . . . . 33Content Widget Properties . . . . . . . . . . . . . . . . . . . . . . . 33

The DataGrid Widget . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34Steps for Creating a DataGrid . . . . . . . . . . . . . . . . . . . . 34DataGrid Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . 35Properties for DataGrid Columns . . . . . . . . . . . . . . . . . . 36Display Types and their Editor Properties . . . . . . . . . . . . 36

Default. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37Number . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37Date . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37Time . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38Date Time . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38

IX

Money . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39Link . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39RegularExpression. . . . . . . . . . . . . . . . . . . . . . . . 39Evaluation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39

DataGrid Events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40The Editor Widget . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40

Properties of the Editor Widget. . . . . . . . . . . . . . . . . . . . 40Editor Events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42Display Types and their Editor Properties . . . . . . . . . . . . 42

Text. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42Date . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43Time . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43Number . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44Currency . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44Select . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45CheckBox . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45Radio Button Groups . . . . . . . . . . . . . . . . . . . . . . 46TextArea . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46Slider. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47

Validation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47See Changes as You Type . . . . . . . . . . . . . . . . . . . . . . . 47

The Label Widget. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47Display Types and their Formatting Properties . . . . . . . . . 49

Number . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50Date . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50Time . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50Date Time . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51Money . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51Link . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51RegularExpression. . . . . . . . . . . . . . . . . . . . . . . . 52Evaluation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52

The Layers Widget . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52Types of Layers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53Layers Widget Properties. . . . . . . . . . . . . . . . . . . . . . . . 53Layers Widget Events . . . . . . . . . . . . . . . . . . . . . . . . . . 54Properties of Each Layer . . . . . . . . . . . . . . . . . . . . . . . . 55Events for Each Layer . . . . . . . . . . . . . . . . . . . . . . . . . . 56

X

The List Widget . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56List Widget Properties . . . . . . . . . . . . . . . . . . . . . . . . . . 56List Widget Events . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57

The Pane Widget . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57Pane Widget Properties . . . . . . . . . . . . . . . . . . . . . . . . . 58Pane Widget Events . . . . . . . . . . . . . . . . . . . . . . . . . . . 58

The Panel Widget. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59Panel Widget Properties . . . . . . . . . . . . . . . . . . . . . . . . 59

The Picture Widget. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60How to Add the Image . . . . . . . . . . . . . . . . . . . . . . . . . 60Picture Widget Properties . . . . . . . . . . . . . . . . . . . . . . . 60Picture Widget Events . . . . . . . . . . . . . . . . . . . . . . . . . . 61

The Spacer Widget. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61Spacer Widget Properties . . . . . . . . . . . . . . . . . . . . . . . 62

The Splitter Widget . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62Splitter Widget Properties . . . . . . . . . . . . . . . . . . . . . . . 62

The Tabs Widget . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63Working with Databases . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65

What Databases are Supported? . . . . . . . . . . . . . . . . . . . . . . . 65Importing a Database . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65

Basic Settings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67HSQLDB. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68MySQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68Oracle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68DB2. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68SQL Server. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69

Advanced Options. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69Database Objects (Tables and Queries) . . . . . . . . . . . . . . . . . . 70

Tables (Types) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70Key Generation . . . . . . . . . . . . . . . . . . . . . . . . . . 72

Database Queries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72Return Single Result . . . . . . . . . . . . . . . . . . . . . . 74Bind Parameters . . . . . . . . . . . . . . . . . . . . . . . . . 74Testing Queries. . . . . . . . . . . . . . . . . . . . . . . . . . 75

Database Service Operations . . . . . . . . . . . . . . . . . . . . . . . . . 75Viewing the Database Service and Service Operations . . . 75

XI

Database Service Operations . . . . . . . . . . . . . . . . . . . . . 76getCount . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76GetByID. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77getList . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78Insert . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78Update. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79Delete . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80

Error or Success? Handling Results from Database Service Op-erations. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80

Exporting a Data Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81Working with Services and Operations . . . . . . . . . . . . . . . . . . 83

About Services and Operations . . . . . . . . . . . . . . . . . . . . . . . . 83Calling Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83

Creating a Service Call . . . . . . . . . . . . . . . . . . . . . . . . . 84Stringing (Queueing) Service Calls . . . . . . . . . . . . . . . . . 86

Setting Up a Service Call Queue . . . . . . . . . . . . . . 86Setting Up an onResult Event . . . . . . . . . . . . . . . . 87

Service Call Properties and Events . . . . . . . . . . . . . . . . . 87Web Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88

About Web Service Types . . . . . . . . . . . . . . . . . . . . . . . 88Importing and Calling a SOAP or REST Service. . . . . . . . . 88Importing and Calling RSS Feeds . . . . . . . . . . . . . . . . . . 90

Creating the Feed Service . . . . . . . . . . . . . . . . . . 90Calling the Feed and Displaying the Results . . . . . . 91

JavaScript Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93Executing JavaScript on Widget Events . . . . . . . . . . . . . . 94Executing JavaScript on Page Loading. . . . . . . . . . . . . . . 94Executing JavaScript on Service Call Results . . . . . . . . . . 94

Java Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95Creating and Calling a Custom Java Code Service. . . . . . . 95Integrating Existing Java Code. . . . . . . . . . . . . . . . . . . 101Custom Java Service Example . . . . . . . . . . . . . . . . . . . 101

Setting up a User Login Page . . . . . . . . . . . . . . . . . . . . . . . . 105How to Set Up a Log In Page . . . . . . . . . . . . . . . . . . . . . . . . 105Using the Demo Data Source for Login Data . . . . . . . . . . . . . . 107Using a Database for Login Data . . . . . . . . . . . . . . . . . . . . . . 107

XII

Using LDAP for Login Data . . . . . . . . . . . . . . . . . . . . . . . . . . 108The Default Login Page. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108The Security Service . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109

Projects and Project Files . . . . . . . . . . . . . . . . . . . . . . . . . . 111Importing and Exporting Projects . . . . . . . . . . . . . . . . . . . . . 111

Exporting WaveMaker Projects . . . . . . . . . . . . . . . . . . . 111Importing WaveMaker Projects. . . . . . . . . . . . . . . . . . . 111

Generating a WAR File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112Enable Project Loggers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112WaveMaker Project Directory Structure . . . . . . . . . . . . . . . . . 112

Project File Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113Project File Structure . . . . . . . . . . . . . . . . . . . . . . . . . 113Service Directory Structure . . . . . . . . . . . . . . . . . . . . . 113Webapproot Directory Structure . . . . . . . . . . . . . . . . . . 114Page Container Directory Structure. . . . . . . . . . . . . . . . 115

Customizing WaveMaker Applications with JavaScript . . . . . . . 117Working with Widgets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117

Accessing a Widget in JavaScript . . . . . . . . . . . . . . . . . 118Setting Widget Properties . . . . . . . . . . . . . . . . . . . . . . 118Referencing the Calling Widget in an Event . . . . . . . . . . 119Clearing Data Input Fields in JavaScript . . . . . . . . . . . . 119Creating Widgets at Runtime . . . . . . . . . . . . . . . . . . . . 119

Executing Service Calls in Your JavaScript Code . . . . . . . . . . . 120Setting Data Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120Referencing Components at Runtime . . . . . . . . . . . . . . . . . . . 121Object Structure on the Client. . . . . . . . . . . . . . . . . . . . . . . . 121Commonly Used Utilities. . . . . . . . . . . . . . . . . . . . . . . . . . . . 122

CSS Utilities. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122The “Connect” Utility. . . . . . . . . . . . . . . . . . . . . . . . . . 123

Debugging with Firebug . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123Running WaveMaker Studio in Debug Mode . . . . . . . . . . 123Firebug Status Bar . . . . . . . . . . . . . . . . . . . . . . . . . . . 124Printing to the Firebug Console . . . . . . . . . . . . . . . . . . 124Firebug Command Line . . . . . . . . . . . . . . . . . . . . . . . . 124

Creating Custom Widgets . . . . . . . . . . . . . . . . . . . . . . . . . . 127

XIII

The Widget Module File . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128Defining Widgets . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129Widget Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130Widget Events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130

Expose the Event in the Property Editor . . . . . . . . 131Make the Event Fire. . . . . . . . . . . . . . . . . . . . . . 131

Widget Module File Location. . . . . . . . . . . . . . . . . . . . . 132Adding Studio Support for the Widget . . . . . . . . . . . . . . . . . . 132

Packages File Location . . . . . . . . . . . . . . . . . . . . . . . . 133Adding Runtime Support for the Widget . . . . . . . . . . . . . . . . . 133

lib.js File Location. . . . . . . . . . . . . . . . . . . . . . . . . . . . 134Testing the Widget. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134Dojo and WaveMaker . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134

XIV

CHAPTER 1

Overview

This guide helps you get the most out of WaveMaker Visual AJAX Studio™ (WaveMaker Studio). To learn how to create and run a simple project, it’s a good idea to start with the WaveMaker Studio Tutorial.

This guide contains the following sections:“Installing WaveMaker Studio” on page 3“Building Pages” on page 5“Common Widgets” on page 27“Working with Databases” on page 65“Working with Services and Operations” on page 83“Setting up a User Login Page” on page 105“Projects and Project Files” on page 111“Customizing WaveMaker Applications with JavaScript” on page 117“Creating Custom Widgets” on page 127

2 OVERVIEW

CHAPTER 2

Installing WaveMaker Studio

You can run WaveMaker Studio on Windows, Mac or Linux operating systems. The WaveMaker Studio installer installs WaveMaker Studio, Java (Sun JDK 1.5.0_12), and Tomcat (Apache Tomcat 5.5.23). Tomcat and JDK are required by WaveMaker Studio. The installer does not overwrite existing Java or Tomcat installations but it does create new installations. WaveMaker Studio also includes Hypersonic SQL DB (HSQLDB) as an embedded database.

To install and run WaveMaker, follow these instructions:Windows: On Windows the Tomcat application server is installed for you as a Windows serivce (called WaveMaker Server) that starts automatically. However, if you stop this service (using the Service Control Manager or the net stop WaveMakerServer command), then you must restart it manually (or reboot).Linux: On Linux you need to start Mavericks manually using the wavemaker.sh script. This script starts Tomcat and then launches Firefox. To stop Mavericks, run the shutdown.sh script.Mac: WaveMaker Studio runs on Mac OS X Leopard only. Download and open the WaveMaker.dmg file. Drag the WaveMaker icon into your Applications directory. To run WaveMaker, doubleclick the WaveMaker icon. The WaveMaker Studio Control Panel appears.Click the Start WaveMaker button to start the WaveMaker services. Wait a few seconds and then click the Launch Browser button. To stop WaveMaker, click the Stop WaveMaker button.

4 INSTALLING WAVEMAKER STUDIO

CHAPTER 3

Building Pages

“Getting Started With Page Design” on page 5“Working with Widgets” on page 17“About Pages and Layers” on page 21

Getting Started With Page DesignThis section provides you with an introduction to the WaveMaker Studio Page Designer and an overview of the basics of WaveMaker Pages. It contains the following sections:

“The WaveMaker Tutorial” on page 5“The WaveMaker Studio Page Designer” on page 6“Designing Pages In WaveMaker” on page 14“Live Layout” on page 15

The WaveMaker Tutorial

The best place to learn the basics about building pages is the WaveMaker Studio Tutorial. You can access the tutorial from the Project Dashboard as soon as you open a project in WaveMaker Studio. The tutorial walks you through the steps of creating a simple application.

6 BUILDING PAGES

The WaveMaker Studio Page Designer

The WaveMaker Studio Page Designer is where you build your application pages. To see the Page Designer, click the Design tab at the top left of the WaveMaker Studio screen. Here you select and configure the widgets that define your page, as well as the services and data that these widgets are tied to.

This section explains the following components of the Page Designer:

GETTING STARTED WITH PAGE DESIGN 7

“Design Toolbar” on page 7“Palette” on page 7“Page Builder” on page 10“Model Tree” on page 11“Property Editor” on page 12“Keyboard Shortcuts” on page 13

Design Toolbar

This toolbar provides buttons for common Page Designer functions. The toolbar contains the following buttons:

Palette

Located along the left side of the Page Designer, the Palette displays the various types of elements that you can add to your application, such as widgets, gadgets and subpages. To build your pages, drag items from the Palette and drop them in the Page Builder.

New Page. Create a new page.

Save Page As. Copy a page to a different page name. The copied page is automatically included in the current project.

Toggle Outlined View. The outline toggle button allows you to see your page without the widget outlines (the run-time look, rather than the design-time look). You typically work with the outlines on, then toggle them off to see what the page would look like at run time.

Toggle Exploded View. The exploded view puts a bit of padding between all the widgets so that they are easy to select. You can toggle it off and on with this button. The exploded view can obscure widget alignment, so use it only when you need it.

Cut. Cut the selected widget. You can then paste the widget into another panel or page.

Copy. Copy the selected widget. You can then paste the widget into another panel or page.

Paste. Paste a widget that you have copied or cut.

Delete. Delete the selected widget or component.

8 BUILDING PAGES

The Palette is organized into logical groups of elements, which are displayed in Accordion boxes. To see what elements are in a particular Accordion box, click on the heading.

GETTING STARTED WITH PAGE DESIGN 9

WaveMaker provides a large set of page elements and groups, but these are ultimately configurable. You can add your own widgets and gadgets (“Creating Custom Widgets” on page 127). By default, the Palette contains the following element groups:

Common: The top group, called “Common” contains commonly-used page widgets. All the widgets in the Common group are described in “Common Widgets” on page 27. All the widgets in the “Common” group are also included in their logical groups, such as “Form Elements” or “Controls”.Form Elements: This group contains elements that you would typically use to create forms. Elements include the AutoForm widget as well as editors pre-configured for currency, date, numbers and so on.Containers and Layout: This group contains elements for page layout. It includes Panels, Spacers, Tabs and so on.Controls: This group contains controls such as a progress bar, a calendar and a tree control.Web Content: This group contains web gadgets, such as a stock gadget, a weather gadget and a YouTube gadget.Static Content: This group contains “static” content, such as a picture widget and a label widget.Custom: This group contains an example custom widget. This is where your own custom widgets would also be placed (“Creating Custom Widgets” on page 127).

10 BUILDING PAGES

Pages: This group contains all your project pages other than the one currently displayed in the Page Builder. You can drag a page into the Page Builder to create a sub-page (“Displaying Subpages” on page 25).

Page Builder

The large area in the center of the Page Designer represents the page itself. The top container is called the layoutBox widget. It cannot be removed. Drag widgets from the Palette to add them to the page.

In the Page Builder, the outline of the selected widget is highlighted in blue. The name of the selected widget appears in the lower left corner of the Page Builder and the size of the widget (in pixels) is listed to the right of the name.

In the Page Builder, you can display the content with or without outlines and with or without padding:

GETTING STARTED WITH PAGE DESIGN 11

Outlined View. The outline view allows you to see your page without the widget outlines (the run-time look, rather than the design-time look). You typically work with the outlines on, then toggle them off to see what the page would look like at run time.Exploded View. The exploded view puts a bit of padding between all the widgets so that they are easy to select. You can toggle it off and on with this button. The exploded view can obscure widget alignment, so use it only when you need it.

The Design Toolbar includes buttons for toggling the Outlined view and the Exploded view (“Design Toolbar” on page 7).

Model Tree

The Model Tree is located on the upper right side of the Page Designer.

The Model Tree has the following three tabs: The Widgets tab shows a hierarchical tree of all the widgets in the current page. When you select a widget in this tree, that widget is also selected in the Page Builder. The Components tab shows the components available to your page. The types of components are service calls, navigation components and variables. Each type of component is represented by its own icon. To add a new component, click the appropriate icon at the top of the components tab:

12 BUILDING PAGES

In the component tree, you can create each component either at the Page level or at the Project level (“Scoping” on page 22). Click on a component to see its properties in the Property Editor.

The Pages tab shows all the pages in the current project. Double-click on a page in the list to open that page in the Page Designer.

Property Editor

The Property editor is located on the lower right of the Page Designer. The Property Editor has three tabs:

Properties: The Properties tab displays the properties of the selected widget or component. Different items have different properties.

Variable. Create variables to hold data that you can bind to service calls or widgets. You can scope a variable at either the Page or the Project level (“Scoping” on page 22).

Service Call. A Service Call is a way for a WaveMaker application to invoke an action, such as a database query, navigation from one page to another or a custom Java method (“Creating a Service Call” on page 84).

Navigation. An application component that loads a particular Layer or Page (“Navigation Between Pages and Layers” on page 23). In the case of pages, the Navigation component also stores information about where to display the page.

GETTING STARTED WITH PAGE DESIGN 13

Events: The Events tab shows all the events for the selected object, if there are any.Styles: The Styles tab allows you to define styles for the selected object. The Styles tab provides two different ways to define styles. You can select pre-existing classes, to define such things as font, font size, color and so on. Or you can click the Custom Styles heading and type in your own custom CSS. For more on either method, see “Styling Widgets” on page 20.

Keyboard Shortcuts

You can use the following keyboard shortcuts in the Page Designer.

14 BUILDING PAGES

Designing Pages In WaveMaker

This section gives a brief overview of how to design a page in the Page Designer. To design a page in WaveMaker, you arrange widgets (from the Palette) in the Page Builder. Widgets are the building blocks of your pages. The Palette provides many different types of widgets, such as text editors, grids, containers, pictures and so on. Once you drop a widget into the Page Builder, you can drag it around as you like.

To get a widget onto the page, drag it from the Palette and drop it where you want it. The Page Builder always contains a special widget called the layoutBox (“The layoutBox” on page 15). The layoutBox holds all the other widgets that you drop into the Page Builder. You cannot delete the layoutBox or drag a new one into the Page Builder, but you can set some properties to configure it.

Shortcut Description

<Ctrl> V Paste copied widget

<Ctrl> C Copy selected widget

<Ctrl> S Save

<Ctrl> F Change sizeUnits property of selected widget to flex

<Ctrl> B Toggle value of selected widget’s box property

<Esc> Switch focus to the parent widget of the currently-selected widget.

<Shift> To force a widget into one of its child containers, hold the <Shift> key while dragging the widget.

GETTING STARTED WITH PAGE DESIGN 15

Many widgets can be used as containers for other widgets, so you can nest them one inside the other. The panel widget (“The Panel Widget” on page 59) is a generic container widget that it very useful in structuring widgets on a page.

You can set up the panel widget to arrange its contents vertically or horizontally (“Arranging Widgets within a Container (Box Property)” on page 18). You can also use spacer widgets to adjust the spacing between widgets (“The Spacer Widget” on page 61).

Each widget has its own set of properties that define how it looks and how it behaves. For descriptions of the most common widgets and their properties, see “Common Widgets” on page 27.

For more on using widgets on your page, see “Working with Widgets” on page 17.

The layoutBox

The layoutBox is the top container for each page. Each page has one and only one layoutBox and you cannot drag a new layoutBox onto the page from the Palette.

You can apply padding, margins, backgrounds and other styling to the layoutBox, just as you would to any other container widget. Like other containers, the layoutBox has a box property which you can set to display the contents either horizontally or vertically.

Tying Widgets to Data and Services

As you build your page, you are going to want to tie specific widgets to data and services in your application. For example, you might want to tie a DataGrid widget to a table in a database.

In WaveMaker Studio, to set up this connection between a widget and a source of data, you use the widget’s binding property (“Binding Widgets to Data” on page 21). Note that before you can set up a binding, you must first import the database (“Importing a Database” on page 65) or service (“About Services and Operations” on page 83) that you are using.

Live Layout

WaveMaker Studio’s LiveLayout™ feature allows you to see live data in the Page Designer as you are working with your pages. You can also execute queries in the Query Editor. This allows you to dynamically test run pieces of the application as you assemble it, rather than having to run the whole application.

16 BUILDING PAGES

The following figure shows a page in the Page Builder. This page has a search field and search button, a DataGrid widget that shows the results of the search, and an AutoForm widget that shows details about whatever record is selected in the grid. Notice that this example page shows data in the Page Builder.

If you click a different record in the DataGrid, the AutoForm widget updates to show the new record. LiveLayout allows you to do all this right in the Page Builder, without having to stop and run the application.

Here’s a an example of you would set up the page shown above to use LiveLayout:

WORKING WITH WIDGETS 17

1. In order for Live Layout to work, you must first import your database (“Importing a Database” on page 65). If you haven’t already imported a database, do that first.

2. At the top right of WaveMaker Studio, in the Project tabs, click the Live Layout button.

3. Select the Editor widget in the Page Designer.

4. On the Properties tab, under “Editing” type in the following value for the displayValue property:a

5. In the Page Designer select the DataGrid widget.

6. On the Properties tab, under “Other”, click the updateNow button.

7. In the Page Designer select the AutoForm widget.

8. On the Properties tab, under “Other”, click the updateNow button.

LiveLayout now shows you live data right in the Page Designer. Try clicking different records in your DataGrid. The AutoForm widget automatically updates to show you the new data.

Working with WidgetsThis section covers some basic information for working with widgets:

“Selecting Widgets” on page 17“Setting Widget Size” on page 19“Styling Widgets” on page 20“Binding Widgets to Data” on page 21

For descriptions of common predefined widgets, see “Common Widgets” on page 27. For information on creating your own custom widgets, see “Creating Custom Widgets” on page 127.

Selecting Widgets

If you have trouble selecting a widget in the Page Builder area, select it in the Model Tree.

18 BUILDING PAGES

When you select a widget in the Model Tree, it is automatically selected in the Page Builder.

Arranging Widgets within a Container (Box Property)

Most widgets that can act as containers (the Panel widget, for example) have a property called the box property. The box property determines how the contents of the panel are laid out. For example, if the box property is set to Left-to-Right, then the contents of the panel are arranged horizontally, expanding vertically to the full height of the panel. In the following illustration, the outer Panel has the box property set to Left-to-Right.

You can size each child element horizontally, but not vertically. Vertically each element takes up the full height available in the panel. To make a child element shorter than the other child elements, you would need to nest it in another Panel:

WORKING WITH WIDGETS 19

However, if the box property is set to Top-to-Bottom then the contents are arranged vertically. In this case, each child element expands to fill the full width of the parent Panel.

Setting Widget Size

For widgets in Top-to-Bottom or Left-to-Right containers, only one dimension is editable (the other dimension is controlled by the container).You have two basic ways to size a widget:

Click and drag to resize a widget with the mouse. If you resize a widget this way, the sizeUnits are automatically changed to pixels (px).Use the size and SizeUnits properties to set the widget size.

Size defines the size of the widget in the editable dimension, so it corresponds to width or height depending on context.

SizeUnits are the units of measurement for the Size value. SizeUnits can be expressed in pixels (px), Ems (em), points (pt), or flex values (“Flex” on page 19). Ems are nearly ideal since the screen-size of an 'em' is proportional to the current font. In other words, if the user has adjusted his font size, objects measured in ems automatically adapt.

Flex

When you set a widget’s sizeUnits property to flex, the widget takes up a proportion of the available space in the container. The proportion depends on the value of the size property. If you have two widgets, such as spacers, both with sizeUnits set to flex and size set to one, then they will take up equal amounts of any available space in the parent widget.

20 BUILDING PAGES

Flex values work as a ratio, so if one widget has a flex of 1 and another a flex of 4, the first one will be four times bigger than the second.

NOTE: Note that widgets that have a non-zero flex, cannot be manually sized because they are automatically sized.

Styling Widgets

Each Widget can be styled by selecting the Styles tab in the Property Editor. The Styles tab offers you two ways to style the widget: you can use Classes or Custom Styles:

Classes: To use classes, click to expand the Classes accordion box. Here are predefined classes for displaying each widget. Just click the values you want to use.Custom Styles: To define custom styles, click to expand the Custom Styles accordion box. Here you can type in any valid CSS. For example, you can set values for padding, margins, height and width, background color, font size, and so on. Here are a few simple examples of CSS that you might type directly into this box:padding: 0 200px;margin: 10px;width: 75%;"background-color: grey; color: white;

Another possibility is to use the Content widget. You can paste your own custom CSS into your project (in the Source > Markup sub-tab) and then apply styles from that directly to your Content Widget (“The Content Widget” on page 33).

ABOUT PAGES AND LAYERS 21

Binding Widgets to Data

You can bind widgets to data or service calls, using the binding property. When you click the binding property button, the Binding dialog appears:

Under “Bind Targets” select the item you want to bind.Under “Bind Sources”, select the object to which you want to bind it. This could be an item in a list, the results of a service call, an expression, and so on.

Bind to displayValue or dataValue?

In the Binding dialogs, you can choose bind to an editor’s displayValue or its dataValue. In many cases displayValue and dataValue are the same. They are different for widgets that display a value differently from the way it is stored in the underlying data.

The most common case in which the two values are different is for dates and times: displayValue is the readable string (1/02/08) whereas the dataValue is the date in milliseconds that is expected by a service.

It is usually best practice to bind to the dataValue. However, when you are binding to another UI element, such as a label, you sometimes need to bind to the displayValue. Setting either the displayValue or dataValue updates the other property.

Binding to Expressions

To bind to an expression, click the Expression tab in the “Bind Sources” side of the Binding dialog. Type and/or build your expression in the Data Expression area. You can select from the Bind Sources list here as well.

NOTE: By default expressions are considered strings. To have an expression evaluated as a number, begin it with %%. So you'd do %%1.

Binding to Variables

You can bind to variables just as you would any other data object. A Variable has a type, so you'd only want to bind that to something that accepts the type. If your Variable is an Actor, for example, you could bind the Actor's lastName to an input's inputValue or a label's content, since these things are strings. We don't currently do type checking.

About Pages and LayersWhen we talk about “designing a page” in WaveMaker Studio, we’re talking about arranging and configuring a group of widgets that we want to present to the user as a unit and that is addressable. Addressable means

22 BUILDING PAGES

that you can make service calls that “show” this group of widgets to a user. (An example of a widget grouping that is not addressable is a panel widget. You can not make a service call to display a particular panel.)

To define an addressable group of widgets, you can use “pages” but you can also use “layers. WaveMaker Studio uses the Ajax concept that an application consists not of discrete web pages, but of pages and layers. Both pages and layers are essentially just mechanisms for grouping content and services that you want to present to your users as a unit and that you want to be able to call from a service:

Page: A unit of application development in studio. Pages have local scope. They appear in the Dashboard and are accessible on the Design Tab. Once you create a page, it is accessible as a subpage in the Pages section of the Palette.Layer: A widget that allows for multiple widgets to occupy the same area of the screen, in a navigable way. Tabs and Accordion widgets are layers. Layers have no local scope. The widgets they contain are actually part of the containing page scope.

So how do you know when to use a Page and when to use a Layer? The first thing to remember is that there is no wrong answer. The main differences between the two for an application developer are “Scoping” on page 22 and “Loading” on page 22.

Scoping

The main difference between pages and layers is one of scope. Things scoped at the page level are accessible only on that page. Widgets are scoped to the page they are on.

When you use a Layers widget and set up multiple layers, then all the widgets on each layer are available on all the other layers. Similarly, all the service calls you’ve defined on that page are available on every other layer. In places where you need a lot of interactivity between widgets, it’s probably more convenient to use layers rather than pages.

Service calls and variables can all be scoped either at the project level or at the page level. If you scope a service call or variable the page level, it is accessible only on that page.

Loading

Another difference between pages and layers is how they are loaded in the application. To display a new page, the client asks the server for the content and the server sends it back. A whole new page is loaded, refreshing the state and destroying the existing context.

ABOUT PAGES AND LAYERS 23

However, a single page can contain multiple layers which can be dynamically revealed or hidden. To show a different layer, you don’t need to get it from the server because the client already has it.

Navigation Between Pages and Layers

The most common way to set up navigation between pages and layers is to create a “Navigation Component”. A Navigation component is an application component that loads a particular layer or page. In the case of pages, the Navigation component also stores information about where to display the page.

Once you create the Navigation component, you call it just like a service call or any other application component. You create a Navigation component in the Components section of the Model Tree, by clicking the New Navigation icon.

24 BUILDING PAGES

This launches the “Configure Navigation” screen. On this screen you choose whether you want to navigate to a layer or a page:

Layer: If you choose the Layer radio button, a drop-down menu containing all the layers on the current page is enabled. Select a layer from this menu.

Page: If you choose the Page radio button, a drop-down menu containing all the pages in the application is enabled. Select a page from this menu and then choose how you want to display the page.To display a page, you can choose either to use the entire screen, replacing everything in the browser or you can choose to display the page in an existing pane widget.

ABOUT PAGES AND LAYERS 25

When you’ve made all your configuration selections, click the Save button. The new Navigation component now appears in the Components list in the Model Tree and you can call it as you would any other component. For example, you can select the navigation component as the value for a button’s onclick event.

Whole Screen Navigation

If you want to set up a page to display in the whole browser, set up a Navigation component that displays a page and choose the Whole Screen option. When your navigation component is triggered, the page you selected appears in the browser. Note that:

When the page is loaded, you lose any existing contextIf the page you load has no navigation options, then the user’s can’t get back to where they were. This might or might not be what you want.

Displaying Subpages

The easiest way to display a subpage is to drag it from the “Pages” section of the Palette and place it where you want it. If you have more than one page in your project, then all the pages in the project effectively become widgets and appear in this section of the Palette.

When you drag a page from the Palette and drop it in the Page Builder, you are creating a subpage. The subpage is automatically contained in a pane widget (“The Pane Widget” on page 57). A pane widget is just a container for a page.

The important thing to know about pane widgets is that they are targettable. This means that every pane widget in your application is a

26 BUILDING PAGES

location where you can place a page. When you create a new Navigation component, then all the panes in your project are listed as areas where you can choose to display a page.

As we’ve said, the WaveMaker Studio automatically creates a pane for you when you drag a page from the Palette and drop it in the Page Builder. However, you are also free to drag a Pane widget from the Palette directly. See the section on Pane widgets for more information (“The Pane Widget” on page 57).

Tab or Accordion Navigation

To set up tab or accordion navigation, you typically use layers, rather than pages. For more information, see “The Layers Widget” on page 52.

CHAPTER 4

Common Widgets

This section describes the most commonly used widgets and helps you configure them. This section covers all the widgets in the “Common” section of the Palette.

“The Accordion Widget” on page 27“The AutoForm Widget” on page 28“The Bevel Widget” on page 31“The Button Widget” on page 31“The Content Widget” on page 33“The DataGrid Widget” on page 34“The Editor Widget” on page 40“The Label Widget” on page 47“The Layers Widget” on page 52“The List Widget” on page 56“The Pane Widget” on page 57“The Panel Widget” on page 59“The Picture Widget” on page 60“The Spacer Widget” on page 61“The Splitter Widget” on page 62“The Tabs Widget” on page 63

The Accordion WidgetThe Accordion widget is a Layers widget (“The Layers Widget” on page 52) for adding accordion layers. If you decide you don’t want to use accordion layers, you can easily switch to another style of layer by changing the layersType property.

28 COMMON WIDGETS

The AutoForm WidgetThe AutoForm widget is a widget for displaying, inputting or updating a record. The AutoForm widget has an associated DataSet object that represents its data source. It also has a DataOutput object, which you can use to get the data out of the AutoForm.

When you define the DataSet (“Getting the DataSet” on page 28), the AutoForm widget automatically generates Editor widgets for every item in the DataSet (except lists and substructures). The binding on these Editor widgets is already done for you, so this can save you a huge amount of time.

The Editor widgets that AutoForm generates for you are ordinary Editor widgets. You can configure them as you would any other widget and you are free to delete them.

The AutoForm widget is a type of Panel widget. This means that AutoForm can act as a container for other widgets. Just drop them in the AutoForm widget. If you drop an AutoForm widget into another AutoForm widget, you can use the child widget as a SubForm (“Creating SubForms” on page 29).

To use the AutoForm widget to insert or update records, you bind its dataOutput to an appropriate service call (“Using the DataOutput” on page 28).

For a complete list of AutoForm widget properties, see “AutoForm Properties” on page 29.

Getting the DataSet

Like the DataGrid and List widgets, the AutoForm widget has an associated DataSet that defines the source of the data. You can bind this DataSet in the usual way, through the binding property, but AutoForm also provides a “shortcut” with its special dataSetName property.

The dataSetName property is a simple drop-down menu that contains all the objects that are available as the DataSet for this AutoForm. To define the DataSet, simply select an item from the dataSetName property menu. The dataSetName menu includes: service calls, variables, “selected item” in DataGrids and Lists.

Using the DataOutput

In addition to a DataSet object, each AutoForm widget has an associated DataOutput object. The DataOutput object contains all the values (dataValue, rather than displayValue) of all the Editor widgets in the AutoForm that are bound to the DataSet.

THE AUTOFORM WIDGET 29

The DataOutput is available as a binding source, so you can use it as an input to a database service call or in any other way you choose.

Using AutoForm as a “Detail” Widget

Previous versions of WaveMaker Studio provided a “Detail” widget that displayed information about a data object. AutoForm provides all the functionality of the Detail widget and more.

To use the AutoForm widget as a Detail widget, check the readonly property in the “Display” section of the Property Editor. This changes all the Editors from inputs to outputs.

Creating SubForms

The AutoForm widget does not generate Editor widgets for lists and substructures in the DataSet. However, you can easily create a subform, by dragging one AutoForm widget into another. When you do this, the dataSetName property for the second (child) AutoForm contains a list of lists and substructures from the first (parent AutoForm. Thus you can very quickly and easily create a SubForm.

AutoForm Properties

AutoForm Common Propertiesname: the name that WaveMaker Studio uses to reference the widget. This is the name that appears in Model Tree, in the Page Builder, in binding dialogs, and so on; this is also the name you use to reference the widget in code services.binding: defines the DataSet (input data source). Clicking the binding property launches a dialog for defining this DataSet. Alternatively, you can choose a DataSet from the dataSetName property menu.showing: when checked (true), the AutoForm widget is visible to users; when unchecked (false), the widget is hidden.dataSetName: a drop-down menu of obects that you can choose to use as the DataSet (data source) for this AutoForm widget. You can alternatively define a DataSet using the dialog launched by the binding property.

AutoForm Display Propertiesreadonly: if checked (true), the Editor widgets in the AutoForm are displayed as output, rather than input, fields. The AutoForm displays as a Detail widget. If unchecked (false), the Editor widgets are input fields and the users can input their own values.

30 COMMON WIDGETS

editorSize: specifies the size of the Editor widgets in the AutoForm. You first need to specify the units of size, which you do by setting the editorSizeUnits property. The editorSize property sets a default size for all the Editor widgets in this AutoForm; you can still size each Editor widget individually. editorSizeUnits: specifies the units in which the editorSize property is measured. The default value is flex. Choices are:∞ px: pixels∞ em: text size; adapts automatically to current screen size∞ pt: point (1/72 inch)∞ flex: stretches widget to fill up proportional area of available space

(see “Setting Widget Size” on page 19)captionSize: specifies the size of the caption in each Editor widget. The caption is the “label” on the widget, the text that the user sees. The value of the caption is specified by the caption property. Before you can set the captionSize, you first need to specify the units of size, which you do by setting the captionUnits property.captionUnits: specifies the units in which the captionSize property is measured. The default value is flex.captionAlign: specifies the horizontal alignment of the caption in each Editor widget. The alignment is relative to the entire available caption area, rather than the entire area of the Editor widget. Possible values are: Right, Left, and Center.captionPosition: specifies the vertical alignment of the caption in each Editor widget. The position is relative to the Editor input (or output) field. Possible values are: Top, Bottom, Left and Right.

AutoForm Layout Propertieslock: if checked (true), you cannot add or remove widgets to this container widget.autosize: if checked (true) this property sizes the widget so that it is just big enough for its contents and no bigger. If unchecked (false) the size of the widget is determined by the size property.size: specifies the size of the AutoForm widget. Before you can set the size, you first need to specify the units of size, which you do by setting the sizeUnits property. If the autosize property is checked (true) then the size property cannot be set.sizeUnits: specifies the units in which the size property is measured. If the autosize property is checked (true) then the sizeUnits property cannot be set. Default value is flex. Choices are:∞ px: pixels∞ em: text size; adapts automatically to current screen size

THE BEVEL WIDGET 31

∞ pt: point (1/72 inch)∞ flex: stretches widget to fill up proportional area of available space

(see “Setting Widget Size” on page 19)box: the alignment of the child widgets (any widgets inside the AutoForm widget). Values are Top-to-Bottom or Left-to-Right. See the “Arranging Widgets within a Container (Box Property)” on page 18 for more information on the box property.

AutoForm Operations PropertiesautoEditors: automatically add editors based on dataclearEditors: clear data from editorsdeleteEditors: remove all editors from AutoFormclearForm: remove all widgets from AutoForm

AutoForm Styles

AutoForm styles affect both the labels and the data. To change just the labels or just the data, you need to use custom styles.

The Bevel WidgetThe Bevel widget is a simple divider bar that provides visual separation of elements on a Page. Similar to a Splitter (“The Splitter Widget” on page 62), but does not allow resizing of adjacent areas.

Bevel Propertiesname: the name that WaveMaker Studio uses to reference the widget. This is the name that appears in Model Tree, in the Page Builder, in binding dialogs, and so on; this is also the name you use to reference the widget in code services.binding: not used with the Bevel widgetshowing: when checked (true), the widget is visible to users; when unchecked (false), the widget is hidden.

The Button WidgetThe button widget creates a button. You can configure the button using its properties and you can change the appearance using styles (“Styling Widgets” on page 20).

“Button Properties” on page 32“Button Events” on page 32

32 COMMON WIDGETS

Button Properties

The Button widget has the following properties:

Common Propertiesname: the name that WaveMaker Studio uses to reference the widget. This is the name that appears in Model Tree, in the Page Builder, in binding dialogs, and so on; this is also the name you use to reference the widget in code services.binding: use to dynamically set the value of the caption property or the disabled property.showing: when checked (true), the widget is visible to users; when unchecked (false), the widget is hidden.disabled: when checked (true) the widget can take no inputs.

Display Propertiescaption: the caption is the “label” on the widget, the text that the user sees.hint: text displayed when the cursor hovers over the button

Layout Propertiesautosize: if checked (true) this property sizes the widget so that it is just big enough for its contents and no bigger. If unchecked (false) the size of the widget is determined by the size property.size: specifies the size of the widget. Before you can set the size, you first need to specify the units of size, which you do by setting the sizeUnits property. If the autosize property is checked (true) then the size property cannot be set.sizeUnits: specifies the units in which the size property is measured. If the autosize property is checked (true) then the sizeUnits property cannot be set. Default value is px. Choices are:∞ px: pixels∞ em: text size; adapts automatically to current screen size∞ pt: point (1/72 inch)∞ flex: stretches widget to fill up proportional area of available space

(see “Setting Widget Size” on page 19)

Button Events

The Button widget provides a single event, the onclick event. This event fires when a user clicks on the button.

THE CONTENT WIDGET 33

The Content WidgetContent widgets allow you to easily use your own static markup. The WaveMaker Tutorial includes an example of how to use a Content widget.

How to Use the Content Widget

To add markup to a content widget, follow these steps:

1. Open your project.

2. In the Page Designer, drag a Content widget from the Palette onto the page.

3. Click the Source tab along the top of the Page Designer. Several sub-tabs appear.

4. Click the tab labeled Markup. Delete the single line of sample markup in the text area here.

5. Paste the text from your own CSS markup file into the text area under the Markup tab in the WaveMaker Studio.

6. Save the project.

7. Click on the Design tab to bring up the Page Designer again.

8. Select your Content widget.

9. In the Property Editor, under the “Other” section, find the property called content. The pull-down menu for this property now contains the IDs in the markup you just added. Select the appropriate ID from the pull-down menu.

10.Save the project.

Content Widget Properties

The Panel widget has the following properties:

Common Propertiesname: the name that WaveMaker Studio uses to reference the widget. This is the name that appears in Model Tree, in the Page Builder, in binding dialogs, and so on; this is also the name you use to reference the widget in code services.binding: use to dynamically set the value of the disabled property.showing: when checked (true), the widget is visible to users; when unchecked (false), the widget is hidden.disabled: when checked (true) the widget can take no inputs.

Layout Properties

34 COMMON WIDGETS

autosize: if checked (true) this property sizes the widget so that it is just big enough for its contents and no bigger. If unchecked (false) the size of the widget is determined by the size property.size: specifies the size of the widget. Before you can set the size, you first need to specify the units of size, which you do by setting the sizeUnits property. If the autosize property is checked (true) then the size property cannot be set.sizeUnits: specifies the units in which the size property is measured. If the autosize property is checked (true) then the sizeUnits property cannot be set. Default value is px. Choices are:∞ px: pixels∞ em: text size; adapts automatically to current screen size∞ pt: point (1/72 inch)∞ flex: stretches widget to fill up proportional area of available space

(see “Setting Widget Size” on page 19)

Other Propertiescontent: a drop-down menu showing <div> names from the Markup source. Paste your own content into the Markup to define options in this menu. See “How to Use the Content Widget” on page 33 for more details.

The DataGrid WidgetThe DataGrid widget is a highly-configurable widget for displaying lists. DataGrid columns are sortable and sizeable by users. Each column in the DataGrid has its own properties that you can use to configure that column:

“Steps for Creating a DataGrid” on page 34“DataGrid Properties” on page 35“DataGrid Events” on page 40“Properties for DataGrid Columns” on page 36

Steps for Creating a DataGrid

To use the DataGrid, follow these steps:

1. Drag a DataGrid widget onto the Page.

2. Click the binding property. The Binding dialog appears.

3. Under “Bind Targets” select the dataSet item in the DataGrid.

4. Under “Bind Sources”, select the object to which you are binding the grid. The object must represent a list. Typically, you will use a service call.

THE DATAGRID WIDGET 35

5. Add the columns. You can click autoColumns to have them built for you, or you can add columns manually by clicking the addColumn operation.

6. Use a column’s field property to specify a specific field from the Grid binding for that column to display.

7. To size the columns, you can either click autoSize or use the columnWidth property to specify a precise width.

DataGrid Properties

The DataGrid widget has the following properties:

Common Propertiesname: the name that WaveMaker Studio uses to reference the widget. This is the name that appears in Model Tree, in the Page Builder, in binding dialogs, and so on; this is also the name you use to reference the widget in code services.

binding: defines the input dataSet for this DataGrid. The dataSet must be a list. Clicking the binding property launches a dialog for defining this input source (“Tying Widgets to Data and Services” on page 15). showing: when checked (true), the widget is visible to users; when unchecked (false), the widget is hidden.

Layout Propertiessize: specifies the size of the widget. Before you can set the size, you first need to specify the units of size, which you do by setting the sizeUnits property. sizeUnits: specifies the units in which the size property is measured. If the autosize property is checked (true) then the sizeUnits property cannot be set. Default value is flex. Choices are:∞ px: pixels∞ em: text size; adapts automatically to current screen size∞ pt: point (1/72 inch)∞ flex: stretches widget to fill up proportional area of available space

(see “Setting Widget Size” on page 19)

DataGrid Operation Properties

The DataGrid provides the following operations for configuring the grid:addColumn: allows you to manually add columns one at a timeautoColumns: adds a column for each type returned so you don’t have do it manuallyclearColumns: removes all columns from the grid

36 COMMON WIDGETS

updateNow: updates the grid with live data from the service call while in design mode—no need to test run to see the data

Properties for DataGrid Columns

Each column in the DataGrid has its own properties that you can use to configure that column:

name: the name that WaveMaker Studio uses to reference the widget. This is the name that appears in Model Tree, in the Page Builder, in binding dialogs, and so on; this is also the name you use to reference the widget in code services.caption: specifies the column heading that is displayed to the user.

Layout PropertiesautoSize: if checked (true) this property sizes the widget so that it is just big enough for its contents and no bigger. If unchecked (false) the size of the widget is determined by the size property.columnWidth: width of the column as a percentage of the total width of the gridindex: order in which the columns are displayed in the grid. Change the index to move columns left or right

Data Propertiesfield: select the field you want displayed in the columndisplay: defines the type of format (number, money, date, and so on. ) See the “Display Types and their Editor Properties” on page 42.format: opens the details property for configuring the format. See the “Display Types and their Editor Properties” on page 42.

Columns Operation Properties

The DataGrid columns provide the following operations for configuring the grid:

addColumn: adds a new column to the end of the Grid. Use the index property to move the colmn left or rightremoveColumn: removes the currently selected column

Display Types and their Editor Properties

Each DataGrid column has a display property. Set the display property to define the type of data you’re displaying in the column. Once you set the display property, click the format property to further configure the column. The configuration options depend on the display type. In the list of format properties, click back to get back to the main properties. Possible values for the display property are described in the following sections:

THE DATAGRID WIDGET 37

“Default” on page 37“Number” on page 37“Date” on page 37“Time” on page 38“Date Time” on page 38“Money” on page 39“Link” on page 39“RegularExpression” on page 39“Evaluation” on page 39

Default

Use to display text. No format properties are available for the default display.

Number

Use to display numbers. The digits format property determines the number of decimal places that are displayed in the label.

The locale format property represents language code, used for i18n. Based on locale setting, different data may be displayed. Possible values are:nls, de, en, n-au, en-ca, en-gb, es, es-es, fr, it, it-it, js, ko, ko-kr, pt, pt-br, zh, zh-cn

The round format property can be used to specify that the amount be rounded rather than truncated.

Date

Use to display dates.

The datePattern format property determines the format of the date. For example:

MMM-dd-yyy

The formatLength format property determines the style of the displayed date:

short - 12/15/2007 medium – Dec 15, 2007long – December 15, 2007full – Saturday, December 15, 2007

The locale format property represents language code, used for i18n. Based on locale setting, different data may be displayed. Possible values are:nls,

38 COMMON WIDGETS

de, en, n-au, en-ca, en-gb, es, es-es, fr, it, it-it, js, ko, ko-kr, pt, pt-br, zh, zh-cn

Time

Use to display times.

The timePattern format property determines the format of the date. For example:

HH:mm

The formatLength format property determines the style of the displayed time:

short - 4:00 PM medium – 4:00:00 PMlong – 4:00:00 PM Pacific Standard Timefull – 4:00:00 PM Pacific Standard Time

The locale format property represents language code, used for i18n. Based on locale setting, different data may be displayed. Possible values are:nls, de, en, n-au, en-ca, en-gb, es, es-es, fr, it, it-it, js, ko, ko-kr, pt, pt-br, zh, zh-cn

Date Time

Use to display date and time.

The datePattern format property determines the format of the date. For example:

MMM-dd-yyy

The timePattern format property determines the format of the date. For example:

HH:mm

The formatLength format property determines the style of the displayed date-time:

short - 12/15/2007 4:00 PM medium – Dec 15, 2007 4:00:00:00 PMlong – December 15, 20074:00:00 PM Pacific Standard Timefull – Saturday, December 15, 2007 4:00:00 PM Pacific Standard Time

The locale format property represents language code, used for i18n. Based on locale setting, different data may be displayed. Possible values are:nls, de, en, n-au, en-ca, en-gb, es, es-es, fr, it, it-it, js, ko, ko-kr, pt, pt-br, zh, zh-cn

THE DATAGRID WIDGET 39

Money

Use to display money.

The currency format property specifies the symbol to display before amount.

The digits format property determines the number of decimal places that are displayed.

The round format property can be used to specify that the amount be rounded rather than truncated.

The locale format property represents language code, used for i18n. Based on locale setting, different data may be displayed. Possible values are:nls, de, en, n-au, en-ca, en-gb, es, es-es, fr, it, it-it, js, ko, ko-kr, pt, pt-br, zh, zh-cn.

Link

Use to display a URL link. To specify the URL, use the link property in the format property list, rather than the link property in the main Property Editor.

RegularExpression

Use to format a column using a regular expression. Typically, you define a regular expression and replace anything that matches that expression with something else. You define the regular expression in the expression format property and the replacement value in the replace format property.

The expression format property specifies the regular expression to use for formatting. For example:

(^\d{3}).*(\d{2}).*(\d{4})

The replace format property is used for in-line substitution:$1-$2-$3

The caseSensitive format property is checked (true) when you want the expression to be case-sensitive.

The global format property is checked (true) when you want to keep checking for the regular expression after the first match. It is unchecked (false) when you want to stop after the first match.

Evaluation

Use to format a column value.

40 COMMON WIDGETS

The expression format property takes a dojo.formatter expression. For example, to format numbers using commas, you could use:

dojo.number.format($&)

To trim spaces from beginning and end of a string, you could use:dojo.trim($&)

DataGrid Events

The following event properties are available for the DataGrid widget:onCellClick: fires when a single cell is clickedonHeaderCellClick: by default, when a user clicks on a header cell, the application performs a sort on the column. You can override by calling a custom service or custom JavaScript triggered on this eventonSelected: fires when an entire row is selectedonSetColumns: used for custom JavaScript on columns—fires when grid is rendered

The Editor WidgetThe Editor widget is a sophisticated widget for creating a wide variety of inputs. Use the display property to specify the type of input. Choices are: Date, Time, Number, Currency, Select (“Select” on page 45), Check Box, Text Area, Radio Button (“Radio Button Groups” on page 46) and Slider.

Properties of the Editor Widget

Common Propertiesname: the name that WaveMaker Studio uses to reference the widget. This is the name that appears in Model Tree, in the Page Builder, in binding dialogs, and so on; this is also the name you use to reference the widget in code services.binding: you can use this property (“Tying Widgets to Data and Services” on page 15) to dynamically set any of the following:∞ disabled – if True, no events occur∞ caption – label for the input∞ displayValue – value as it is shown on the page (“Bind to

displayValue or dataValue?” on page 21)∞ dataValue - value as it appears in database (inherited from the

displayValue if not set)∞ readonly - if true, user cannot input to the Editor

showing: when checked (true), the widget is visible to users; when unchecked (false), the widget is hidden.

THE EDITOR WIDGET 41

disabled: when checked (true) the widget can take no inputs.

Display Propertiesreadonly: if checked (true), the widget is displayed as an output, rather than input, fields. caption: the caption is the “label” on the widget, the text that the user sees.captionSize: specifies the size of the caption in the Editor widget. The value of the caption is specified by the caption property. Before you can set the captionSize, you first need to specify the units of size, which you do by setting the captionUnits property.captionUnits: specifies the units in which the captionSize property is measured. The default value is flex.captionAlign: specifies the horizontal alignment of the caption in the Editor widget. The alignment is relative to the entire available caption area, rather than the entire area of the Editor widget. Possible values are: Right, Left, and Center.captionPosition: specifies the vertical alignment of the caption in the Editor widget. The position is relative to the Editor input (or output) field. Possible values are: Top, Bottom, Left and Right.

Layout Propertiessize: specifies the size of the widget. Before you can set the size, you first need to specify the units of size, which you do by setting the sizeUnits property. If the autosize property is checked (true) then the size property cannot be set.sizeUnits: specifies the units in which the size property is measured. If the autosize property is checked (true) then the sizeUnits property cannot be set. Default value is px. Choices are:∞ px: pixels∞ em: text size; adapts automatically to current screen size∞ pt: point (1/72 inch)∞ flex: stretches widget to fill up proportional area of available space

(see “Setting Widget Size” on page 19)

Editing Propertiesdisplay: the format in which WaveMaker Studio displays the text. For a full list of types and type properties (see “Display Types and their Formatting Properties” on page 49).editor: click to display the properties for configuring the selected display type (see “Display Types and their Formatting Properties” on page 49).displayValue: default display value for the widget.

42 COMMON WIDGETS

Editor Events

The Editor widget has a single event, called onchange. This event fires when the display value of the widget changes. For example, when a user selects a value from a drop-down menu, the display value of that menu changes. You could use the onchange event to call an operation that populates a second drop-down menu.

Display Types and their Editor Properties

Each Editor widget has a display property. Set the display property to define the type of data you’re displaying in the Editor. Once you set the display property, click the editor property to further configure the Editor. The configuration options depend on the display type. In the list of editor properties, click back to get back to the main properties. Possible values for the display property are described in the following sections:

“Text” on page 42“Date” on page 43“Time” on page 43“Number” on page 44“Currency” on page 44“Select” on page 45“CheckBox” on page 45“TextArea” on page 46 “Radio Button Groups” on page 46

Text

Use to display text. The following editor properties are available when the display property is set to Text:

changeOnKey: if checked (true) the output for the field changes with each character you enter, so you can see changes as you typeinvalidMessage: message which displays if validation is not met or required field not filled inpassword: Masks the users input with ****promptMessage: when in focus, displays hint to userregExp: a regular expression used for client side validation (“Validation” on page 47)required: if checked (true), this Editor widget represents a required field and the field cannot be submitted unless the user enters a value.

THE EDITOR WIDGET 43

Date

Use to display dates. The Calendar widget is automatically displayed below the date-entry field. Invalid dates in the Calendar are unselectable.

The following editor properties are available when the display property is set to Date:

invalidMessage: message which displays if validation is not met or required field not filled inmaximum: maximum date rangeminimum: minimum date rangepromptMessage: when in focus, displays hint to userrequired: if checked (true), this Editor widget represents a required field and the field cannot be submitted unless the user enters a value.

Time

Use to display times. The Time widget is automatically displayed below the date-entry field. Invalid dates in the Calendar are unselectable.

44 COMMON WIDGETS

The following editor properties are available when the display property is set to Tme:

invalidMessage: message which displays if validation is not met or required field not filled inmaximum: maximum time rangeminimum: minimum time rangepromptMessage: when in focus, displays hint to userrequired: if checked (true), this Editor widget represents a required field and the field cannot be submitted unless the user enters a value.showMessages: if checked (true) this Editor widget diplays the promp and invalidMessage messages.

Number

Use to display numbers. The following editor properties are available when the display property is set to Number:

changeOnKey: if checked (true) the output for the field changes with each character you enter, so you can see changes as you typeinvalidMessage: message which displays if validation is not met or required field not filled inmaximum: maximum time rangeminimum: minimum time rangepassword: masks the users input with ****places: number of decimal places to showpromptMessage: when in focus, displays hint to userregExp: a regular expression used for client side validation (“Validation” on page 47)required: if checked (true), this Editor widget represents a required field and the field cannot be submitted unless the user enters a value.

Currency

Use to display currency. The following properties are available when the display property is set to Currency:

changeOnKey: if checked (true) the output for the field changes with each character you enter, so you can see changes as you typeinvalidMessage: message which displays if validation is not met or required field not filled inmaximum: maximum valueminimum: minimum value

THE EDITOR WIDGET 45

password: masks the users input with ****places: number of decimal places to showpromptMessage: when in focus, displays hint to userregExp: a regular expression used for client side validation (“Validation” on page 47)required: if checked (true), this Editor widget represents a required field and the field cannot be submitted unless the user enters a value.

Select

Use to make the Editor widget a Select Menu. Select Menus allow the user to select a value from a list of values. In order for this to work, you need to populate the select list with the values. There are two ways to do this. For both you need to deal with the specific editor type properties (the properties available when you click the editor: (details) button).

Method One: Enter the values into the options property as comma separated values a, b, cMethod Two: Use the binding property to bind the select to a dataSet. If you bind to a dataSet, you must bind to a list (just like for DataGrid). You can use a Service Call or a Variable. Then choose a dataField to show a specific field.Then, for any value output you bind to the editor's displayValue or dataValue. For a select, these will be identical.

The following editor properties are available when the displayType is Select:

allowNone: adds a blank entry to the list of selectable itemsbinding: allows you to obtain the values for the drop down from a service call or variabledataField: if bound – select the column name to be used as the data value for the selection (i.e. StateID)displayField: if bound – select the column name of the values to be displayed to the user (i.e. StateName)options: manually enter option to be used as both display and data values for the selectionrequired: if checked (true) the user must select an item from the menu

CheckBox

Use the checkBox display type to create a checkbox. The following editor properties are available for the checkBox Editor:

dataType: the data type for the checkBox selection value. The data type for this value can be a string, a boolean, or a number.

46 COMMON WIDGETS

required: if checked (true) the value cannot be null.showMessages: if checked (true) this Editor widget diplays the promp and invalidMessage messages.startChecked: if checked (true) the default value of this checkbox is “true” (the exact value would depend on the dataType you selected for the checkbox).

Radio Button Groups

To create a group of radio buttons, drag an editor widget onto the page for each radio button you want. Change the value of the display property to RadioButton. By default, the radio buttons are all in the same group. You can also edit the Editor details (the details button for the editor property) and set a name for the radioGroup to limit its scope.

To bind to a value associated with a radioGroup, bind to any editor in that group's groupValue property (“Tying Widgets to Data and Services” on page 15). If multiple radio buttons have same group name, then only one response is allowed per group.

Use the RadioButton display type to create a checkbox. The following editor properties are available for the RadioButton Editor:

dataType: the data type for the RadioButton selection value. The data type for this value can be a string, a boolean, or a number.radioGroup: type in a group name for this radio button. This will create a sub-group of radio buttons. All radio buttons with the same radioGroup name wil belong to this sub-group.required: if checked (true) the value cannot be null.showMessages: if checked (true) this Editor widget diplays the promp and invalidMessage messages.startChecked: if checked (true) this radio button appears selected by default.

TextArea

When you set the display value of the Editor widget to TextArea, the Editor widget appears as a text area. The following editor properties are available for the TextArea Editor:

required: if checked (true) the value cannot be null.showMessages: if checked (true) this Editor widget diplays the prompt and invalidMessage messages.

THE LABEL WIDGET 47

Slider

When you set the display value of the Editor widget to Slider, the Editor appears as a slider control that enters a value. Establish the range of slider values by setting the maximum and minimum values for the slider control.

The following editor properties are available for the slider Editor:discreteValues: enter discrete values for the slider as a comma-delimited list of numbersmaximum: maximum valueminimum: minimum valuerequired: if checked (true) the value cannot be null.showMessages: if checked (true) this Editor widget diplays the prompt and invalidMessage messages.

Validation

For validation, click the details button for the editor property. You can type in a regular expression in the regExp field for the editor to validate against.

The editors turn yellow and gain the ! triangle when they do not validate. Note that if the required property is checked in Editor (Details), then the field will not validate until you have typed something into it.

See Changes as You Type

To see changes as you type in an input field, check the source input's changeOnKeypress property.

The Label WidgetThe Label widget provides non-editable text. Type the text you want to display into the caption property. If you want the text to be a link, type the URL into the link property.

48 COMMON WIDGETS

The full list of properties for the Label widget are as follows:

Common Propertiesname: the name that WaveMaker Studio uses to reference the widget. This is the name that appears in Model Tree, in the Page Builder, in binding dialogs, and so on; this is also the name you use to reference the widget in code services.binding: use to dynamically set the value of the caption property, the link property or the disabled property.showing: when checked (true), the widget is visible to users; when unchecked (false), the widget is hidden.disabled: this property is not applicable to the Label widget.

Display Propertiescaption: specifies the caption that is displayed to the user.

Layout Propertiesautosize: if checked (true) this property sizes the widget so that it is just big enough for its contents and no bigger. If unchecked (false) the size of the widget is determined by the size property.

THE LABEL WIDGET 49

size: specifies the size of the widget. Before you can set the size, you first need to specify the units of size, which you do by setting the sizeUnits property. If the autosize property is checked (true) then the size property cannot be set.sizeUnits: specifies the units in which the size property is measured. If the autosize property is checked (true) then the sizeUnits property cannot be set. Default value is px. Choices are:∞ px: pixels∞ em: text size; adapts automatically to current screen size∞ pt: point (1/72 inch)∞ flex: stretches widget to fill up proportional area of available space

(see “Setting Widget Size” on page 19)box: the alignment of the child widgets (any widgets nested inside this widget). Values are Top-to-Bottom or Left-to-Right. See the “Arranging Widgets within a Container (Box Property)” on page 18 for more information on the box property.

Formatting Propertiesdisplay: the format in which WaveMaker Studio displays the text. For a full list of types and type properties (see “Display Types and their Formatting Properties” on page 49).format: click to display the properties for configuring the selected display type (see “Display Types and their Formatting Properties” on page 49).link: links the caption to a URL or Service Call.

Display Types and their Formatting Properties

Each Label widget has a display property. Set the display property to define the type of data you’re displaying in the Label. Once you set the display property, click the format property to further configure the Label. The configuration options depend on the display type. In the list of format properties, click back to get back to the main properties.

“Number” on page 50“Date” on page 50“Time” on page 50“Date Time” on page 51“Money” on page 51“Link” on page 51“RegularExpression” on page 52 “Evaluation” on page 52

50 COMMON WIDGETS

Number

Use to display numbers. The digits format property determines the number of decimal places that are displayed in the label.

Date

Use to display dates.

The datePattern format property determines the format of the date. For example:

MMM-dd-yyy

The formatLength format property determines the style of the displayed date:

short - 12/15/2007 medium – Dec 15, 2007long – December 15, 2007full – Saturday, December 15, 2007

The locale format property represents language code, used for i18n. Based on locale setting, different data may be displayed. Possible values are:nls, de, en, n-au, en-ca, en-gb, es, es-es, fr, it, it-it, js, ko, ko-kr, pt, pt-br, zh, zh-cn

Time

Use to display times.

The timePattern format property determines the format of the date. For example:

HH:mm

The formatLength format property determines the style of the displayed time:

short - 4:00 PM medium – 4:00:00 PMlong – 4:00:00 PM Pacific Standard Timefull – 4:00:00 PM Pacific Standard Time

The locale format property represents language code, used for i18n. Based on locale setting, different data may be displayed. Possible values are:nls, de, en, n-au, en-ca, en-gb, es, es-es, fr, it, it-it, js, ko, ko-kr, pt, pt-br, zh, zh-cn

THE LABEL WIDGET 51

Date Time

Use to display date and time.

The datePattern format property determines the format of the date. For example:

MMM-dd-yyy

The timePattern format property determines the format of the date. For example:

HH:mm

The formatLength format property determines the style of the displayed date-time:

short - 12/15/2007 4:00 PM medium – Dec 15, 2007 4:00:00:00 PMlong – December 15, 20074:00:00 PM Pacific Standard Timefull – Saturday, December 15, 2007 4:00:00 PM Pacific Standard Time

The locale format property represents language code, used for i18n. Based on locale setting, different data may be displayed. Possible values are:nls, de, en, n-au, en-ca, en-gb, es, es-es, fr, it, it-it, js, ko, ko-kr, pt, pt-br, zh, zh-cn

Money

Use to display money.

The currency format property specifies the symbol to display before amount.

The digits format property determines the number of decimal places that are displayed.

The round format property can be used to specify that the amount be rounded rather than truncated.

The locale format property represents language code, used for i18n. Based on locale setting, different data may be displayed. Possible values are:nls, de, en, n-au, en-ca, en-gb, es, es-es, fr, it, it-it, js, ko, ko-kr, pt, pt-br, zh, zh-cn

Link

Use to display a URL link. To specify the URL, use the link property in the format property list, rather than the link property in the main Property Editor.

52 COMMON WIDGETS

RegularExpression

Use to format a Label caption using a regular expression. Typically, you define a regular expression and replace anything that matches that expression with something else. You define the regular expression in the expression format property and the replacement value in the replace format property.

The expression format property specifies the regular expression to use for formatting. For example:

(^\d{3}).*(\d{2}).*(\d{4})

The replace format property is used for in-line substitution:$1-$2-$3

The caseSensitive format property is checked (true) when you want the expression to be case-sensitive.

The global format property is checked (true) when you want to keep checking for the regular expression after the first match. It is unchecked (false) when you want to stop after the first match.

Evaluation

Use to format Label caption value. This is typically used for a Label when the caption is generated through a binding, rather than a constant value entered by the developer.

The expression format property takes a dojo.formatter expression. For example, to format numbers using commas, you could use:

dojo.number.format($&)

To trim spaces from beginning and end of the Label caption, you could use:

dojo.trim($&)

The Layers WidgetThe Layers widget is a container for individual layers. Layers are containers similar to pages but with a different scope and more flexible and efficient navigation possibilities (“About Pages and Layers” on page 21). Each Layers widget is configurable with properties, as is each layer it contains:

“Types of Layers” on page 53“Layers Widget Properties” on page 53“Layers Widget Events” on page 54“Properties of Each Layer” on page 55

THE LAYERS WIDGET 53

“Events for Each Layer” on page 56

Types of Layers

The WaveMaker Studio Layers widget provides three different styles. The layersType property allows you to specify which type of layers you want to use. You can easily switch Layers types.

Tabs: The tabbed layers style gives each layer a tab. Users can navigate between layers by clicking the relevant tab. Use the title property to set the name on the tab. You can also create tabbed layers with the Tabs widget (“The Tabs Widget” on page 63).Accordion: The accordion layers style gives each layer an expandable accordion-style display, like the one in the Palette. Use the title property to set the label for the accordion box. You can also create accordion layers with the Accordion widget (“The Accordion Widget” on page 27).Layers (Default): With the default layers style, only one layer is visible at a time and there is no visual cue about the other layers that exist. Navigation between layers is triggered by events, such as a user clicking a button or link.

Once you’ve created the initial Layers container, you can add new layers using the add operation in the Property Editor. To set up navigation between layers, use the Layer Service (“Navigation Between Pages and Layers” on page 23).

Layers Widget Properties

The following properties are available on the Layers widget:

Common Propertiesname: the name that WaveMaker Studio uses to reference the widget. This is the name that appears in Model Tree, in the Page Builder, in binding dialogs, and so on; this is also the name you use to reference the widget in code services.binding: use to dynamically set the value of the disabled property.showing: when checked (true), the widget is visible to users; when unchecked (false), the widget is hidden.disabled: when checked (true), no events occur in this Layers widget (“Layers Widget Events” on page 54).

Layout Propertiesautosize: if checked (true) this property sizes the widget so that it is just big enough for its contents and no bigger. If unchecked (false) the size of the widget is determined by the size property.

54 COMMON WIDGETS

size: specifies the size of the widget. Before you can set the size, you first need to specify the units of size, which you do by setting the sizeUnits property. If the autosize property is checked (true) then the size property cannot be set.sizeUnits: specifies the units in which the size property is measured. If the autosize property is checked (true) then the sizeUnits property cannot be set. Default value is px. Choices are:∞ px: pixels∞ em: text size; adapts automatically to current screen size∞ pt: point (1/72 inch)∞ flex: stretches widget to fill up proportional area of available space

(see “Setting Widget Size” on page 19)

Other PropertiesdefaultLayer: specifies which layer to show by defaultlayersType: specifies the type of layers (“Types of Layers” on page 53)

Operation Properties

The Layers widget provides the following operations for configuring the grid:

add: automatically adds a new Layer to the layers widget

Layers Widget Events

The Layers widget provides the following two events:onchange: fires after the Layers widget changes the active layeroncanchange: fires when the layers object is about to change the activelayer. Use it to disallow the change of layer.

This section explains a little more about the oncanchange event, and provides an example using both events.

The oncanchange event has an argument called inChangeInfo which is an object of the following format: {newIndex: inIndex, canChange: true}

where newIndex is the index of the layer that will be shown and canChange is a boolean value indicating whether the change is allowed. You can write code to check the new index and set inChangeInfo.canChange = false to disallow the change of layers.

For example, suppose you write a JavaScript function called tabLayers1turbo.declare("Main", turbo.Part, {start: function() {

this.tabLayers1Change();},canChangeTabs: true,

THE LAYERS WIDGET 55

button1Click: function(inSender) {this.canChangeTabs = !this.canChangeTabs;this.label1.setCaption(this.canChangeTabs ? "yes" : "no");

},tabLayers1Change: function(inSender, inIndex) {

this.label6.setCaption("Showing: " + this.tabLayers1.getLayer().name);},tabLayers1Canchange: function(inSender, inChangeInfo) {

// inChangeInfo contains: // - canChange, which should be set to false if the change should not occur// - newIndex, the index of the layer that will be shown (this can be used to selectively

allow layer changes)inChangeInfo.canChange = this.canChangeTabs;

},_end: 0});

Properties of Each Layer

Within the Layers widget, each individual Layer also has its own properties:

Common Propertiesname: the name that WaveMaker Studio uses to reference the widget. This is the name that appears in Model Tree, in the Page Builder, in binding dialogs, and so on; this is also the name you use to reference the widget in code services.binding: not used for the Layer widget

Layout Propertiessize: specifies the size of the widget. Before you can set the size, you first need to specify the units of size, which you do by setting the sizeUnits property. If the autosize property is checked (true) then the size property cannot be set.sizeUnits: specifies the units in which the size property is measured. If the autosize property is checked (true) then the sizeUnits property cannot be set. Default value is flex. Choices are:∞ px: pixels∞ em: text size; adapts automatically to current screen size∞ pt: point (1/72 inch)∞ flex: stretches widget to fill up proportional area of available space

(see “Setting Widget Size” on page 19)box: the alignment of the child widgets (any widgets inside the widget). Values are Top-to-Bottom or Left-to-Right. See the “Arranging Widgets within a Container (Box Property)” on page 18 for more information on the box property.

Other Propertiescaption: the label on the tab (for Tabbed Layers) or accordion menu (for Accordion Layers).

56 COMMON WIDGETS

Operations

Each Layer has the following operations that you can use to move between layers in the Page Builder at design time.

moveNext: in the Page Builder, use to show the next Layer movePrevious: in the Page Builder, use to show the previous Layer

Events for Each Layer

Each Layer in the Layers widget has an onShow event that fires when that Layer becomes the active Layer in the Layers widget.

The List WidgetA List widget is a very simple way to display a list of objects. In most cases, it is better to use a DataGrid widget (“The DataGrid Widget” on page 34) than a List widget because a List widget is far less configurable. For example, column heads are always the name of the item they are listing and cannot be renamed. You cannot sort on a column.

List Widget Properties

To configure a List widget, the following properties are available:

Common Propertiesname: the name that WaveMaker Studio uses to reference the widget. This is the name that appears in Model Tree, in the Page Builder, in binding dialogs, and so on; this is also the name you use to reference the widget in code services.binding: defines the input dataSet for this widget. The dataSet must be a list. Clicking the binding property launches a dialog for defining this input source (“Tying Widgets to Data and Services” on page 15). From this dialog you can also dynamically set the value of the disabled property.showing: when checked (true), the widget is visible to users; when unchecked (false), the widget is hidden.disabled: when checked (true), no events occur on this list (“List Widget Events” on page 57).

Layout Propertiesautosize: if checked (true) this property sizes the widget so that it is just big enough for its contents and no bigger. If unchecked (false) the size of the widget is determined by the size property.

THE PANE WIDGET 57

size: specifies the size of the widget. Before you can set the size, you first need to specify the units of size, which you do by setting the sizeUnits property. If the autosize property is checked (true) then the size property cannot be set.sizeUnits: specifies the units in which the size property is measured. If the autosize property is checked (true) then the sizeUnits property cannot be set. Default value is px. Choices are:∞ px: pixels∞ em: text size; adapts automatically to current screen size∞ pt: point (1/72 inch)∞ flex: stretches widget to fill up proportional area of available space

(see “Setting Widget Size” on page 19)

Other PropertiescolumnWidths: widths of each column dataFields: comma-delimited list of in the dataSet for which a column should be displayed. Names are case sensitive. For example:customerName, contactFirstName, contactLastName

If you leave the dataField property blank, all fields are included in the list.headerVisable: if checked (true) , then headers are displayed; if unchecked, headers are not displayedupdateNow: updates the underlying service component and displays the current results in the Page Designer

List Widget Events

The following event properties are available for the DataGrid widget:onClick: fires when a user clicks in the ListonDblClick: fires when a user double-clicks in the ListonSelect: fires when a row in the List is selectedondeselect: fires when the List widget loses focus

The Pane WidgetA Pane widget is a subpage container. It defines an area on a page where you display a subpage (“Displaying Subpages” on page 25). To use the pane widget, drag it into the page builder and then create a Navigation Component that displays a page in the pane (“Navigation Between Pages and Layers” on page 23).

58 COMMON WIDGETS

NOTE: WaveMaker Studio automatically creates a pane widget for you when you drag a page from the Palette and drop it into the Page Builder. WaveMaker Studio also automatically generates a name for pane widget, although you are free to change the name. You can target these automatically-generated pane widget when you create a Navigation Component.

Pane Widget Properties

The Pane widget has the following properties:

Common Propertiesname: the name that WaveMaker Studio uses to reference the widget. This is the name that appears in Model Tree, in the Page Builder, in binding dialogs, and so on; this is also the name you use to reference the widget in code services.binding: not used for the Pane widget.showing: when checked (true), the widget is visible to users; when unchecked (false), the widget is hidden.

Layout Propertiesautosize: if checked (true) this property sizes the widget so that it is just big enough for its contents and no bigger. If unchecked (false) the size of the widget is determined by the size property.size: specifies the size of the widget. Before you can set the size, you first need to specify the units of size, which you do by setting the sizeUnits property. If the autosize property is checked (true) then the size property cannot be set.sizeUnits: specifies the units in which the size property is measured. If the autosize property is checked (true) then the sizeUnits property cannot be set. Default value is px. Choices are:∞ px: pixels∞ em: text size; adapts automatically to current screen size∞ pt: point (1/72 inch)∞ flex: stretches widget to fill up proportional area of available space

(see “Setting Widget Size” on page 19)

Other PropertiespageName: select a default page to load in this Pane widget

Pane Widget Events

The Pane widget has one event, called onPageChanged. This event fires whenever a new page is loaded in this Pane widget.

THE PANEL WIDGET 59

The Panel WidgetIn WaveMaker Studio, you typically lay your pages out in Panels. The Panel widget acts as a container for other widgets. This widget is not itself visible to the user (unless you specifically give it a background color or border using the styles property).

The contents of each Panel are arranged horizontally or vertically, depending on the value of the box property (“Arranging Widgets within a Container (Box Property)” on page 18). Some of the widgets inside the Panel might have a specific size, while other are set up to fill the remaining space. When you use this method, your pages display more reliably on different browsers and different screens.

Panel Widget Properties

The Panel widget has the following properties:

Common Propertiesname: the name that WaveMaker Studio uses to reference the widget. This is the name that appears in Model Tree, in the Page Builder, in binding dialogs, and so on; this is also the name you use to reference the widget in code services.binding: the binding property is not used with the Panel widget.showing: when checked (true), the widget is visible to users; when unchecked (false), the widget is hidden.

Layout Propertieslock: if checked (true), you cannot add or remove widgets to this container widget.autosize: if checked (true) this property sizes the widget so that it is just big enough for its contents and no bigger. If unchecked (false) the size of the widget is determined by the size property.size: specifies the size of the widget. Before you can set the size, you first need to specify the units of size, which you do by setting the sizeUnits property. If the autosize property is checked (true) then the size property cannot be set.sizeUnits: specifies the units in which the size property is measured. If the autosize property is checked (true) then the sizeUnits property cannot be set. Default value is flex. Choices are:∞ px: pixels∞ em: text size; adapts automatically to current screen size∞ pt: point (1/72 inch)

60 COMMON WIDGETS

∞ flex: stretches widget to fill up proportional area of available space (see “Setting Widget Size” on page 19)

box: the alignment of the child widgets (any widgets inside this widget). Values are Top-to-Bottom or Left-to-Right. See the “Arranging Widgets within a Container (Box Property)” on page 18 for more information on the box property.

The Picture WidgetUse the Picture widget to add an image. In order for this to work, you need to put your image files in the webbapproot directory for your project.

How to Add the Image

To add an image to your WaveMaker Studio application, follow these steps:

1. Create an images directory for your project under the webapproot directory

2. Add your image files to the images directory

3. Add a Picture widget to the page.

4. In the Property Editor, set the source property to a relative address from the webapproot directory, such as images/foo.jpg (not the http-style forward slashes).

You can also use the Picture widget to create an image link. Specify the image in the source property and the link URL in the link property.

Picture Widget Properties

The Panel widget has the following properties:

Common Propertiesname: the name that WaveMaker Studio uses to reference the widget. This is the name that appears in Model Tree, in the Page Builder, in binding dialogs, and so on; this is also the name you use to reference the widget in code services.source: location of the image; can be either a local path relative to the webapproot directory (uses forward slash “/”) or a URLbinding: use to dynamically set the value of the disabled property.showing: when checked (true), the widget is visible to users; when unchecked (false), the widget is hidden.disabled: when checked (true) the widget can take no inputs.

THE SPACER WIDGET 61

Layout Propertiesautosize: if checked (true) this property sizes the widget so that it is just big enough for its contents and no bigger. If unchecked (false) the size of the widget is determined by the size property.size: specifies the size of the widget. Before you can set the size, you first need to specify the units of size, which you do by setting the sizeUnits property. If the autosize property is checked (true) then the size property cannot be set.sizeUnits: specifies the units in which the size property is measured. If the autosize property is checked (true) then the sizeUnits property cannot be set. Default value is flex. Choices are:∞ px: pixels∞ em: text size; adapts automatically to current screen size∞ pt: point (1/72 inch)∞ flex: stretches widget to fill up proportional area of available space

(see “Setting Widget Size” on page 19)aspect: aspect ratio; can be:∞ h (preserve image horizontally)∞ v (preserve image vertically)∞ none (default)

box: the alignment of the child widgets (any widgets inside the widget). Values are Top-to-Bottom or Left-to-Right. See the “Arranging Widgets within a Container (Box Property)” on page 18 for more information on the box property.

Other Propertieslink: type in a URL to create an image link. When the user clicks on the image, the specified URL loads. Note that this is not where you specify an URL to the image source. Use the source property for that.

Picture Widget Events

The Picture widget provides a single event, the onclick event. This event fires when a user clicks on the image.

The Spacer WidgetThe Spacer widget is useful when you want to add space between elements in a container. By using the flex (“Flex” on page 19) value for the sizeUnits property, you can make the Spacer widgets particularly powerful. For example, to center a widget on a page, just put a Spacer widget on either side and give both Spacer widgets a flex of one.

62 COMMON WIDGETS

Spacer Widget Properties

You can specify the following properties for a Spacer widget:name: the name that WaveMaker Studio uses to reference the widget. This is the name that appears in Model Tree, in the Page Builder, in binding dialogs, and so on; this is also the name you use to reference the widget in code services.binding: this property is not used with the Spacer widget.showing: when checked (true), the widget is visible to users; when unchecked (false), the widget is hidden.autosize: if checked (true) this property sizes the widget so that it is just big enough for its contents and no bigger. If unchecked (false) the size of the widget is determined by the size property.size: specifies the size of the widget. Before you can set the size, you first need to specify the units of size, which you do by setting the sizeUnits property. If the autosize property is checked (true) then the size property cannot be set.sizeUnits: specifies the units in which the size property is measured. If the autosize property is checked (true) then the sizeUnits property cannot be set. Default value is flex. Choices are:∞ px: pixels∞ em: text size; adapts automatically to current screen size∞ pt: point (1/72 inch)∞ flex: stretches widget to fill up proportional area of available space

(see “Setting Widget Size” on page 19)box: the alignment of the child widgets (any widgets nested inside this widget). Values are Top-to-Bottom or Left-to-Right. See the “Arranging Widgets within a Container (Box Property)” on page 18 for more information on the box property.

The Splitter WidgetThe Splitter widget is a moveable divider bar that provides visual separation of elements on a Page. Similar to a Bevel, except that users can move the Splitter to allow resizing of adjacent areas.

Splitter Widget Properties

The Splitter widget has the following properties:

Common Properties

THE TABS WIDGET 63

name: the name that WaveMaker Studio uses to reference the widget. This is the name that appears in Model Tree, in the Page Builder, in binding dialogs, and so on; this is also the name you use to reference the widget in code services.binding: not used with the Splitter widget.showing: when checked (true), the widget is visible to users; when unchecked (false), the widget is hidden.

Layout Properties maximum: The maximum value for the Splitter’s movement. The value “-1” (default) specifies unlimitted movement.minimum: The minimum value for the Splitter’s movement. The value “-1” (default) specifies unlimitted movement.

The Tabs WidgetThe Tabs widget is a Layers widget (“The Layers Widget” on page 52) for adding tabbed layers. If you decide you don’t want to use tabbed layers, you can easily switch to another style of layer by changing the layersType property.

64 COMMON WIDGETS

CHAPTER 5

Working with Databases

This chapter contains the following information:“What Databases are Supported?” on page 65“Importing a Database” on page 65“Database Objects (Tables and Queries)” on page 70“Database Service Operations” on page 75“Exporting a Data Model” on page 81

What Databases are Supported?Currently WaveMaker Studio supports MySQL, Oracle, and SQL Server. The installation also includes Hypersonic SQL DB (HSQLDB), as an embedded database. This database is included for demo and testing purposes. For more information on HSQLDB, see:

http://hsqldb.org/web/hsqlDocsFrame.html

Importing a DatabaseTo use a database in an application, you first need to import it into the project. This import process gives WaveMaker Studio all the connection and authentication information it needs to connect to your database.

When you import the database, WaveMaker creates:a Data Model. The Data Model describes all the database tables that you want to be able to access in WaveMaker. The Data Model can also include additional information such as custom queries. WaveMaker Studio stores your database table information and your custom queries as data objects. For more information on these data objects, see “Database Objects (Tables and Queries)” on page 70.a database Service. A Service is just a group of defined actions, such as a database insert or search action. The database service that WaveMaker creates for you provides the following basic actions, called operations,

66 WORKING WITH DATABASES

for interacting with each table in the database: insert, update, delete, getbyID, getList, getCount. For more information on database service operations, see “Database Service Operations” on page 75.

To import a database, follow these steps:

1. Open the project in which you want to use the database.

2. In the Editor Tabs (across the top left of the WaveMaker Studio) click the Data Model to open the Data Model Editor.

3. The Data Model Editor appears. The Data Model editor appears. The Data Model editor has an Objects tab and an Import tab. Click the Import tab to open the Import Database screen.

IMPORTING A DATABASE 67

4. At the top of the screen, in the New Data Model Name field, type in a name for the Data Model. You can just give it the same name as the database or you can use a different name. The name can contain only alphanumeric characters.

5. Below the New Data Model Name field, the screen shows a Username field and a Password field. This is where you type a valid username and password for this database connection.

6. The bottom part of the Import Database screen is an Accordion with two headings: Settings and Advanced Options. Click on the heading to see the configuration fields for that heading. At a minimum, you need to fill out the fields under the Settings heading (“Basic Settings” on page 67). The Advanced Options might be useful for the advanced user (“Advanced Options” on page 69).

7. Click the Test Connection button. You should get a “Connection Successful” message. If the test fails, go back and make sure your settings are correct.

8. Click the Import Database button. WaveMaker Studio begins importing the database (this could take a few minutes). When the import is complete, the Data Model Editor shows you the database objects you have just created (“Database Objects (Tables and Queries)” on page 70).

9. Save the project.

Basic Settings

The “Settings” area of the Import Database screen allows you to choose what type of database you want to import and configure the basic required settings.

NOTE: The Settings area is collapsed if the “Advanced Options” area is expanded. Click on the Settings bar to see the Settings area again. For more on advanced configuration options, see “Advanced Options” on page 69.

When you choose your database type the Database drop-down menu, the configuration for that type of database appear. The configuration fields are different for the different database types:

∞ “HSQLDB” on page 68∞ “MySQL” on page 68∞ “Oracle” on page 68∞ “DB2” on page 68∞ “SQL Server” on page 69

68 WORKING WITH DATABASES

HSQLDB

When you import an HSQLDB database, you will need to type the following settings into the “Database Connection” screen:

Database System: The type of database you want to import. Choose HSQLDB.File: The location of the HSQLDB database on your file system. For example, if your database file is called cmdb and it is in C:\Program Files\WaveMaker, then you would type in:C:\Program Files\WaveMaker\Support\Data\cmdb\cmdb

MySQL

When you import a MySQL database, you will need to type the following settings into the “Database Connection” screen:

Database System: The type of database you want to import. Choose MySQL.Host: The network host for the MySQL database. Default value is localhostPort: The port number for the MySQL database.Database: The name of the database instance.

Oracle

When you import an Oracle database, you will need to type the following settings into the “Database Connection” screen:

Database System: The type of database you want to import. Choose Oracle.Host: The network host for the Oracle database. Default value is localhostPort: The port number for the Oracle database.SID: The Oracle System Identifier that refers to the instance of the Oracle database running on the server. The default is ORCL, which is the default SID that is configured when installing your Oracle database.

DB2

When you import a DB2 database, you will need to type the following settings into the “Database Connection” screen:

Database System: The type of database you want to import. Choose DB2.Host: The network host for the DB2database. Default value is localhostPort: The port number for the DB2 database.

IMPORTING A DATABASE 69

Database: The name of the database.

SQL Server

When you import a SQL Server database, you will need to type the following settings into the “Database Connection” screen:

Database System: The type of database you want to import. Choose SQLServer.Host: The network host for the SQL Server database. Default value is localhostPort: The port number for the SQL Server database.Database: The name of the database.Instance: The name of the SQL Server instance.

Advanced Options

For advanced users, WaveMaker Studio provides some advanced configuration options. To see these options, click the Advanced Options accordion heading. The following options are available:

Connection URL: When you import a database using the standard configuration options on the Import Database screen, WaveMaker Studio creates a JDBC URL for you. This URL is shown here in the Connection URL field. If you know what you are doing and want to change this JDBC URL, you can do it here.Java Package: WaveMaker Studio generates Java classes for you when you import a database. If you want a different Java package name than the default name we generate, type it in here. Table Filter: By default WaveMaker Studio imports all the tables in the database. If you want to import only a subset of the tables, type in a comma-delimited list of regular expressions here.Schema Filter: When you are importing a database that supports schemas, WaveMaker Studio imports only the tables for the default schema. If you want to import tables from other schemas, add the schema names in this field.Driver Class: JDBC driver class name. WaveMaker Studio creates a JAR file for each database that uses a sepcifed dirver. If you want to use a different JAR file for connecting, specify it here (the JAR file must be in the Application Server’s class path).Dialect: Specifies the Hibernate dialect for connecting to the database.

70 WORKING WITH DATABASES

Database Objects (Tables and Queries)All the database objects available to your application are listed in the Database Objects list on the left side of the Data Model editor. Each database that you import into your application appears in the list. Click the database to expand it and see the “Tables (Types)” on page 70 and “Database Queries” on page 72 for that database.

Tables (Types)

When you import a database, WaveMaker Studio automatically creates data objects, called types, that allow your application to interact with that database. Types are the Java types that represent the tables in your database, including and columns, keys and relationships.

To see the tables for a database, click the Data Model Editor tab and then click to expand the objects for that database in the “Database Objects” list. The tables are listed under the “Types” heading.

In this list, keys are marked with asterisks (*) and relationships are marked as follows:

> one-to-one or one-to-zero< one-to-many

If you select a type in the list, more information about that type appears in the Data Model Viewer on the right.

DATABASE OBJECTS (TABLES AND QUERIES) 71

The following table explains the information that is displayed about each column. You can change any of these values and save your changes to the Data Model. Note that this does not change the database that the data model represents. To change the database, you need to export the database.

Below the columns information, the Data Model editor shows the relationships for the selected table. You can add and delete relationships here.

Primary Key A check box. Checked if the column is a primary key.

Foreign Key True or False value. True if the column is a foreign key, false if not.

Type Data type of the column.

Not Null A check box. Checked if the column can NOT hold a null value. If unchecked, the column value can be null.

Length Maximum column length.

Precision Refers to the maximum number of digits used by the selected (numeric) data type.

Generator If the column is a primary key, specifies the method of key generation (“Key Generation” on page 72).

Params If a generator is selected, specifies the parameters for that generator, if any.

72 WORKING WITH DATABASES

To add a relationship, first create the tables that will be related. Then add a column for the foreign key, select that column, and click on the '+' next to “Relationships”. Add a name for the relationship and in the “Related Type” drop down, pick which table you want to reference.

NOTE: Changes you make in the Data Model editor are not automatically made in the database that it represents. In order to change your database, you need to export your Data Model (“Exporting a Data Model” on page 81).

Key Generation

For primary keys, you can use a generator to generate the key values. The Generator field provides the following key generation options:

If your Generator type requires an input parameter, enter it in the Params column next to the Generator column.

Database Queries

When you import a database, WaveMaker Studio automatically generates a few basic database queries for you. You can use these generated queries as they are, modify them to suit your needs, or create new queries from scratch.

Generator Description

assigned lets the application to assign an identifier to the object before save() is called. This is the default strategy if no <generator> element is specified.

identity supports identity columns in DB2, MySQL, MS SQL Server, Sybase and HypersonicSQL. The returned identifier is of type long, short or int.

sequence uses a sequence in DB2, PostgreSQL, Oracle, SAP DB, McKoi or a generator in Interbase. The returned identifier is of type long, short or int

native picks identity, sequence or hilo depending upon the capabilities of the underlying database

DATABASE OBJECTS (TABLES AND QUERIES) 73

To see the database queries for a database, click the Data Model Editor tab and then click to expand the objects for that database in the “Database Objects” list. The queries are listed under the “Queries” heading.

If you click one of these queries, it appears in the Query Editor to the right of the “Database Objects” list.

74 WORKING WITH DATABASES

This editor uses the Hibernate Query Language (HQL) which is similar to (but not the same as) SQL. To create a query, you need to fill in the following fields:

Query Name: To save your query (so that you can create a service component to call it in your application) you need a query name. This should be a unique alphanumeric name with no spaces.Query: This is where you type in your HQL query. Click on an existing query for an example. There is a good HQL syntax reference here:

http://www.hibernate.org/hib_docs/reference/en/html/queryhql.html

Return Single Result

You can optionally use the Returns Single Result checkbox to specify that the query can return only one object (rather than a list). If this box is checked, then only one object is returned from the server, even if multiple objects match the query.

Bind Parameters

You can create bind parameters for user input. To create a new bind parameter, type in a name and a select the type from the drop-down menu. Then click the plus (+) button. The new parameter will appear in the Bind Parameters list.

When you build your query, you can refer to the bind parameter using the parameter name preceded by a colon (:paramName). For example, if you have a bind parameter called myParam, you could create the following query:from Customers _a where _a.id=:myParam

To delete a parameter, select it in the list and click the delete (X) button.

DATABASE SERVICE OPERATIONS 75

Testing Queries

To test a query in the Query editor, type in a value for each bind parameter in the Query Input field. If you have multiple bind parameters, type in the inputs as a comma delimited list.

Click the Live Layout button, if you haven’t already done so. Then click the the execute button (the orange arrow). The results appear below the Query Input field.

Database Service OperationsWhen you import a database, WaveMaker Studio automatically generates a service for that database. This service includes all the basic operations you need to work with the database. This section discusses the database service and operations:

“Viewing the Database Service and Service Operations” on page 75“Database Service Operations” on page 76“Error or Success? Handling Results from Database Service Operations” on page 80

Viewing the Database Service and Service Operations

After you import the database, you can click the Services tab to see the service.

76 WORKING WITH DATABASES

Click to expand or collapse each operation. When you expand an operation you can see its inputs and outputs. This will be useful when you call the operation.

For information about each of these automatically generated applications, see “Database Service Operations” on page 76. For more on service calls in general, see “Working with Services and Operations” on page 83.

Database Service Operations

This section discusses the automatically-generated operations:“getCount” on page 76“GetByID” on page 77“getList” on page 78“Insert” on page 78“Update” on page 79“Delete” on page 80

getCount

The getCount operation performs a search on your database and returns an integer representing the number of records that match the search

DATABASE SERVICE OPERATIONS 77

conditions. The getCount operation has two inputs: the searchInstance input and the options input:

The searchInstance input allows you to bind to each column in the table. Typically, you bind a column in the table to an input (Editor widget). You can bind to as many columns as you want. The search returns the number of records that match all the search conditions.

The options input is the same as for the getList operation (“getList” on page 78), although the paging options are not applicable to the getCount operation:

GetByID

When you import your database, WaveMaker Studio automatically creates a getByID operation for each table in the database. The getByID operation takes an input of the same type as the primary key for that table. It returns the database record with an ID that matches the input.

In general, to set up getByID, you follow these basic steps:

1. Import the database.

2. Open the Page Designer.

3. In the Model Tree on the right side of the Page Designer, click on the Components tab.

4. Click on the cylinder icon to create a new service call. The “Configure Service Call” dialog appears.

5. Create a database service and configure it to use the getById operation for the table.

6. Bind the input to the widget that allows the user to specify a particular record. Typically, you bind to the primary key field in the “selected” List widget item.

Option Description

excludeZeros Exclude attributes with zero values from search.

Default: true

matchMode Determines how to match string values. can be one of the following values: "anywhere", "start", "end", "exact". Default: start

ignoreCase Case insensitive string matching. Default: true

excludeNone Exclude attributes with null values from search. Default: true

maxResults Not applicable.For paging. Not applicable.

firstResults Not applicable. For paging.

orderBy Not applicable. For paging.

78 WORKING WITH DATABASES

getList

The getList operation performs a search on your database and returns a list of records that matches the search conditions. The getList operation has two inputs: the searchInstance input and the options input:

The searchInstance input allows you to bind to each column in the table. Typically, you bind a column in the table to an input (Editor widget). You can bind to as many columns as you want. The search returns records that match all the search conditions.

The options input lets you configure the search options and also provides some paging configuration. The input options are as follows:

The getList operation returns a list of objects. To display this list in your application, use a widget that displays lists, such as the DataGrid widget or the List widget.

Insert

When you import your database, WaveMaker Studio automatically creates an insert operation for each table in the database. The insert operation inserts a new record into the corresponding table in the database. It takes as input an object of the same type as the table.

Typically, you create a variable to store the object, rather than binding directly between input widgets and the service operation. This way you

Option Description

excludeZeros Exclude attributes with zero values from search.

Default: true

matchMode Determines how to match string values. can be one of the following values: • anywhere - Search for value any where in the search field of the database.• exact - Search for the exact values in the search field of the database (if

user leaves the search value blank then data is not shown.)• start - Search for value starts with the search criteria value in the search

field of the database.• end - Search for value ends with the search criteria value in the search field

of the database. The default is start.

ignoreCase Case insensitive string matching. Default: true

excludeNone Exclude attributes with null values from search. Default: true

maxResults For paging. Maximum number of rows to return.

firstResults For paging. Starting with result #.

orderBy For paging. The column to order the results by. orderBy syntax: asc|desc:<propertyname> [, asc|desc:<propertyname>]*

For example, given a city instance, order by city name and related country name: "asc: city, asc: country.country"

DATABASE SERVICE OPERATIONS 79

can reuse the same variable for all your insert, update or delete operations on this table.

In general, to set up an insert operation, you follow these basic steps:

1. Import the database.

2. In the Page Designer, create an Editor widget for each column in the table. This is where the user will input the data for the new record.

3. Create a variable of the same type as the table. (You set the type of the variable using the type property. The drop-down list of types includes a type for each table in each database you have imported into this project.)

4. Bind the data from the input Editors to the variable.

5. Create a database service and configure it to use the insert operation for the table. Bind the inputs to the variable you created.

6. Bind the insert service to the variable

7. Configure a Button widget to execute the insert operation on click.

Update

When you import your database, WaveMaker Studio automatically creates an update operation for each table in the database. The update operation updates a specified record in the corresponding table in the database. It takes as input an object of the same type as the table.

Typically, you create a variable to store the object, rather than binding directly between input widgets and the service operation. This way you can reuse the same variable for all your insert, update or delete operations on this table.

In general, to set up an update operation, you follow these basic steps:

1. Import the database.

2. In the Page Designer, create an Editor widget for each column in the table. Populate each Editor with the existing database value for the selected record. You can get the data by binding to either a service call or to data selected in a Grid.

3. Create a variable of the same type as the table. (You set the type of the variable using the type property. The drop-down list of types includes a type for each table in each database you have imported into this project.)

4. Bind the data from the Editors to the variable.

80 WORKING WITH DATABASES

5. Create a database service and configure it to use the update operation for the table. Bind the inputs to the variable you created.

6. Configure a Button widget to execute the update operation on click.

Delete

When you import your database, WaveMaker Studio automatically creates a delete operation for each table in the database. The delete operation deletes the specified record in the corresponding table in the database. It takes as input an object of the same type as the table.

Typically, you create a variable to store the object, rather than binding directly between input widgets and the service operation. This way you can reuse the same variable for all your insert, update or delete operations on this table.

In general, to set up a delete operation, you follow these basic steps:

1. Import the database.

2. In the Page Designer, create an Editor widget for each column in the table. Populate each Editor with the database value for the selected record. You can get the data by binding to either a service call or to data selected in a Grid.

3. Create a variable of the same type as the table. (You set the type of the variable using the type property. The drop-down list of types includes a type for each table in each database you have imported into this project.)

4. Bind the data from the Editors to the variable.

5. Create a database service and configure it to use the delete operation for the table. Bind the inputs to the variable you created.

6. Configure a Button widget to execute the delete service on click.

Error or Success? Handling Results from Database Service Operations

To take action based on the results of the database service call, you can use the onError and onResult events:

onError event: allows you to trigger an action when the service call does not change a record in database onSuccess event: allows you to trigger an action when the service call does change a record in database

EXPORTING A DATA MODEL 81

You can access the service call events just as you would access widget events. Select the service call (in the Model Tree), then click the Events tab in the Property Editor.

For each event, you can select an existing service call or you can create a new service call. Select the New option to configure a new call from an existing service. Select the JavaScript option to create and call a new JavaScript function.

Exporting a Data ModelYou can export your Data Model to a database. In the current release, we recommend that you do this only with simple Data Model that you are creating from scratch. If you import an existing database, do not try to make changes in the Data Model and then export those changes back to the database.

To export a data model:

1. Create the data model.

2. Select your root data model node in the tree.

82 WORKING WITH DATABASES

3. The Connection Settings form appears to the right.

4. In the Username and Password fields, type in the user name and password for the database you’re exporting to.

5. In the Connection URL field, type in the JDBC URL. An easy way to find this, if you are not sure what it is, is to go to the import dialog. Fill in all the information as though you want to import the database. Click on “advanced options”, remove the "ifexists=true" bit of the URL, and copy the JDBC URL. The JDBC URL might look something like this:jdbc:hsqldb:file:c:/test/hsql/p1;shutdown=true

6. Click the Save button.

7. Click the Export button.

CHAPTER 6

Working with Services and Operations

This chapter contains the following information:WaveMaker Studio“About Services and Operations” on page 83“Calling Services” on page 83“Web Services” on page 88“JavaScript Services” on page 93“Java Services” on page 95

About Services and OperationsWaveMaker Studio applications treat everything as a service. Database interactions, web service interactions, custom Java code, all these are treated as services.

Each service is a group of one or more operations. Operations are defined actions that your application can invoke in order to make something happen. For example, a database service provides a variety of operations that allow you to interact with the database (such as update, delete, or insert).

Many operations involve a request to the server to take some action, such as updating a database, authenticating a user, and so on. Some operations can be executed entirely on the client, such as changing the active layer in a set of tabbed layers.

In a WaveMaker Studio application, a service can be a Database Service, a Web Service, a custom Java Service or a custom JavaScript service. WaveMaker Studio provides some predefined services. For example, the Security Service provides an operation to log out the current user (“The Security Service” on page 109).

Calling ServicesTo call a service operation, you create a Service Call. You can create the component at the page level or the application level and you can string

84 WORKING WITH SERVICES AND OPERATIONS

Service Calls together as well. This section explains how to create Service Calls:

“Creating a Service Call” on page 84

“Stringing (Queueing) Service Calls” on page 86“Service Call Properties and Events” on page 87

Creating a Service Call

To call an operation in a WaveMaker application, you create a component called a Service Call. At a minimum, a Service Call specifies the service and operation you want to invoke, and a source for any required inputs to that operation. Service Calls also have associated properties and events that you can use to further configure the call (“Service Call Properties and Events” on page 87).

To set up a Service Call, follow these steps:

1. Click the Design tab to open the Page Designer.

2. In the Model Tree on the right side of the Page Designer, click on the Components tab. The Components tab shows you the components (variables, service Calls and Navigations) that you have created for the current page, and also any components that you have defined on the Project level.

3. Select the location where you want to put the Service Call (either the current Page or the Project itself). When you define a component on the Project level, it is available on all the Pages in your project. Components defined on the Page level are accessible only on that page. In general, it is best to place your Service Call on the page where you need it (“Scoping” on page 22). By default, components are added to the current page.

4. Click on the cylinder icon. The “Configure Service Call” dialog appears.

CALLING SERVICES 85

5. At the very top of the screen there is a text field that contains the name of the Service Call. All Service Calls are automatically named, but it’s a good idea to change the name to something descriptive so that you will be able to identify the call later. Type in a name for the call.

6. From the Service pull-down menu, select the service you want to use. This list contains a service for each database, web service, and custom service you have imported. It also includes the Page and Layer services for page and layer navigation (“Navigation Between Pages and Layers” on page 23).

7. Once you select a service, the operations for that service populate the Operation drop down. Select the operation you want to call.

8. Next you can set up bindings for the operation’s inputs. If the operation you are calling does not have any required inputs then you do not need to do this. Otherwise, select a required input in the “Bind Targets” list.

9. After you select the input, go to the “Bind Sources” list on the right of the dialog, and select the source for the input data. The list includes all the widgets, Variables and Service Calls that you can choose for the input.

10.When you make your selection, a link icon appears over in the Bind Targets section of the screen. This shows that the binding is complete.

11.Repeat this process for each required input in the operation, and for any other inputs that you want to bind.

12.Click Close.

13.Save the project.

86 WORKING WITH SERVICES AND OPERATIONS

The Service Call component is complete. It appears in the Bind Source list and you can bind to it.

Stringing (Queueing) Service Calls

There are two ways to string together Service Calls: onResult . Service Calls have an event called “onResult” that allows you to specify a second Service Call to execute after the current Service Call completes. See “Setting Up an onResult Event” on page 87 for instructions. queue. Service Calls have a property called “queue” that allows you to specify a list of calls to execute after that Service Call executes. See “Setting Up a Service Call Queue” on page 86 for instructions.

The onResult option is simpler when you want to call Service Calls in a row. Queue is more powerful and clear if you're stringing together a number of requests.

Setting Up a Service Call Queue

A Service Call queue is a list of Service Calls that execute in order, one after the other. The queue is set up as a property on the first Service Call. To set up a Service Call queue, follow these steps:

1. Create all the service Service Calls that you need.

2. In the Model Tree, click the Component tab and select the Service Call that will execute first.

3. In the Property Editor, click the button next to the queue property (under the “Operations” heading). The Queue Services dialog box appears.

4. From the Select Service drop-down menu, select the next Service Call that you want to execute and then click the Add to Queue button.

5. In the same way, add the other Service Calls that you want to place in the Queue. You can move Service Calls around in the list by clicking on the Move Selected Up and Move Selected Down buttons. Service Calls will execute in the order they appear in this list.

6. Click OK.

Note that the queue will not proceed if there is an error condition along the way.

CALLING SERVICES 87

Setting Up an onResult Event

The onResult event is a property of a Service Call that allows you to specify a second Service Call to execute when the first is finished. To set this up, follow these steps:

1. Create all the service Service Calls that you need.

2. In the Model Tree, click the Component tab and select the Service Call that will execute first.

3. In the Property Editor, click the Events tab.

4. From the drop-down menu for the onResult event, select the second Service Call.

You can alternatively set up Navigation components, or custom JavaScript, instead of specifying a Service Call to execute.

Service Call Properties and Events

Service Calls have the following properties:

Service Calls have the following events:

Property Description

name Specifies the name that WaveMaker Studio uses to reference the widget. This is the name that appears in Model Tree, in the Page Builder, in binding dialogs, and so on; this is also the name you use to reference the widget in code services.

configure Launches a dialog for setting up bindings for Service Call inputs.

autoUpdate The component runs automatically. Also enables LiveLayout to populate the data directly in the WaveMaker Studio.

clearInput Clears all current input values.

operation The name of the operation you are invoking. The operation property is a drop-down menu from which you can choose any operation in the specified service.

service The name of the service that contains the operation you are invoking. The service property is a drop-down menu from which you can choose any service that you have added to your project.

updateNow Use to update the service call (with new input data) while in design mode

queue Defines a list of Service Calls to execute, in order, after this Service Call executes.

Event Description

onBeforeUpdate Called right before a service is updated. Allows you to programmatically put data into the service's input data:onBeforeUpdate(inSender, inInputData)

onError Allows you to trigger an action when the service call returns an error.

88 WORKING WITH SERVICES AND OPERATIONS

Web ServicesYou can access Web services in your WaveMaker Studio application by importing the service into the application and then creating Service Calls. REST, SOAP and RSS Web services are supported. This section contains the following topics:

“About Web Service Types” on page 88“Importing and Calling a SOAP or REST Service” on page 88“Importing and Calling RSS Feeds” on page 90

About Web Service Types

You can import the following types of Web services in your WaveMaker Studio application:

SOAP services. SOAP (Simple Object Access Protocol) is a standard XML protocol for exposing and calling Web services. A SOAP service is described by a Web Services Definition Language (WSDL) document, often available through a URL from the service itself. REST Services. A REST (Representational State Transfer) Web Service is comprised of resources accessed through unique URLs (requests) and returned as XML responses. An XML Schema typically defines the structure of those XML responses. In order to add a REST service to a WaveMaker Studio application, you need a WSDL document describing the service. Typically you create this WSDL file yourself. RSS Feeds. RSS (Really Simple Syndication) defines services that provide periodically-updated lists of items. Many Web sites now provide a syndication feed that news readers and blog summaries can subscribe to.

Importing and Calling a SOAP or REST Service

In order to import a SOAP or REST service into your WaveMaker Studio application, you need the WSDL (.wsdl) file that describes the service. For SOAP services, WSDL files are provided by the service creator. For REST services, you probably need to create your own WDL file.

Once you have located a WSDL file, import a SOAP or REST service, by following these steps:

onResult Allows you to specify a Service Call that executes when the current Service Call returns any result. For example, you can have serviceCallB go after serviceCallA by setting the onResult event of serviceCallA to be serviceCallB.

onSuccess onSuccess event: allows you to trigger an action when the service call succeeds.

WEB SERVICES 89

1. If you do not yet have a local copy of the .wsdl file, download it to a temporary location on your local file system. Be sure when you save the file from a URL you save it to a filename with the .wsdl extension.

2. Click on the Services tab in the Editor tab bar across the top of WaveMaker Studio.

3. The Services editor appears. On the left side of the Services editor, click the Add tab.

4. From the Service Type drop-down menu, select Web Service.

5. When you select the Web Service service type, the service configuration fields appear. Select the appropriate type (either SOAP or REST) from the Type drop-down menu.

6. For the WSDL Path field, click the Browse button and browse to the location where you saved the .wsdl file.

7. Click the Import button. WaveMaker Studio imports the .wsdl file. The Services editor shows the Configurations screen.

8. The Configurations screen is where you put authentication information required to access the Web service via HTTP. Most services do not require authentication and you can leave these fields blank. If the server does require authentication, fill in the appropriate fields with a valid username and password. You can optionally specify a connection timeout in milliseconds. Click the “Save” icon.

The Web service is now available in your WaveMaker application. It is listed in the Services List on the left side of the Service Editor. Expand the service to see all the service operations along with their inputs and outputs. You can bind these inputs and output to widgets in the Page Designer.

90 WORKING WITH SERVICES AND OPERATIONS

WaveMaker Studio has placed a copy of the .wsdl file in a service sub-directory under the project directory for this project. Click the WSDL tab to see the .wsdl file for the service. You cannot edit the .wsdl file here and we recommend that you do not edit it at all. If you do need to edit the .wsdl file (to change the service URL for example) find it under the directory for your project and edit it there. Delete the service from your application and re-import it using the same service name.

Importing and Calling RSS Feeds

RSS (Really Simple Syndication) Feeds are services that provide periodically-updated lists of items. Many Web sites now provide a syndication feed that news readers and blog summaries can subscribe to. This section explains both how to create the feed service and how to call it:

“Creating the Feed Service” on page 90“Calling the Feed and Displaying the Results” on page 91

Creating the Feed Service

To add a Feed Service to your application, follow these steps:

1. Click on the Services tab in the Editor tab bar across the top of WaveMaker Studio.

2. The Services editor appears. On the left side of the Services editor, click the Add tab.

3. From the Service Type drop-down menu, select Web Service.

WEB SERVICES 91

4. When you select the Web Service service type, the service configuration fields appear. Select Feed from the Type drop-down menu.

5. The WSDL Path field is disabled. Leave this field blank and click the Import button.

6. The new Feed service appears in the Services list on the left side of the Service editor. You specify the Feed URL as an input to the service so you do not need to define it in advance.

The fact that the feed URL is a service input allows you to bind the URL input to a widget such as a text editor or grid row. This gives you a lot more flexibility than you would have if the URL were a static part of the service configuration.

Calling the Feed and Displaying the Results

Once you create a feed service, you can call it in your application by creating a Service Call. Use a DataGrid widget to display the results. For example:

1. First create a new RSS Feed Service, called FeedService. (“Creating the Feed Service” on page 90 explains how to create the service.)

2. From the Components tab of the Model Tree, create a new Service Call (“Creating a Service Call” on page 84): ∞ The Service Call should call the getFeed operation in your

FeedService. ∞ Under “Bind Targets”, select url under the getFeed input.∞ Under “Bind Sources”, click the Expression tab and type in the

following URL in the Data Expression field:http://rss.news.yahoo.com/rss/topstories

92 WORKING WITH SERVICES AND OPERATIONS

Note that for the purposes of this example we are just using a static URL. You could just as easily bind the input URL to a widget on the page.

∞ Click the Close button to complete the Service Call configuration.

3. Back in the Page Designer, leave the new Service Call selected in the Model Tree and click to check the autoUpdate property check box.

JAVASCRIPT SERVICES 93

4. To display the results of the feed, we use a DataGrid. In the Page Designer, drag a DataGrid widget from the Palette and drop it on the Page.

5. In the Property Editor, click the button for the binding property. ∞ Under “Bind Targets” select the dataSet object for your DataGrid.∞ Under “Bind Sources” expand the Service Call you created for the

Feed and select the entries object.∞ Click the Close button to complete the Service Call configuration.

6. From the Property Editor, either add columns individually (addColumn) or add all the columns automatically (autoColumns).

View the feed results in the Page Designer with LiveLayout (“Live Layout” on page 15) or by running the project.

JavaScript ServicesYou can use your own client-side JavaScript to further customize your WaveMaker application. This section explains how to call custom JavaScript in WaveMaker Studio applications. This section discusses how and where you can call your custom JavaScript in a WaveMaker application:

“Executing JavaScript on Widget Events” on page 94“Executing JavaScript on Page Loading” on page 94“Executing JavaScript on Service Call Results” on page 94

For help writing custom JavaScript for WaveMaker applications, see “Customizing WaveMaker Applications with JavaScript” on page 117.

94 WORKING WITH SERVICES AND OPERATIONS

Executing JavaScript on Widget Events

To call JavaScript for a widget event, you select the widget, click the Events tab and choose the JavaScript option in the drop-down menu for the event. This automatically declares the appropriate function and opens the Source tab at the appropriate place.

For example, suppose you have a button named, “formSubmitButton” and you want to create custom JavaScript to execute when the user clicks this button. To set up the JavaScript you follow these steps:

1. In the Page Designer, select your button, “formSubmitButton”.

2. In the Property Editor, click on the Events tab.

3. From the resulting drop-down menu, select the JavaScript option. The WaveMaker Studio automatically opens the Script section of the Source tab and displays the following function stub:formSubmitButtonClick: function(inSender) {

},

4. Type in the JavaScript function that you want to execute on the button click.

Executing JavaScript on Page Loading

To set up JavaScript that executes upon the loading of the page, follow these steps:

1. Open the page you want to edit Designer.

2. Click on the Source tab and implement the start function. The start function executes when the page loads.

3. For example, you could type the following:start: function() {

console.log("Hello WaveMaker");},

This example uses the Firebug add-on to write to the console log (“Debugging with Firebug” on page 123).

Executing JavaScript on Service Call Results

In your JavaScript code, you can access the results of a Service Call by writing JavaScript code in the source for the onResult event of the Service Call. The onResult event is called upon the successful completion of the Service Call. In order to make this work, you first need to create a variable bound to the Service Call output. Then you can access that variable in your code.

JAVA SERVICES 95

For example:

1. Create a Service Call component called getCustomer. This Service Call uses the getCustomerById operation in a service called “cmdb”. (To get this service, you can import the cmdb HSQLDB database that is included in the WaveMaker Studio installation.)

2. Create a variable component called myCustomer of type cmdb.data.Customers (this type appears in the list of data types after you import the cmdb database). Bind the variable to the output of the getCustomer Service Call.

3. Select the getCustomer component in the Components tab in the Model Tree.

4. In the Property Editor, select the Events tab.

5. For the onResult event, select JavaScript from the drop-down menu. The Script source tab opens with a stub function that runs on a successful result from the getCustomer Service Call.

6. Add your own JavaScript to implement this function. For example, the following code accesses the variable data and concatenates the contactfirstname and contactlastname name fields together into a variable called customerName:

customerName = this.myCustomer.getValue("data").contactfirstname + " " + this.myCustomer.getValue("data").contactlastname;

Java ServicesThere are two basic ways to add Java code to your WaveMaker project:

Write your own custom Java code (“Creating and Calling a Custom Java Code Service” on page 95)Integrate pre-existing code that is already written and available in either .java or .jar files (“Integrating Existing Java Code” on page 101)

The examples at the end of this section should help you get started (“Custom Java Service Example” on page 101).

Creating and Calling a Custom Java Code Service

To create a custom Java service in WaveMaker Studio, follow these general steps:

96 WORKING WITH SERVICES AND OPERATIONS

1. Click on the Services tab in the Editor tab bar across the top of WaveMaker Studio.

2. The Services editor appears. On the left side of the Services editor, click the Add tab.

3. From the Service Type drop-down menu, select Java.

4. When you select the Java service type, the following Java service configuration fields appear:∞ Service ID - a user friendly name to reference your Java Operations∞ Class Name - the name of the Java class

5. Click the Create button. WaveMaker Studio creates a Java file and a stub for you. When you click the Create button to create the Java service, the stub file automatically opens in the Code editor and you can see the service in the Services list to the left of the Code editor.

JAVA SERVICES 97

6. Type in your Java code. The following simple example method takes a string parameter and returns a string comprised of “Hello “ followed by the value of the parameter:public class TestClass {

public String myMethod(String myParameter) {

return "Hello " + myParameter;}

NOTE: Private classes are not supported as services in WaveMaker Studio. For example, if you have the following:public class A{}class B{}

Class B is private, and you the Server will not be able to access it. To use class B, you would need to either make it a public static inner class:public class A{ public static class B{}}

or define it in its own file.

7. Be sure to save the code by clicking the Save icon at the top of the Code editor.

When you save your code, the new Java service appears in the Services list. Each method is listed, along with its inputs and outputs.

98 WORKING WITH SERVICES AND OPERATIONS

You can now call your Java service operations by creating Service Calls, just as you would call any other service operation. For example, assume you created the Java service shown in preceding steps:

The name of the service is:TestClass

It contains a single method called:myMethod

myMethod has one input parameter (a string) called:myParameter

The method returns the following string:"Hello " + myParameter”

In this example, we’re going to create a panel that contains a text input field, a button and a label. When the user types something in the field and clicks the button, the application calls the myMethod operation with the user’s input as the input parameter. You would set this up as follows:

1. In the Page Designer, drag a Panel onto the page.

2. Next drag an Editor widget, a Button widget and a Label widget into the panel.

3. Create the Service Call. From the Components tab of the Model Tree, create a new Service Call (“Creating a Service Call” on page 84): ∞ Type in a name for the Service Call.∞ For the service, select your custom Java service (TestClass). ∞ For the operation, select the myMethod operation.∞ Under “Bind Targets”, select arg1 under input.∞ Under “Bind Sources”, select the dataValue object from your Editor

widget.

JAVA SERVICES 99

∞ Click the Close button to complete the Service Call configuration.

4. In the Page Designer, select the Button widget. For the onClick event, select the Service Call component you created for your Java service operation.

100 WORKING WITH SERVICES AND OPERATIONS

5. In the Page Designer, select the Label widget. In the Property Editor, click the button for the binding property. ∞ Under “Bind Targets” select the caption object for your Label.∞ Under “Bind Sources” find your Java Service Call component and

select the string that it returns.

∞ Click the Close button to complete the Service Call configuration.

6. Save and run your project.

JAVA SERVICES 101

Integrating Existing Java Code

To integrate existing Java code into your WaveMaker application, you first need to put the .jar file or the .java files in the lib directory for your WaveMaker project. For example, if your project is called MyFirstApp, the path for the lib directory would look something like this:C:\Documents and Settings\username\My Documents\WaveMaker\Projects\MyFirstApp\lib

NOTE: The exact path name depends on your username and the location of your WaveMaker Projects directory. The above path would be right for a default WaveMaker installation on Windows.

After you place the files in your project directory, the classes are available to you at development time. You can import them in your custom Java code. When you deploy your application, these classes will be included in the WEB-INF\lib of the generated WAR file.

To register the new class as a custom service, you need to follow the steps described in “Creating and Calling a Custom Java Code Service” on page 95 to create the Java service and stub file. Cut and paste your existing Java code into the Java stub file and save from the Code editor.

Custom Java Service Example

This section provides a Java code service example. You can find this and other examples posted on the WaveMaker developer forum at:

dev.wavemaker.com

This example shows how to create a custom Java code service that accesses elements in the Data model using Hibernate methods. In this example, we create a Service Call that checks whether a record exists and does one of the following things:

if the record exists, the operation updates the databaseif the record does not exist, the operation inserts the new record in the database

Hibernate contains many methods to assist with common database chores such as this. For this example, there is a Hibernate method called saveOrUpdate(). You can access this method using a custom code Service Call.

For this example, assume your database has a table in it called “Employees”. To set up the custom service, follow these steps:

1. Create a Project called:myTestApp

2. Import a database called:

102 WORKING WITH SERVICES AND OPERATIONS

myDB

3. Create a new Java service (the steps for doing this are explained in “Creating and Calling a Custom Java Code Service” on page 95):∞ For the Service Type field, select Java.∞ In the ServiceID field, type:

myCustomJavaServiceID

∞ In the Class Name field, type:MyAddOrUpdateEmployeeClass

∞ Click Create. After you click the Create button, the Source editor opens, displaying the following (empty) class:public class SaveOrUpdateEmployee {

}

4. Edit the class so that it looks like this:import com.activegrid.runtime.AGRuntime; // WaveMaker Runtime Classimport com.wavemaker.mydb.MyDB; // the MyDB Class, ie $PROJECT_HOME\Projects\myTestApp\services\myDB\src\com\wavemaker\mydb\MyDB.javaimport com.wavemaker.mydb.data.Employee; // The Employee Classimport org.hibernate.Session; // Session Class

public class MyAddOrUpdateEmployeeClass {

private MyDB foo = (MyDB)AGRuntime.getInstance().getService("myDB"); // Instantiate a MyDB called foo based on the myDB name we created

public String saveOrUpdateEmployee(Employee employee) { foo.begin(); // Begin the transaction try { Session session = foo.getDataServiceManager().getSession(); // Get the Hibernate session session.saveOrUpdate(employee); // Save or Update foo.commit(); // Then commit } catch (RuntimeException ex) { foo.rollback(); throw ex; } return "success"; }

}

5. Click the Blue Disk Button above the Code Editor Pane to Save. (You should get a message stating “Saving Java Service. If you don’t, you hit the wrong button!)

6. Click the Save Project Button

7. Open the Page Designer.

8. Drag a Panel widget onto the Page.

9. Drag into the Panel:∞ an Editor widget∞ a Button widget

JAVA SERVICES 103

10.Create the Service Call. From the Components tab of the Model Tree, create a new Service Call (“Creating a Service Call” on page 84): ∞ In the Configure Service Call field, type:

myCustomHibernateCall

∞ From the Service menu, select your custom Java service (TestClass).

∞ From the Operation menu, select the myMethod operation.∞ Under “Bind Targets”, select arg1 under input.∞ Under “Bind Sources”, select the dataValue object from your Editor

widget.∞ Click the Close button to complete the Service Call configuration.

11.In the Page Designer, select the Button widget. For the onClick event, select the Service Call component you created for your Java service operation (myCustomHibernateCall).

Run it! Now you can saveOrUpdate, based on the presence or non-existence of a record!

104 WORKING WITH SERVICES AND OPERATIONS

CHAPTER 7

Setting up a User Login Page

Your WaveMaker Studio application can include a login page that requires users to sign on in order to gain access to the application. In order to set up user authentication you need set up a data source that stores your user IDs and passwords. You have the following options for storing this data:

You can use any database supported by WaveMaker Studio. You can use LDAP (Lightweight Directory Access Protocol).

WaveMaker Studio also provides a simple “demo” data source. You can use this data source to set up and test your login page during development.

“How to Set Up a Log In Page” on page 105“Using the Demo Data Source for Login Data” on page 107“Using a Database for Login Data” on page 107“Using LDAP for Login Data” on page 108“The Default Login Page” on page 108“The Security Service” on page 109

How to Set Up a Log In PageTo set up a login page for your application, follow these steps:

1. Set up your data source.

2. Run WaveMaker Studio and open your project.

3. Click the Security tab. The Security Editor appears.

106 SETTING UP A USER LOGIN PAGE

4. In the Data Source pull-down menu, select the type of data source you want to use. You can choose Database, LDAP or Demo. When you make your selection, the configuration editor for that data source appears at the bottom of the Security Editor (default is Demo).

5. Make the appropriate selections for your data source in the configuration editor. This will depend on what type of data source you are using:∞ “Using a Database for Login Data” on page 107∞ “Using LDAP for Login Data” on page 108∞ “Using the Demo Data Source for Login Data” on page 107

6. Click to check the Authentication On check box. As you develop your application, you can use this check box to toggle the authentication on and off. That way, when you preview your application, you don’t have to log in every time.

7. Click the Save Configuration button. When you save a security configuration, WaveMaker Studio adds the security service and a default login page to your project.

8. Save the project. The default login page (“The Default Login Page” on page 108) is now listed under Pages in the Dashboard. (You might need to refresh in order to see this page.)

USING THE DEMO DATA SOURCE FOR LOGIN DATA 107

9. Preview the application. The default Login page appears. Try logging in.

Using the Demo Data Source for Login DataThe Demo data source provides a great design-time tool for authentication. With this data source you can quickly define a few usernames and passwords to use while creating and testing the login functionality for your application. Before you deploy your application, you should set up a more robust data source for authentication.

To set up To set up authentication against a the Demo data source, click the Security tab and choose Demo for the Data Source type. The Demo Data Source configuration editor appears.

To add a new user to the Demo data source:

1. Type the name in the Username field.

2. Type the Password in the Password field.

3. Click the Add button (plus sign).

To delete an existing user from the Demo data source,

1. Select the user in the list.

2. Click the Delete button (X).

The Demo data source automatically includes one default user name (demo) and password (demo).

Using a Database for Login DataIf you’re using a database to store your authentication data, then you first need to import the database you plan to use. The database must include a table that provides a column for your user names and one for the passwords. The user names and passwords must be stored in the same table in the database.

To set up authentication against a database, click the Security tab and choose Database for the Data Source type. You need to provide the following configuration information:

108 SETTING UP A USER LOGIN PAGE

Be sure to save the configuration (click the Save Configuration button) before testing the authentication.

Using LDAP for Login DataTo set up authentication against a database, click the Security tab and choose LDAP for the Data Source type. You need to provide the following configuration information:

Be sure to save the configuration (click the Save Configuration button) before testing the authentication.

The Default Login PageWaveMaker Studio provides a simple login page for you. Whenever you save an authentication configuration, WaveMaker Studio checks to see if you have a login page in your project. If you don’t, WaveMaker Studio will add the default login page to the project.

Data Model The Data Model that contains the columns for the for username, password. Choose the Data Model from the pull-down menu. (You have to import the database first. If you have imported the database and it does not appear in this list, try saving the project and refreshing the page).

Entity Select the table that contains the columns for the user names and passwords.

User Name Field Select the column for the user (login) name.

Password Field Select the column for the password.

Property Description

LDAP URL This field specifies the host name and port number of the LDAP server.

ldap://localhost:389/dc=wavemaker,dc=com

Manager DN The DN for the account that you use to access LDAP.

Manager Password The password for the account that you use to access LDAP.

User DN Pattern Sets the pattern that WaveMaker Studio uses to create a DN for the user. The pattern should be the name relative to the root DN. The pattern argument {0} will contain the username. For example:

"cn={0},ou=people"

THE SECURITY SERVICE 109

You can customize the login page, but do not rename it. If you do, WaveMaker Studio will not recognize it as the login page.

The Security ServiceWhen you create a security configuration for your project, WaveMaker Studio adds a Security Service to your project. The Security Service contains two operations:

getUserName: Use this operation to get the username of the current user. The operation takes no inputs and returns a string containing the userid of the user that is logged in on the current session.

logout: Use this operation to log a user out. This operation takes no inputs. When you call it, it logs out the current user and terminates the session.

110 SETTING UP A USER LOGIN PAGE

CHAPTER 8

Projects and Project Files

This chapter contains the following sections:“WaveMaker Project Directory Structure” on page 112“Importing and Exporting Projects” on page 111“Enable Project Loggers” on page 112“WaveMaker Project Directory Structure” on page 112

Importing and Exporting ProjectsThe current support for exporting projects is mainly intended to facilitate mailing projects to our support staff:

“Exporting WaveMaker Projects” on page 111“Importing WaveMaker Projects” on page 111

Exporting WaveMaker Projects

WaveMaker Studio can export projects in zip format to facilitate sharing of projects through email. To export a WaveMaker project, follow these steps:

1. Open the project in WaveMaker Studio and click the Dashboard tab to open the Dashboard.

2. In the Dashboard under the “Administration” heading, click the Export Project button.

3. The exported file will be in your project directory under export/<project name>.zip.

The export zip file will include the project directory and everything underneath it that cannot be recreated by another installation of the studio.

Importing WaveMaker Projects

To import a WaveMaker project, simply unzip the file into the directory where your projects are located. If there is already a project with that name it should be deleted beforehand.

112 PROJECTS AND PROJECT FILES

The project will now appear in the list of projects (a refresh may be required).

Generating a WAR FileWaveMaker Studio can generate a WAR file for your project, which you can deploy on any application server. To create a WAR file, follow these steps:

1. Open the project in WaveMaker Studio and click the Dashboard tab to open the Dashboard.

2. In the Dashboard under the “Administration” heading, click the Generate WAR File button.

3. WaveMaker Studio creates a WAR file for you (this might take a few minutes) and places it in your project’s dist directory for your project. WaveMaker displays an alert when the WAR file has been successfully generated.

Enable Project LoggersThe log4j.properties has many useful loggers you can enable. The file is located under the project directory in the webapproot/WEB-INF/classes directory. Reload the application for the changes to take effect.

For example, to see the SQL and Bind Parameters sent to the database, enable the following Hibernate loggers: log4j.logger.org.hibernate.SQL

log4j.logger.org.hibernate.type

WaveMaker Project Directory StructureWaveMaker Studio generates a project directory and a set of files for each application built using WaveMaker. All of the project files created by the WaveMaker Studio are human-readable files. Many of the files can be edited outside of the Studio using tools like Eclipse. These project files are used to generate a Java WAR file that can be deployed into any Java server.

This section covers the following topics:“Project File Types” on page 113“Project File Structure” on page 113“Service Directory Structure” on page 113“Webapproot Directory Structure” on page 114“Page Container Directory Structure” on page 115

WAVEMAKER PROJECT DIRECTORY STRUCTURE 113

Project File Types

WaveMaker Studio project files include:HTML files: stored in the webapproot/ directory as index.html

Custom code: stored in the services/ directory or as JAR files in the lib/ directoryWeb services: stored in the services/directory as POJO classes and JAX-WS configuration filesDatabase configuration: stored in the services/directory as standard POJO classes and Hibernate configuration filesServer configuration: stored in the webapproot/web-inf/ directory as Spring configuration files

Project File Structure

The top level of a WaveMaker Studio project contains four directories. These are:

services directory: contains service definitions, classes, and everything else needed for a service (including database, security, web services and custom services); services directory does not appear in projects that do not have any serviceswebapproot directory: contains the root of the standard web applicationsrc directory: contains project-wide source (including the log4j configuration)lib directory: contains project-wide libraries (empty by default)

Service Directory Structure

WaveMaker treats almost everything as a service, including security, data access, custom code and SOAP, REST and WSDL services. The files generated for each service follows the same general pattern:

<project_name>/ services/ <service_name>/ src/ designtime/ servicedef.xml

The servicedef.xml file provides information used at design-time on the services operations (and their parameters and returns), and the types associated with a service. The src directory contains any necessary source for the service.

The service directory structure includes:

114 PROJECTS AND PROJECT FILES

For Java services: the source directory contains files created using a tool like Eclipse. Java source can also be imported in a jar in the top-level lib directory. For Database services: source directory contain WaveMaker-generated source to define the java data objects, the Hibernate queries (foo.ql.xml)and the Hibernate mapping (foo.hbm.xml). For Web services: the source directory contains a Java representation of the WSDL and the JAXWS schema file (foo.xjb).

Webservice services' source directories contain generated source (again, non-user editable), and generally the WSDL file they were generated from.

Generally, each service has a single service class (which contains methods that are exposed to the client), and one class per datatype associated with that service.

A typical data service will look like this: <projectName>/ services/ sakilalight/ src/ sakilalight.properties sakilalight.spring.xml com/ wavemaker/ data/ Sakilalight.java sakilalight/ City.ql.xml Actor.ql.xml Country.java FilmActor.hbm.xml City.java Actor.java Address.hbm.xml FilmActor.ql.xml Film.hbm.xml Address.ql.xml designtime/ servicedef.xml

The .properties and .xml files contain standard Hibernate metadata. The Sakilalight.java contains the main service class, and all other .java files contain types.

Webapproot Directory Structure

The webapproot directory follows the typical structure for web applications. For example, this is where the index.html page is located, as well as the project level JavaScript file. The panes directory contains individual page container definitions. webapproot/ WEB-INF/ <projectname>.js index.html services/ <serviceName>.smd

WAVEMAKER PROJECT DIRECTORY STRUCTURE 115

panes/

The index.html and <projectname>.js files provide an entry point to the system, and bootstrap the AJAX interface.

The WEB-INF directory contains the web.xml file, as well as XML files that specify the Spring configuration. Also, all compiled service classes (from services/<svcsname>/src), and classes from the top-level src directory, are copied into WEB-INF/classes. Libraries from the top-level lib directory are copied into WEB-INF/lib.

The services directory contains a series of SMD files (one per service) with the service definition information. These are basically a translation of the information from the servicedef.xml, which is located in services/<servicename>/runtime.

Page Container Directory Structure

Each page container has its own directory that stores configuration information about that page as well as the widgets and styling for that page:panes/ <paneName>/ <paneName>.css <paneName>.html <paneName>.js <paneName>.widgets.js

The panes directory provides information specific to each page container.

The css file provides CSS for that page; the HTML contains snippets for use in the page container; the .widgets.js provides a definition of the page layout and components; and lastly, the .js file contains any custom JavaScript associated with the page container.

116 PROJECTS AND PROJECT FILES

APPENDIX A

Customizing WaveMaker Applications with JavaScript

You can use your own client-side JavaScript to customize your WaveMaker application. Any JavaScript that your target browsers support can be used in a WaveMaker application.

This chapter explains how to incorporate your JavaScript into your WaveMaker application and provides some information about how your JavaScript can interact with your project components. It assumes you are already familiar with JavaScript.

“Working with Widgets” on page 117“Executing Service Calls in Your JavaScript Code” on page 120“Setting Data Properties” on page 120“Referencing Components at Runtime” on page 121“Object Structure on the Client” on page 121“Commonly Used Utilities” on page 122“Debugging with Firebug” on page 123

For information on how to call JavaScript from your application, see “JavaScript Services” on page 93.

Working with WidgetsThis section has the following topics:

“Accessing a Widget in JavaScript” on page 118“Setting Widget Properties” on page 118“Referencing the Calling Widget in an Event” on page 119“Clearing Data Input Fields in JavaScript” on page 119“Creating Widgets at Runtime” on page 119

118 CUSTOMIZING WAVEMAKER APPLICATIONS WITH JAVASCRIPT

Accessing a Widget in JavaScript

In your page code, you can use the syntax this.foo to specify a widget or component on the page. “this” refers always to the current page and “foo” would be the name of the component or widget.

You use the value of a widget’s name property to specify the widget. So, suppose you want to refer to a panel widget that has a name property set to “panel1”. If the panel widget is on the current page, you can refer to it like this:this.panel1

Setting Widget Properties

For widgets, anything that shows in the Property Editor is a property that you can set on the widget in your code. To access these properties, use getValue and setValue. These two methods are available to all components.

getValue("propertyName")

setValue("propertyName", value)

For example, to set the value of the showing property on a panel widget called “panel1”, you would use:this.panel1.setValue("showing", true);

This sets the value of the showing property to “true” making the panel and its contents visible. To hide the panel, you could set the value of the showing property to false:this.panel1.setValue("showing", false);

To set the value of the caption property on a label widget called “label1”, you could use:this.label1.setValue("caption", "Hi");

To get the existing value of a property on a specific widget, use the generic getValue syntax. You can use getValue for any widget property that appears in the Property Editor. For example, to get the value of the size property on a panel widget called “panel1”, you would use:this.panel1.getValue("size");

This returns the value of the size property on panel1.

To get the value of the disabled property on a Button widget called “button1”, you could use:this.button1.getValue("caption");

You can use getValue and setValue together, to toggle between two values of a boolean type widget property. For example, suppose you have an

WORKING WITH WIDGETS 119

AutoForm widget called autoform1. AutoForm widgets have a readonly property which can be either true or false. To toggle the value of the readonly property, you could use the following syntax:this.autoform1.setValue(“readonly”, !this.autoForm1.getValue(“readonly”));

To set a label to the current date, set the display property of the label to Date and insert the following line in an entry point such as the start function for the page:this.label3.setValue(“caption”, new Date().getTime());

Referencing the Calling Widget in an Event

Use inSender to refer to the calling object in an event. Every widget event is passed the inSender reference. For example, in the onclick event for a button, the reference to the button that was clicked is available via inSender. Use the inSender reference as you would a reference to any widget with this or app.

Clearing Data Input Fields in JavaScript

It is often necessary to clear the data input fields upon completion of an operation. For an editor named “editor1” the data value can be nulled by calling:this.editor1.clear();

Normally this would be done in the onResult event for a Service Call which is triggered upon successful completion of the Service Call.

If you’re using a turbo.AutoForm, you can use the _clearEditors method to clear each editor.If your editors themselves get values from a grid selectedItem, then they can be cleared by clearing the grid selection using:dataGrid.clearSelection()

If your editors themselves get values from a variable, then you can clear the variable using:this.variable.setData()

Creating Widgets at Runtime

To create widgets at runtime, use the .loadComponent method. The syntax for .loadComponent is:parentWidget.loadComponent(inName, inType, inProps);

For example:this.panel1.loadComponent("myLabel", "turbo.Label", {caption: "I made this!"});

120 CUSTOMIZING WAVEMAKER APPLICATIONS WITH JAVASCRIPT

After you create the new widget, you need to re-render the parent widget so that the new widget is included:this.mylabel.reflowParent();

You can destroy objects at runtime with object.destroy.

Executing Service Calls in Your JavaScript CodeService Calls can be executed in JavaScript by calling the update function. For example, suppose you created a Service Call component at the page level and you named it pageLevelServiceCall1. From that page, you can execute the Service Call like this: this.pageLevelServiceCall1.update();

Now suppose you create a Service Call component at the application level (rather than at the page level) and you named it appLevelServiceCall1. You can execute this Service Call on any page by calling:app.appLevelServiceCall1.update();

You can’t pass any parameters to the update function. The function relies on the existing input and output bindings of the Service Call.

Service Calls have an event called onBeforeUpdate that allows you to put data into the Service Call right before the service is updated. This allows you to programmatically put data into the service's input data. The syntax for onBeforeUpdate is:onBeforeUpdate(inSender, inInputData)

You can also put data into a serviceCall input manually before you call update().

Setting Data Propertiesturbo.Variable is a container for structured data. It’s typically used to store data that is retrieved from a web service or a database. turbo.ServiceCall is a turbo.Variable subclass. You can use the setValue and getValue functions to manipulate data on turbo.Variable.

For example, if you have a turbo.Variable that stores an object corresponding to a row in a “customers” table, you could call setValue to set the customer name as follows:this.customerVariable.setValue(“customerName”, “bob”);

and you could retrieve this value using getValue:this.customerVariable.getValue(“customerName”);

REFERENCING COMPONENTS AT RUNTIME 121

The input data for a turbo.ServiceCall is also a turbo.Variable. You can set its values manually in the same way (“Executing Service Calls in Your JavaScript Code” on page 120).

Referencing Components at RuntimeIn your page code, you can use the syntax this.foo to specify any component that is scoped to that page. “this” refers always to the current page and “foo” would be the name of the component.

For project -level components, you need to use the global object app to reference the application itself. At runtime, called app always owns the loaded page.

For example, if you create a Variable component named myVariable (scoped to the project, rather than the page) you can reference that Variable from any page as:app.MyVariable

Object Structure on the ClientIn order to work with your WaveMaker application in custom code, you may want to know something about the object structure on the client. Briefly, the root level client side object is called turbo.Object. Below that, the component object (turbo.Component) is the top-level object that is designable in the WaveMaker Studio.

Widgets (turbo.Widget), pages (turbo.Part) and variables (turbo.Variable) are all components. Service Calls are a subclass of variable and Navigation is a subclass of Service Call.

122 CUSTOMIZING WAVEMAKER APPLICATIONS WITH JAVASCRIPT

At runtime, a global object called app always owns the loaded page. When you run a project, the root runtime object is turbo.Application; turbo.Application loads the main page.

Commonly Used UtilitiesThis section discusses some utilities that you are especially useful in WaveMaker applications:

“CSS Utilities” on page 122“The “Connect” Utility” on page 123

CSS Utilities

Dojo provides some CSS related utilities. The following are especially useful in WaveMaker applications:dojo.addClass(domNode, ”classname”)

where classname is a string representing the new CSS class name. For example:dojo.addClass(this.domNode, “customPanel”)

dojo.removeClass(domNode, classname”)

DEBUGGING WITH FIREBUG 123

where classname is a string representing the CSS class name that you want to remove. For example:dojo.removeClass(this.domNode, “customPanel”)

dojo.hasClass (domNode, “classname”)

where classname is a string representing the CSS class name that you are checking for. If the specified node has the specified classname, then dojo.hasClass returns true. If not, it returns false.

The “Connect” Utility

WaveMaker provides a utility that fires a target method on a target object after a source method on a source object has been called. This utility is used in the context of a component, (such as a page or a widget). The syntax is:connect (srcObject, “srcMethod”, destinationObject, “destinationMethod”)

For example:connect(this.domNode, “onmouseover”, this, “mouseout”)

This “connect” utility is actually a wrapper for the dojo.connect utility. The connect utility does the cleanup “disconnect” for you, so that you do not have to call dojo.disconnect.

Debugging with FirebugThe Firefox add-on, Firebug, provides several useful debugging tools. it is strongly recommended that you have Firebug enabled while developing with WaveMaker. To download Firebug, go to:

http://getfirebug.com/

This section contains the following topics:“Running WaveMaker Studio in Debug Mode” on page 123“Firebug Status Bar” on page 124“Printing to the Firebug Console” on page 124“Firebug Command Line” on page 124

Running WaveMaker Studio in Debug Mode

WaveMaker Studio provides two startup options, regular or debug:The regular mode runs WaveMaker using a Dojo “build” for efficiency. This build combines and compresses the Dojo files into fewer, larger files that are easier for the browser to quickly load and parse. Consequently, those files are more difficult to get meaningful error messages out of in Firebug.

124 CUSTOMIZING WAVEMAKER APPLICATIONS WITH JAVASCRIPT

The debug mode does not use this Dojo build. In debug mode, the WaveMaker Studio files are uncompressed so that they are more readable editable. The debug version is very useful for debugging your application with Firebug.

Firebug Status Bar

Firebug lets you know of errors within your application with a status bar error indicator. Watching the status bar indicator will quickly let you know when there is a problem.

Printing to the Firebug Console

From within any JavaScript function, informational statements and variables can be printed out the Firebug console using console.log(). To log a static string to the console use:console.log("Hello WaveMaker");

Firebug Command Line

Firebug provides a command line for testing your code without editing your source files. To use the Firebug command line, open Firebug, click the Console tab, and type your JavaScript at the command prompt. Here are a few suggestions:

To enable debug information on studio widgets, use:turbo.logging=true;

To use Firebug to directly inspect components or widgets at design time, use:studio.part.widgetname

For example, to null the data value of an editor1 on the main page from the Firebug console use:studio.part.editor1.setValue("dataValue", null);

To use Firebug to directly inspect global variables at design time, use:studio.part.app.variablename

NOTE: Note that within the Firebug console, you cannot use “this” to refer to the current page. Instead, you need to use “studio.part”.

You can get a lot of information at design time, through LiveLayout and through the Firebug console. However, note that page code is not run at design.

To inspect a component at runtime, use the pagename.component syntax for components scoped at the page level:main.label1

or app.component for components scoped at the project level:

DEBUGGING WITH FIREBUG 125

app.myVariable

126 CUSTOMIZING WAVEMAKER APPLICATIONS WITH JAVASCRIPT

APPENDIX B

Creating Custom Widgets

You can make your own custom widgets accessible in your WaveMaker applications and you can customize existing WaveMaker widgets. Customizing widgets requires some knowledge of JavaScript.

In order to create and use a custom widget in WaveMaker, you need to do three things:

1. Create a module file that defines the widget (“The Widget Module File” on page 128).

2. Add design-time support for the widget (“Adding Studio Support for the Widget” on page 132).

3. Add runtime support for the widget (“Adding Runtime Support for the Widget” on page 133).

When you export the project or generate a WAR from the project, the new custom widget will be included. WaveMaker Studio provides an example custom widget in the Custom section of the Palette.

128 CREATING CUSTOM WIDGETS

The Widget Module FileYou define a custom widget in a module file. The widget module file is a JavaScript module with the .js extension. A single module file can contain many widgets. Each widget within the module must have a unique widget name. Most custom widgets extend an existing widget, but you can also create an entirely new widget.

Here’s an example:dojo.provide("wm.packages.example.CustomWidgets");dojo.require("turbo09.widget.Label");

dojo.declare("turbo.WMLink", turbo.Label, {caption: "WaveMaker",link: "http://dev.wavemaker.com"

});

The example above contains the three function calls that you use in your widget module file:

1. dojo.provide("moduleName");

The dojo.provide statement declares the module this file will provide. The moduleName is the path of the widget module file (without the common folder) relative to the studio/static directory (“Widget Module File Location” on page 132). The moduleName uses dots (.) rather than slashes (/) in the path. For example, if our module file is named CustomWidgets, our module name would be wm.packages.example.CustomWidgets and our dojo.provide statement would look like this:dojo.provide("wm.packages.example.CustomWidgets");

2. dojo.require("moduleName");

The dojo.require statement states what modules need to be imported for this module. If you are extending an existing widget, then you need to import the module that defines the widget you are extending. For example, if we want to extend the WaveMaker Label widget, we would need the module for the Label widget:dojo.require("turbo09.widget.Label");

All the predefined WaveMaker widget module files are located in the WaveMaker installation directory in the following directory:studio\static\turbo09\widget

3. dojo.declare("widgetClassName", baseClassWidget, {/*widget body*/});

where:∞ widgetClassName is the class name of the widget you are creating.∞ baseClassWidget is the name of the widget that you are extending, if

any.

THE WIDGET MODULE FILE 129

∞ {/*widget body*/} contains the body of your widget declaration. This includes any properties (“Widget Properties” on page 130) and events (“Widget Events” on page 130) that you want to expose to users in the WaveMaker Studio.For example, the following widget’s class name is turbo.WMLink and it has predefined values for the caption and link properties.dojo.declare("wm.example.WMLink", turbo.Label, {

caption: "WaveMaker",link: "http://dev.wavemaker.com"

}

Before you can use the new widget, you need to:Put your widget module file in the WaveMaker custom widget directory (“Widget Module File Location” on page 132)Add it to the WaveMaker Studio (“Adding Studio Support for the Widget” on page 132)Add it to the Runtime (“Adding Runtime Support for the Widget” on page 133)

Defining Widgets

WaveMaker widgets are closely related to Dojo's Dijit widgets. More information about the Dojo toolkit and the Dijit project is available at http://dojotoolkit.org.

Here are a couple of tips on widget creation:The easiest way to create a new widget is to use an existing widget as your base widget. All the functionality, events and properties that the base widget provides are already there and you can customize them to meet your needs. You specify the base widget in the dojo.declare statement. You will also need to import the widget’s module in the dojo.require statement.If you want to create a widget that can contain other widgets, use the Panel widget as your base widget.The init function is the primary access hook to the underlying HTML of a widget. Here we’ll implement the init function to create a div node, called myPetNode and append it to the DOM as a child node.init: function() {

this.inherited(arguments); this.myPetNode = document.createElement('div'); this.domNode.appendChild(this.myPetNode);

}

The life cycle for WaveMaker widgets is something like this:

Creation:

130 CREATING CUSTOM WIDGETS

1. construct: all constructors are invoked starting with base classes and working up to the sub class.

2. create: create method is invoked which calls:a. prepare(inProps): copies the properties inProps that came from the

constructor, i.e. when you do new Foo({ ... }), the { ... } are inPropsb. build: setup any needed DOM, responsible for setting domNode

property (note: does not call setDomNode)c. init: do whatever else you want to do to initialize your widget (the

init function in Widget calls setDomNode, which triggers the initDijit as noted above).

d. postInit: hook to do other stuff (rarely needed)

Destruction:

1. destroy: call destroy to kill a widget. Various classes override destroy to do custom cleanupa. turbo.Dijit calls this.dijit.destroy(), then calls inherited

(turbo.Widget) destroyb. turbo.Widget destroys all child widgets, and does various other

cleanup tasks.

Typically one overrides init to do setup, and destroy to do cleanup. The rest are not usually needed. For Dijits, you may also want to override initDijit and do setup on the Dijit after calling the superclass function.

Widget Properties

Any properties that you define in dojo.declare are automatically shown as properties for that widget in the Property Editor. You can also provide default values for new and existing properties.dojo.declare("wm.example.WMLink", turbo.Label, {

caption: "WaveMaker",link: "http://dev.wavemaker.com"

For each new property you define, you can create get and set functions (for example for the caption property, you could create getCaption and setCaption functions). Define these in the widget declaration section of the dojo.declare function.

Widget Events

To add an event to a widget, you need to do two things:Declare the event in dojo.declare (“Expose the Event in the Property Editor” on page 131)Make the event fire (“Make the Event Fire” on page 131)

THE WIDGET MODULE FILE 131

Expose the Event in the Property Editor

In your widget definition (in dojo.declare), any function that has a name starting with “on” is automatically treated as an event. For example, functions named onclick, onmouseover, onguard, ontop, would all be treated as events.

Typically you just declare the function and leave it as an empty stub:onWMclick: function() {},

Now the widget has an event called onWMclick. In the Property Editor, the event is listed in the Events tab. Here, application developers can set up whatever behavior they want this event to trigger, using a Service Call, Navigation Component, custom JavaScript, etc.

When a user creates custom JavaScript for your event, the function for that event has one extra argument (not present in the widget definition) the inSender argument.

For example, in the dojo.declare in your custom widget module, you define the following event on your custom widget:

onWMmouseout: function(inEvent) {},

Working in the WaveMaker Studio with the code for the very same event, the function looks like this:function(inSender, inEvent) {

},

The inSender references the widget that fired the event. In a WaveMaker Studio application, events are called in the context of the page. The keyword this refers to the page and this.customerEditor would refer to a widget of that name on the page, while inSender.caption would refer to the caption property of the widget that fired the event.

This setup provides convenient access to all widgets and components defined on the page while still providing anonymous access to the widget that fired the event.

It’s your job to make sure that this event actually fires (“Make the Event Fire” on page 131).

Make the Event Fire

As the widget author, you are responsible for ensuring that the event fires. How you do this is ultimately up to you. A typical method would be to hook into standard browser DOM-level events. To do this, you can chain events together using the connect function within the init function. init: function() {

this.inherited(arguments);

132 CREATING CUSTOM WIDGETS

this.connect(this.domNode, "onclick", this, "onWMclick") },

In this example, when an onclick event occurs in an instance of the widget type we’re defining, the onWMclick event in the current object is called. Here’s an example of how this might look in a complete dojo.declare statement:dojo.declare("turbo.LinkLabel", turbo.Label, {

init: function() {this.inherited(arguments);this.connect(this.domNode, "onclick", this, "onWMclick")

}, onWMclick: function() { }});

In the example above, the this.inherited line calls the init function for the base widget, turbo.Label.

NOTE: The connect function is a wrapper for the dojo.connect function. It includes some automatic “disconnect” functionality when the widget is destroyed.

Widget Module File Location

Place your custom widget file in your home directory under WaveMaker\common\packages.

For example, if your home directory is myacct\Documents, then the custom widget directory would be:myacct\Documents\WaveMaker\common\packages

Adding Studio Support for the WidgetIn order to use your custom widget in the WaveMaker Studio, you need to add your module to the packages.js file (“Packages File Location” on page 133). The packages.js file defines the name, image and description for each widget, as it appears in the Palette. This file also determines which Palette heading the widget is listed under.

The widget entries are separated by commas, except for the last entry in the file, which is not comma terminated. The syntax for the widget entries is: [palette section, name, widgetClassName, moduleName, image, description]

where:palette section is the heading under which you want the widget to be grouped in the Palette.name is the name shown for the widget in WaveMaker Studio.

ADDING RUNTIME SUPPORT FOR THE WIDGET 133

widgetClassName is the widgetClassName that you defined in the dojo.declare statement in the widget module file.moduleName is the name of the .js widget module file. This name should be the same as the moduleName in the dojo.provide in your widget file. image is the image shown in the Palette for the widget.description is the description shown under the widget name in the Palette.

For example:// custom widgets["Custom", "WaveMaker Link", "wm.example.WMLink", "wm.packages.example.CustomWidgets", "images/turbo/label.png", "A link to dev.wavemaker.com"]

NOTE: Remember that you need a trailing comma unless your widget is the last one in the file and your widget must also be separated from the preceding entry with a comma.

Packages File Location

The packages.js file is located in your home directory under WaveMaker\common\packages.

For example, if your home directory is myacct\Documents, then the packages.js file would be:myacct\Documents\WaveMaker\common\packagespackages.js

Adding Runtime Support for the WidgetTo add runtime support for your custom widget, you need to add your module to the lib.js file (“lib.js File Location” on page 134). This will make the widgets in the module available to all projects run from the studio.

To add the module to the lib.js file, simply add the module name, in quotes. Place a comma at the end of your entry in the file, unless it is the last entry. Be certain to comma terminate the previous entry.

For example, you could add the following line to lib.js:// custom Widgets"wm.packages.example.CustomWidgets”

The module name must match the moduleName you specified in the packages.js file (“Adding Studio Support for the Widget” on page 132).

134 CREATING CUSTOM WIDGETS

lib.js File Location

The lib.js file is located in your home directory under WaveMaker\common\packages. For example, if your home directory is myacct\Documents, then the lib.js file would be:myacct\Documents\WaveMaker\common\packages\lib.js

Testing the WidgetReload WaveMaker Studio. Open a new or existing project. You should now see your custom widget in the Palette. If you receive any errors upon loading studio, check your syntax. The most common error of custom widgets is the failure to load the module. “Could not import module “wm.packages.example.CustomWidgets”

This can be the result of:The module file is not available in the defined locationThe module name and provide do not matchThe declare statement does not match the packages definition

Firebug can provide further information as to the cause of the failure (“Debugging with Firebug” on page 123). Firebug will also show you the contents of the JavaScript files. This is useful for tracking down problems caused by caching.

When you’re testing your widget, note that events do not fire in design mode. To test events, you need to actually run the application.

Dojo and WaveMakerThe WaveMaker widget architecture relies heavily on the Dojo toolkit, which is an Open Source DHTML toolkit written in JavaScript. Dojo is divided into three main parts:

Dojo Core: browser normalization, language enhancements, and so onDijit: Dojo widgetsDojoX: big collection of stuff, with varying levels of maintenance and support

While our widgets do rely on Dojo, our base widget (turbo.Widget) is not a Dijit. WaveMaker use a separate widget system. We do have a turbo.Dijit wrapper class that wraps Dijits for use in WaveMaker Studio.

For more information on the Dojo toolkit, refer to the Dojo web site:

http://dojotoolkit.org/