Your SlideShare is downloading. ×
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Enterprise Web Developer Using the ExtJS Widgets
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Enterprise Web Developer Using the ExtJS Widgets

3,933

Published on

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
3,933
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
185
Comments
0
Likes
0
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. Enterprise Web Developer Using the ExtJS Widgets Version 4.0.746 Background Enterprise Web Developer (EWD) includes advanced functionality that allows you to make use of the powerful Javascript widget libraries from ExtJS (http://extjs.com). By incorporating these widgets into your applications, you'll be able to quickly and easily create Rich Internet Applications. Unlike users of these widget libraries who are forced to hand-craft the required code, you'll be able to let EWD do all the hard work. With EWD you'll be creating in minutes what others will take days or weeks to accomplish. Your web applications will never look the same again! This document is a reference guide to using EWD's ExtJS custom tags. Pre-requisites This guide assumes that you installed EWD (build 746 or later) and have read the eXtc Web Developer Overview, the Installation Guide, Tutorial and Ajax documents. You should also have the main EWD API Guide at hand. You'll also need to install the ExtJS Javascript library files (version 2.2 or later). Full instructions are available at their web site: • ExtJS: http://extjs.com Please note the licensing requirements for ExtJS. It is your responsibility to comply with these. Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 1
  • 2. EWD's ExtJS Custom Tags EWD provides a set of custom tags that represent the various ExtJS widgets. The ExtJS custom tags have a prefix of ext: For example: <ext:grid> <ext:tree> EWD's compiler will convert these into the corresponding Javascript and HTML tags that you would otherwise have to write by hand. This approach provides you with a much simpler and intuitive way of using ExtJS widgets, some of which can be very complex and require a lot of advanced Javascript programming. EWD also automatically handles all the many additional complexities that can occur when using ExtJS widgets within an Ajax application, where whole sections of markup containing one set of widgets are replaced with new markup containing new sets of widgets. With EWD you can focus on what you're wanting to do with the ExtJS widgets, not how they actually work. The current version of EWD does not implement the full set of ExtJS widgets, but the main desktop, windowing and layout widgets are available. More widgets will be added in future builds. ExtJS widgets are highly configurable via what are known as config options. EWD allows you to apply these config options by mapping them to correspondingly named attributes within each ExtJS custom tag. Usually EWD will automatically apply a set of sensible defaults for config options that you don't specify. Values for all config options can be either string literal values or session variables, for example: <ext:gridColumn header="#col1Title" width="120" sortable="true" /> The header value will be determined by a session variable named colTitle, denoted by the # character, whilst the width and sortable values use fixed literal values. This document will not list the various config options for each ExtJS custom tag. If you wish to find out the config options that are available for each custom tag, then you should refer to the ExtJS API documentation at http://extjs.com/deploy/dev/docs/ for the ExtJS class created by the EWD custom tag (see Appendix I for mappings). EWD Configuration When you install the ExtJS libraries, you'll usually do so by creating a sub-directory under your web server's root path into which all the ExtJS resurce files are copied, eg: C:Program FilesApache GroupApache2htdocsext-2.2 or /var/www/html/ext-2.2 Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 2
  • 3. If so, the various ExtJS Javascript files will be referred to, within your web pages, via a relative URL based on the sub-directory name you chose, eg: /ext-2.2 EWD provides a simple shortcut for loading the ExtJS Javascript files into your applications' pages. After the initial <ewd:config> tag at the top of your EWD pages, simply add: <ext:config path=”/ext2.2” /> Substitute the path as appropriate to your ExtJS installation. If you are developing an EWD Ajax application, you'll need this ExtJS configuration tag in only your container page(s). It should not appear in your EWD page fragments. Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 3
  • 4. How EWD's ExtJS tags map to ExtJS Javascript EWD's ExtJS custom tags allow you to express ExtJS widgets in terms of nested XML tags. However, EWD's compiler has to convert the custom tags into the appropriate ExtJS Javascript code. In the main, this is performed as follows: • Most of the main ExtJS classes have a corresponding EWD Custom Tag, eg: • <ext:Panel> corresponds with Ext.Panel • <ext:ComboBox> corresponds with Ext.form.ComboBox • Most ExtJS custom tags can be nested inside other ExtJS custom tags (where it makes sense to do so). • All the documented config options for an ExtJS class are available as attributes in the corresponding EWD Custom tag • Each EWD ExtJS custom tag is compiled into a line of Javascript that instantiates an instance of the corresponding ExtJS class, eg: • <ext:panel id="specimenListPanel" border="false" /> compiles to: • var extObjindex463=new Ext.Panel({border:false,id:"specimenListPanel"}); • Unless specifically over-ridden, each child ExtJS tag is added to the items array of the corresponding parent ExtJS class. eg: <ext:panel region="center" id="centerPanel" border="false" > <ext:panel id="trialGridPanel" src="trialSelection.ewd" border="false"/> <ext:panel id="trialSummaryPanel" border="false" /> <ext:panel id="visitGridPanel" border="false" /> <ext:panel id="selectedVisitGridPanel" border="false" /> <ext:panel id="demographicsFormPanel" border="false" /> <ext:panel id="specimenListPanel" border="false" /> </ext:panel> compiles to: var extObjindex436=new Ext.Panel({border:false,contentEl:"trialGridPanelDiv",id:"trialGridPanel"}); var extObjindex443=new Ext.Panel({border:false,id:"trialSummaryPanel"}); var extObjindex448=new Ext.Panel({border:false,id:"visitGridPanel"}); var extObjindex453=new Ext.Panel({border:false,id:"selectedVisitGridPanel"}); var extObjindex458=new Ext.Panel({border:false,id:"demographicsFormPanel"}); var extObjindex463=new Ext.Panel({border:false,id:"specimenListPanel"}); var extObjindex429=new Ext.Panel({border:false,id:"centerPanel",items: [extObjindex436,extObjindex443,extObjindex448,extObjindex453,extObjindex458,extObjindex463], region:"center"}); If applicable, you can override the use of the items array and use any other relevant config option that takes a collection of object references by using the parentAttribute attribute, eg: <ext:listeners parentAttribute=”listeners” > This tells EWD's compiler to add the reference to the ExtJS Listeners object to the listeners config option in the parent tag instead of its items config option. Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 4
  • 5. This allows you to very simply and easily nest ExtJS widgets (provided it makes sense to do so). It also gives you complete control over the widgets and their inter- relationships. • Some EWD custom tags such as <ext:ewdForm> automatically modify many of its child EWD ExtJS custom tags, to provide a convenient way of simplifying the typical use of ExtJS tags. The principle has been to create a mapping that allows commonly used behaviour to be packaged up into a small set of interoperating EWD custom tags with a minimum of attributes, whilst allowing the power-user to use any or all of the config options from within the convenience of EWD's tags. Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 5
  • 6. ExtJS Layout Widgets: ViewPort One of the standard layout features provided by ExtJS is the Viewport. This allows the browser page to be divided into 5 areas, known as north, south, east, west and center. The panels can be initially set to be collapsed and/or with moveable/draggable borders. The Viewport is a good way of making very efficient use of the space within the browser page. The ViewPort creates the outer container within the browser, and Panels are then used to define the working areas within it. In complex applications, the primary viewport panels can, themselves, include one or more sub-panels. Let's create a simple example. First, create a new EWD application sub-directory named extjsDemo. Eg if your EWD Application Root Path is c:ewdApps, create: c:ewdAppsextjsDemo Copy the page definition below and save it in a file named viewportDemo1.ewd in the extjsDemo application directory. Note: EWD does not currently allow tags to be split across more than one line. The example boxes in this document will show some lines wrapped across 2 or more lines. Make sure you reduce these to a single line per tag in your EWD source files. You should then have a file: c:ewdAppsextjsDemoviewportDemo1.ewd <ewd:config isFirstPage="true" /> <ext:config path="/ext-2.2" /> <html> <head> <title>EWD/Ext-JS Viewport & Layout Demo</title> </head> <body> <ext:viewport layout="border"> <ext:panel region="north" el="myNorthRegion" autoHeight="true" border="false" margins="0 0 1 0" /> <ext:panel region="west" title="West Region" collapsed="true" collapsible="true" split="true" width="500" minWidth="200" /> <ext:panel region="east" title="East Region" collapsed="true" collapsible="true" split="true" width="450" minWidth="250" /> <ext:panel region="center" title="Center Region" /> <ext:panel region="south" title="South Region" collapsed="true" collapsible="true" split="true" height="250" minHeight="100" /> </ext:viewport> <div id="myNorthRegion" style="text-align:center">This is the North Panel</div> </body> </html> Compile this page to the technology of your choice, eg: d compileAll^%zewdAPI(“extjsDemo”,,”php”) Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 6
  • 7. The first time you compile this page you should compile the complete application to ensure that EWD generates all the additional supporting pages. Thereafter you can just recompile the page on its own using: d compilePage^%zewdAPI(“extjsDemo”,”viewportDemo1”,,”php”) If you've installed and configured everything properly, when you run this page in a browser, you should see something like the following: If you click on the arrowed tabs on the west, east and south panels, they should each slide into view. You can then drag their borders around or collapse them again by clicking the arrowed tabs again. Note the way the North panel contents has been defined in a separate <div> tag, and is referenced using the el attribute. In fact, contentEl is the recommended attribute to use, but this will produce a white panel whereas el produces the blue one. Try it and see! Currently, of course, there's nothing in any of the other panels, so let's rectify that! Let's create a simple page fragment that we'll use as content for each of the panels. Copy and paste the following fragment definition into a file and save it in the extjsDemo directory as panelContent1.ewd. Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 7
  • 8. <ewd:config isFirstPage="false" pageType="ajax" /> <span style="background-color:#ffffff;"> Hello world! </span> Now add a src attribute referring to this fragment to the east, west, south and center panels: <ewd:config isFirstPage="true" /> <ext:config path="/ext-2.2" /> <html> <head> <title>EWD/Ext-JS Viewport & Layout Demo</title> </head> <body> <ext:viewport layout="border"> <ext:panel region="north" el="myNorthRegion" autoHeight="true" border="false" margins="0 0 1 0" /> <ext:panel region="west" src="panelContent1.ewd" title="West Region" collapsed="true" collapsible="true" split="true" width="500" minWidth="200" /> <ext:panel region="east" src="panelContent1.ewd" title="East Region" collapsed="true" collapsible="true" split="true" width="450" minWidth="250" /> <ext:panel region="center" src="panelContent1.ewd" title="Center Region" /> <ext:panel region="south" src="panelContent1.ewd" title="South Region" collapsed="true" collapsible="true" split="true" height="250" minHeight="100" /> </ext:viewport> <div id="myNorthRegion" style="text-align:center">This is the North Panel</div> </body> </html> Recompile the entire application: d compileAll^%zewdAPI(“extjsDemo”,,”php”) and reload viewportDemo1 in your browser. Each of the panels should now contain the text Hello world! You're now ready to extend this into a fully-fledged Ajax application. First, simply copy the panelContent1.ewd file to create separately named fragments, eg: • panelContentEast.ewd • panelContentWest.ewd • panelContentCenter.ewd • panelContentSouth.ewd Next add a unique id attribute to the <span> tag in each of these fragments, eg in panelContentEast.ewd: Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 8
  • 9. <ewd:config isFirstPage="false" pageType="ajax" /> <span id="myEastPanel" style="background-color:#ffffff;"> Initial text in the East Panel </span> Finally change the references in the src attributes to the respective fragments, eg: <ext:viewport layout="border"> <ext:panel region="north" el="myNorthRegion" autoHeight="true" border="false" margins="0 0 1 0" /> <ext:panel region="west" src="panelContentWest.ewd" title="West Region" collapsed="true" collapsible="true" split="true" width="500" minWidth="200" /> <ext:panel region="east" src="panelContentEast.ewd" title="East Region" collapsed="true" collapsible="true" split="true" width="450" minWidth="250" /> <ext:panel region="center" src="panelContentCenter.ewd" title="Center Region" /> <ext:panel region="south" src="panelContentSouth.ewd" title="South Region" collapsed="true" collapsible="true" split="true" height="250" minHeight="100" /> </ext:viewport> Recompile the extjsDemo application and refresh your browser. You should see the different content in each of the panels. The cool thing is that you've now also loaded a unique target id into the top of each of the panels, so you can now start delivering new fragments into each specific panel in response to user-generated events. Because this is actually just one physical browser page, an event in one panel can cause a fragment to be targetted into the same or any other panel. Let's try this out. Your main container page (viewportDemo1.ewd) should now be looking like this: <ewd:config isFirstPage="true" /> <ext:config path="/ext-2.2" /> <html> <head> <title>EWD/Ext-JS Viewport & Layout Demo</title> </head> <body> <ext:viewport layout="border"> <ext:panel region="north" el="myNorthRegion" autoHeight="true" border="false" margins="0 0 1 0" /> <ext:panel region="west" src="panelContentWest.ewd" title="West Region" collapsed="true" collapsible="true" split="true" width="500" minWidth="200" /> <ext:panel region="east" src="panelContentEast.ewd" title="East Region" collapsed="true" collapsible="true" split="true" width="450" minWidth="250" /> <ext:panel region="center" src="panelContentCenter.ewd" title="Center Region" /> <ext:panel region="south" src="panelContentSouth.ewd" title="South Region" collapsed="true" collapsible="true" split="true" height="250" minHeight="100" /> </ext:viewport> <div id="myNorthRegion" style="text-align:center">This is the North Panel</div> </body> </html> Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 9
  • 10. and your fragment named panelContentEast.ewd should currently contain: <ewd:config isFirstPage="false" pageType="ajax" /> <span id="myEastPanel" style="background-color:#ffffff;"> Initial text in the East Panel </span> Note the target id this will introduce into the container page: myEastPanel Now change your fragment named panelContentCenter.ewd to contain: <ewd:config isFirstPage="false" pageType="ajax" /> <script language="javascript"> function changeLeftPanel() { ewd.ajaxRequest("panelContentEast2","myEastPanel") ; } </script> <span id="myCenterPanel" style="background-color:#ffffff;"> <input type="button" value="Click me!" onclick="changeLeftPanel()" /> </span> Let's examine what this fragment will do: when the button in this fragment is clicked, it will trigger the javascript function changeLeftPanel(), causing a fragment named panelContentEast2.ewd to be fetched and targetted in the id that was originally sent into the East panel by the fragment panelContentEast.ewd. So let's now finally create the fragment panelContentEast2.ewd: <ewd:config isFirstPage="false" pageType="ajax" /> <span> Look! The content in the East Panel has been changed! </span> Recompile the extjsDemo application and refresh the browser. If you slide the East panel open, you should see the following: Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 10
  • 11. Now click the button in the Center panel. The content in the East panel should change: Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 11
  • 12. Your ExtJS Viewport is now ready to provide a framework for a complete Ajax application! Extending the Viewport: Tabs ExtJS allows you to add tabbed panels to your Viewport. Let's add some to the center panel. First, edit the main viewportDemo1.ewd page, and change the center panel tag from: <ext:panel region="center" src="panelContentCenter.ewd" title="Center Region" /> to: <ext:tabPanel region="center" > <ext:Panel title="Panel 1" closable="false" src="panelContentCenter.ewd" active="true" /> <ext:Panel title="Panel 2" closable="false" fragmentOnSelect="panelContentCenter2.ewd" /> </ext:tabPanel> What's going to happen is that the second tab won't load its content fragment until the tab is clicked. We'll need to create that fragment, as a file named panelContentCenter2.ewd: <ewd:config isFirstPage="false" pageType="ajax" /> <span id=”myTab2”> This is the second tabbed panel in the center region! </span> Once again, we'll seed a targetId (in this case myTab2) into the second tab pane, so we can use this for targetting later fragments into the panel. Try recompiling the extjsDemo application and refresh the browser again. This time you should see the following: Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 12
  • 13. The panel for Tab 1 is displayed (using the content from fragment panelContentCenter.ewd) because its active attribute was set to true: <ext:tab title="Panel 1" closable="false" src="panelContentCenter.ewd" active="true" /> Click the tab named Panel 2 and you should see the second tab appear with its contents fetched from the fragment panelContentCenter2.ewd. You can now add as many tabs as you like to any of the panels in the viewport. Extending the Viewport: Accordion Panes Another great feature you can add to your viewport is accordion panes. These allow lots of information to be stacked up into a pile of panels, with only one visible at any one time. You can slide each panel into view simply by clicking its title bar or button. EWD makes it easy to add accordion panes. Let's add some to the West panel. First, edit the main viewportDemo1.ewd page, and change the west panel tag from: <ext:panel region="west" src="panelContent1.ewd" title="West Region" collapsed="true" collapsible="true" split="true" width="500" minWidth="200" /> Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 13
  • 14. to: <ext:accordionPanel region="west" title="West Region" collapsed="true" collapsible="true" split="true" width="500" minWidth="200"> <ext:Panel id="pane1" border="false" title="Accordion Panel 1" src="accordionContent1.ewd" /> <ext:Panel id="pane2" border="false" title="Accordion Panel 2" src="accordionContent2.ewd" /> </ext:accordionPanel> Now we'll create the two content fragments: accordionContent1.ewd: <ewd:config isFirstPage="false" pageType="ajax" /> <span id="myAccordionPane1"> This is the first accordion panel </span> accordionContent2.ewd: <ewd:config isFirstPage="false" pageType="ajax" /> <span id="myAccordionPane2"> This is the second accordion panel </span> Try recompiling the extjsDemo application and refresh the browser again. If you slide open the West panel, you should see the following: Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 14
  • 15. Click on the button at the right-hand side of the Accordion Panel 2 title banner and it will slide open, replacing the first one. Because we added unique ids to each of the content fragments, we can now target these accordion panels with Ajax page fragments! Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 15
  • 16. ExtJS Layout Widgets: Toolbar & Menus Another set of layout widgets provided by ExtJS allows you to add a toolbar to the top of your page (or panel), to which you can add buttons and drop-down menus. Once again, EWD makes it very quick and easy to use these widgets. First, create a new EWD page named toolbarDemo.ewd in your extjsDemo directory, containing the following: <ewd:config isFirstPage="true"> <ext:config path="/ext-2.2" debug="true"/> <html> <head> <title>Toolbar Demo</title> </head> <body> <ext:toolbar id="myToolbar" autorender="true" /> <div id="myContent">This is a demo of the ExtJS Toolbar and Menus</div> </body> </html> Compile using, eg: d compileAll^%zewdAPI(“extjsDemo”,,”php”) Load this page into a browser and you should see the text: This is a demo of the ExtJS Toolbar and Menus underneath a very thin blue line. This thin blue line is the taskbar which, because it doesn't yet contain anything, is barely visible (Note: the EWD-specific attribute autoRender=”true” tells EWD to add a <div> tag to the page that is used as the rendering point for the toolbar. If you next the <ext:toolbar> tag inside any type of Panel tag, it will automatically render itself into the Panel). We'll now add a menu button to this. Replace the line: <ext:toolbar id="myToolbar" autorender="true" /> Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 16
  • 17. with: <ext:toolbar id="myToolbar" autorender="true"> <ext:toolBarButton text="Example Menu" /> </ext:toolbar> Recompile toolbarDemo.ewd using, eg: d compilePage^%zewdAPI(“extjsDemo”,”toolbarDemo”,,”php”) and refresh your browser. You should now see the toolbar properly, complete with the menu option. When you roll your mouse over the menu option, it will appear as a button: Clicking the menu option won't have any effect right now. Now let's add a couple of menu options to it. <ext:toolbar id="myToolbar" autorender="true"> <ext:toolBarButton text="Example Menu"> <ext:menu> <ext:menuItem text="First Option" /> <ext:menuItem text="Second Option" /> </ext:menu> </ext:toolBarButton> </ext:toolbar> Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 17
  • 18. Recompile the page and refresh your browser. Now when you click the menu button, a drop-down panel with the two menu options will appear. Now let's add an event handler to the options so that we can trigger events when they are clicked: <ext:toolbar id="myToolbar" autorender="true"> <ext:toolBarButton text="Example Menu"> <ext:menu> <ext:menuItem id="opt1" text="First Option" onselect="Ext.Msg.alert('Menu Action','You selected: ' + item.id + ': ' + item.text);" /> <ext:menuItem id="opt2" text="Second Option" onselect="Ext.Msg.alert('Menu Action','You selected: ' + item.id + ': ' + item.text);" /> </ext:menu> </ext:toolBarButton> </ext:toolbar> Notice that the object item is available to your event handler and its two properties id and text return the values of the corresponding attributes for the menu item that was clicked by the user. In this simple example we're just generating an alert, displaying which menu option was clicked. Notice that in this example we're making use of the ExtJS alert which allows you to specify a message heading and automatically greys the background. We could, of course, used a standard Javascript alert(). Recompile the page and refresh the browser. Now you should get an alert when you click a menu option. Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 18
  • 19. It's now a simple step to use this menu to drive some Ajax behaviour. For example, we could add a Javascript functionto the EWD page: <script language="javascript"> function mySelectHandler(item) { if (item.id == "opt1") { ewd.ajaxRequest("toolbarContent1","myContent") ; } if (item.text == "Second Option") { ewd.ajaxRequest("toolbarContent2","myContent") ; } } </script> Next, change the event handlers in the <ext:menuItem> tags: <ext:toolbar id="myToolbar" autorender="true"> <ext:toolBarButton text="Example Menu"> <ext:menu> <ext:menuItem id="opt1" text="First Option" onselect="mySelectHandler(item) " /> <ext:menuItem id="opt2" text="Second Option" onselect="mySelectHandler(item) " /> </ext:menu> </ext:toolBarButton> </ext:toolbar> Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 19
  • 20. And now create the two fragments: toolbarContent1.ewd: <ewd:config isFirstPage="false" pageType="ajax" /> <span> Here is the first option content! </span> toolbarContent2.ewd: <ewd:config isFirstPage="false" pageType="ajax" /> <span> Here is the second option content! </span> Recompile the extjsDemo application and refresh the browser. Now when you click a menu option, the content below the toolbar is replaced with that of the corresponding fragment. Of course we could have targetted any id within the browser page. Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 20
  • 21. Multi-level Menus EWD makes it easy to have multi-level drop-down menus of any depth you like. Simply use nested <ext:menuOption> tags, using the nesting to reflect the menu hierarchy you require, eg: <ext:toolbar id="myToolbar" autorender="true"> <ext:toolBarButton text="Example Menu"> <ext:menu> <ext:menuItem id="opt1" text="First Option" onselect="mySelectHandler(item)" /> <ext:menuItem id="opt2" text="Second Option" onselect="mySelectHandler(item)" /> <ext:menuItem id="opt3" text="Third Option" onselect="mySelectHandler(item)"> <ext:menu> <ext:menuItem id="opt3a" text="Option 3a" onselect="mySelectHandler(item)" /> <ext:menuItem id="opt3b" text="Option 3b" onselect="mySelectHandler(item)"> <ext:menu> <ext:menuItem id="opt3b1" text="Option 3b-1" onselect="mySelectHandler(item)" /> <ext:menuItem id="opt3b2" text="Option 3b-2" onselect="mySelectHandler(item)" /> </ext:menu> </ext:menuItem> <ext:menuItem id="opt3c" text="Option 3c" onselect="mySelectHandler(item)" /> <ext:menuItem id="opt3d" text="Option 3d" onselect="mySelectHandler(item)"> <ext:menu> <ext:menuItem id="opt3d1" text="Option 3d-1" onselect="mySelectHandler(item)" /> <ext:menuItem id="opt3d2" text="Option 3d-2" onselect="mySelectHandler(item)" /> <ext:menuItem id="opt3d3" text="Option 3d-3" onselect="mySelectHandler(item)" /> </ext:menu> </ext:menuItem> </ext:menu> </ext:menuItem> <ext:menuItem id="opt4" text="Fourth Option" onselect="mySelectHandler(item)" /> </ext:menu> </ext:toolBarButton> </ext:toolbar> This will generate the following menu in the browser: Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 21
  • 22. Checkbox Menu Options ExtJS also allows you to have menu options that you can check, firing an event when you do so. Once again, EWD makes this easy to use. Use the <ext:checkItem> tag instead and use a different event handler: onCheck. The onCheck handler works identically to the onSelect handler, but the item object includes a checked property to allow your method to perform the correct actions depending on whether the checkbox was checked or unchecked by the user. For example: <ext:checkItem id="opt3d4" text="I like EWD" oncheck="alert('Checked the menu item: ' + item.text + '; checked=' + item.checked);" /> Menu Separators and Heading Titles You can very easily add separator bars to split up logical groups of menu options by simply using the <ext:menuSeparator /> tag, eg: <ext:toolbar id="myToolbar" autorender="true"> <ext:toolBarButton text="Example Menu"> <ext:menu> <ext:menuItem id="opt1" text="First Option" onselect="mySelectHandler(item)" /> <ext:menuSeparator /> <ext:menuItem id="opt2" text="Second Option" onselect="mySelectHandler(item)" /> <ext:menuItem id="opt3" text="Third Option" onselect="mySelectHandler(item)"> <ext:menu> <ext:menuItem id="opt3a" text="Option 3a" onselect="mySelectHandler(item)" /> <ext:menuItem id="opt3b" text="Option 3b" onselect="mySelectHandler(item)"> <ext:menu> <ext:menuItem id="opt3b1" text="Option 3b-1" onselect="mySelectHandler(item)" /> <ext:menuItem id="opt3b2" text="Option 3b-2" onselect="mySelectHandler(item)" /> </ext:menu> </ext:menuItem> <ext:menuItem id="opt3c" text="Option 3c" onselect="mySelectHandler(item)" /> <ext:menuItem id="opt3d" text="Option 3d" onselect="mySelectHandler(item)"> <ext:menu> <ext:menuItem id="opt3d1" text="Option 3d-1" onselect="mySelectHandler(item)" /> <ext:menuItem id="opt3d2" text="Option 3d-2" onselect="mySelectHandler(item)" /> <ext:checkItem id="opt3d3" text="Option 3d-3" oncheck="alert(1)" onselect="mySelectHandler(item)" /> <ext:checkItem id="opt3d4" text="I like EWD" oncheck="alert('Checked the menu item: ' + item.text + '; checked=' + item.checked);" /> </ext:menu> </ext:menuItem> </ext:menu> </ext:menuItem> <ext:menuSeparator /> <ext:menuItem id="opt4" text="Fourth Option" onselect="mySelectHandler(item)" /> </ext:menu> </ext:toolBarButton> </ext:toolbar> Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 22
  • 23. Alternatively (or additionally) you can use the <ext:menuTextItem> tag to create a text heading that acts as a title and separator between blocks of menu options, eg: <ext:toolbar id="myToolbar" autorender="true"> <ext:toolBarButton text="Example Menu"> <ext:menu> <ext:menuItem id="opt1" text="First Option" onselect="mySelectHandler(item)" /> <ext:menuTextItem text="Normal Options" /> <ext:menuSeparator /> <ext:menuItem id="opt2" text="Second Option" onselect="mySelectHandler(item)" /> <ext:menuItem id="opt3" text="Third Option" onselect="mySelectHandler(item)"> <ext:menu> <ext:menuItem id="opt3a" text="Option 3a" onselect="mySelectHandler(item)" /> <ext:menuItem id="opt3b" text="Option 3b" onselect="mySelectHandler(item)"> <ext:menu> <ext:menuItem id="opt3b1" text="Option 3b-1" onselect="mySelectHandler(item)" /> <ext:menuItem id="opt3b2" text="Option 3b-2" onselect="mySelectHandler(item)" /> </ext:menu> </ext:menuItem> <ext:menuItem id="opt3c" text="Option 3c" onselect="mySelectHandler(item)" /> <ext:menuItem id="opt3d" text="Option 3d" onselect="mySelectHandler(item)"> <ext:menu> <ext:menuItem id="opt3d1" text="Option 3d-1" onselect="mySelectHandler(item)" /> <ext:menuItem id="opt3d2" text="Option 3d-2" onselect="mySelectHandler(item)" /> <ext:checkItem id="opt3d3" text="Option 3d-3" oncheck="alert(1)" onselect="mySelectHandler(item)" /> <ext:checkItem id="opt3d4" text="I like EWD" oncheck="alert('Checked the menu item: ' + item.text + '; checked=' + item.checked);" /> </ext:menu> </ext:menuItem> </ext:menu> </ext:menuItem> <ext:menuTextItem text="Special Options" /> <ext:menuItem id="opt4" text="Fourth Option" onselect="mySelectHandler(item)" /> </ext:menu> </ext:toolBarButton> </ext:toolbar> Simple Toolbar Buttons A toolbar button doesn't have to have a menu attached to it: it can be a simple button with an associated event hander. For example: <ext:toolBarButton text="Hide Help" id="hideHelpBtn" pressed="true" onclick="hideHelp(item)"> By using the pressed attribute, you can make the button stand out as a properly rendered button on the toolbar without you having to hover over it. Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 23
  • 24. Make sure your event handler passes the variable item, as shown above. This provides a pointer to the button object. So, for example, you could immediately hide the button and show another instead using: function hideHelp(item) { item.hide() ; Ext.getCmp('showHelpBtn').show(); } Note the use of Ext.getCmp() which is how you get a pointer to another ExtJS component via its id. Of course your event handler could also be used to trigger the fetch of another EWD fragment into a targetId, eg. function getHelp(item) { item.hide() ; Ext.getCmp('HelpPanel').show(); ewd.ajaxRequest(“helpDetails”,”helpDiv”) ; } Other Toolbar widgets ExtJS provides a number of other Toolbar widgets that are mapped to equivalent EWD custom tags. These include: • <ext:toolbarFill /> This pushes all subsequent toolbar widgets to the right. It has no attributes. • <ext:toolbarSpacer /> This adds some space between adjacent toolbar widgets. It has no attributes • <ext:toolbarSeparator /> This adds a vertical bar as a separator between adjacent widgets. It has no attributes • <ext:toolbarTextItem text=”Some text” /> This adds a piece of text into the toolbar. Panels, Toolbars and StatusBars By using the nestable behaviour of the EWD ExtJS tags, you can put toolbars and status bars inside Panel widgets, and panels inside other panels. For example: Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 24
  • 25. <ext:Panel id="mainPanel" title="Main container Panel" layout="absolute" border="true" frame="false" width="1000" height="600" autoRender="true"> <ext:Panel id="subPanel" title="Panel with Toolbar and Status bar" border="true" x="100" y="100" frame="false" width="500" contentEl="panelContents"> <ext:toolbar id="theToolbar"> <ext:toolBarButton text="Add Site" pressed=”true” onclick="addSite()"/> <ext:toolBarFill /> <ext:toolBarButton text="Test" onclick="testit()"/> </ext:toolbar> <ext:statusBar id="myStatusBar" defaultText="Current Status OK"> <ext:toolBarButton text="Click Me" onclick="goToMatching(item)"/> <ext:toolBarSeparator /> <ext:toolBarTextItem text="status"/> </ext:statusBar> </ext:Panel> <ext:statusBar id="outerStatusBar" defaultText="This is the outer panel" /> </ext:Panel> <div id="panelContents"> <br /> <p>This is a test panel</p> <p>with its own toolbar and statusbar</p> <br /> </div> This should render as shown below: Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 25
  • 26. In this example, the outer container panel is rendered using autoRender=”true”, so EWD automatically adds a <div> tag to the page/fragment that will be used as its rendering anchor point. The inner panel will render itself automatically inside the container panel. By specifying the outer panel as layout=”absolute”, the inner one can be positioned inside it using the x and y attributes. By nesting the toolbar and statusbar inside the inner panel, it is rendered with the toolbar and statusbar. But notice the outer panel also has its own status bar: it's all controlled by the level of nesting of the tags. The contents for the inner panel are obtained, in this example, from a <div> tag that we've specified and hard-coded. The contentEl attribute is used to pull this content into the panel. Finally, notice how the statusBar widget can make use of and or all of the various toolBar widgets, and notice the use of the pressed=”true” attribute in the first toolbar button which makes it visually appear as a button without the need to float your mouse over it. Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 26
  • 27. Grids One of the greatest and most powerful features in ExtJS is its grid widget. Grids can be either read-only or editable, or a mixture of the two (ie with some columns being editable and some being display-only). EWD makes it very quick and simple to use ExtJS grid widgets. We'll start with a simple display-only grid. Like many ExtJS widget, the data in a grid is held in a datastore. This is a JSON-based data structure which is delivered to the browser from the back-end system. EWD looks after all the JSON-specific aspects of the datastore creation and transmission, leaving you just the simple task of specifying the array of data that will populate the datastore and hence the grid. First, let's create a simple page that will display a grid. Copy the contents below into a file named gridDemo.ewd. <ewd:config isFirstPage="true"> <ext:config path="/ext-2.2" /> <html> <head> <title>Ext JS Grid Example</title> </head> <body> <span> <ext:grid datastore="myData" stripeRows="true" autoRender=”true” title="Example Ext/EWD Grid" width="400" frame="true" autoHeight=”true”> <ext:gridColumn header="Company" width="60" sortable="true" tooltip="The company in question"/> <ext:gridColumn header="Price" type="float" width="30" sortable="true" /> <ext:gridColumn header="Change" type="float" width="30" sortable="true" /> </ext:grid> </span> </body> </html> You define an ExtJS grid using two custom tags: <ext:grid> This defines the grid container, its dimensions and styling <ext:gridColumn> This defines each column in the grid, and characteristics such as its heading, data type and whether or not it can be sorted by clicking the column heading Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 27
  • 28. If you compile and run the gridDemo.ewd page, you'll find that you get an Invalid Request error. This is because we haven't created the datastore named myData that is referred to in the <ext:grid> tag. Datastores are the responsibility of the programmer to create, and this is done in the prePageScript. Add a pre-page script to the <ewd:config> tag: <ewd:config isFirstPage="true" prePageScript="##class(ewd.test).getDemoGridData"> In the example above, we're going to call a Caché class method named getDemoGridData in a class named ewd.test. You can change this to use a class of your own choice. Here's the source code for the class method: ClassMethod getDemoGridData(sessid As %String) As %String { s data(1,1)="Apple" s data(1,2)=29.89 s data(1,3)="0.24" s data(1,4)="true" s data(2,1)="Ext" s data(2,2)=83.81 s data(2,3)="0.28" s data(2,4)="true" s data(3,1)="Google" s data(3,2)=71.72 s data(3,3)="0.02" s data(3,4)="false" s data(4,1)="Microsoft" s data(4,2)=52.55 s data(4,3)="0.01" s data(4,4)="true" d createGridDatastore^%zewdExtJS(.data,"myData",”r”,sessid) QUIT "" } In this example we're simply hard-coding values, but in real-world examples the values would be fetched from your database. However, the pattern will be the same: • create a 2-dimensional local array: array(rowNo, colNo) = value • pass this array into the createGridDatastore function that EWD provides for you. Note the parameter “r”. This specifies that the EWD Session array named myData is allowed to be read via JSON by the browser. This parameter can be left blank, as “r” is the default. Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 28
  • 29. The programmer's task is therefore straightforward and intuitive. He/she needs to know nothing about how the ExtJS grid datastore is structured in JSON terms, nor how it is conveyed to the browser. Equally, the page designer's task is straightforward and intuitive. Specify the grid and its column structure, and specify the name of the datastore that will populate it. If you save and compile the class method above (adjusting the reference to it in the prePageScript attribute appropriately), then recompile the gridDemo.ewd page, when you reload the browser you should now see the following: Note the way you can click on the column headings, and how you can drag the columns around, and also turn columns on and off. Note that we only opted to display 3 of the columns that were available in the datastore. Look at the class method listing above and notice that the fourth column of data consists of just the values true and false, so a good way to represent this data would be with a checkbox. This is quite easy but first you will need to load a special Javascript file that you'll find in the EWD download zip file: ExtExtensions.js. Place a copy of this file in an appropriate path on your web server – in this example we'll assume that it is in the root path. Now add the following tag to the <head> section of your page: <script src="/ExtExtensions.js" type="text/javascript"></script> Now add the extra column definition: <ext:gridColumn header="In Stock" renderAs="checkbox" width="30" /> So, simply by specifying the column using renderAs=”checkbox”, EWD will compile in the necessary ExtJS Javascript to use a checkbox for this column, You can try modifying some of the grid column attributes, add further columns, etc. For details of the available config option attributes, go to the ExtJS API guide at http://extjs.com/deploy/dev/docs/ and reference: <ext:grid> Ext/grid/GridPanel <ext:gridColumn> Ext/grid/ColumnModel Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 29
  • 30. Editable Grids EWD and ExtJS also allow you to make a grid editable, so you can use it as a simple spreadsheet-like interface for editing data in your database. To create an editable grid, use the <ext:editorGridPanel> tag instead of the <ext:grid> tag. You can make any or all of the columns editable by adding the attribute editAs to the <ext:gridColumn> tags. The value of the editAs attribute specifies the datatype and hence the mechanism and/or widgets that ExtJS will bring into play to allow you to edit the data field. Supported values in EWD are: • text simple text field allowing any alphanumeric character • number text field allowing only numeric values • checkbox on/off checkbox for boolean values • select drop-down list of possible valid options for the value • date pop-up calendar widget allows simple date entry • textarea automatically expanding textarea box for multi-line text For example, the following demonstrates how to specify all these types: <ext:gridColumn header="First Page" editAs="text" width="90" sortable="true" /> <ext:gridColumn header="Timeout (sec)" type="float" editAs="number" width="90" sortable="true" /> <ext:gridColumn header="Fast Symbol Table" editAs="checkbox" width="110" /> <ext:gridColumn header="Namespace" width="120" editAs="select" name="namespace" sortable="true"/> <ext:gridColumn header="Compiled Date" dateFormat="d M Y" editAs="date" width="120" /> <ext:gridColumn header="Notes" editAs="textarea" grow="true" growMax="160" width="120" / > See later for more details on how to handle each of these types. For now, let's modify our simple gridDemo.ewd page to make the Price column editable: • change the grid tag to an editorGridPanel tag • add the attribute clicksToEdit="1" to the editorGridPanel. By default you have to click on a field twice to edit it, but a single click tends to be more intuitive. • change the Price column definition to include editAs=”number” : Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 30
  • 31. <ext:editorgridpanel datastore="myData" clicksToEdit="1" stripeRows="true" title="Example Ext/EWD Grid" width="400" frame="true"> <ext:gridColumn header="Company" width="60" sortable="true" tooltip="The company in question"/> <ext:gridColumn header="Price" type="float" width="30" editAs="number" sortable="true" /> <ext:gridColumn header="Change" type="float" width="30" sortable="true" /> <ext:gridColumn header="In Stock" type="bool" renderAs="checkbox" width="30" /> </ext:editorgridpanel> When you recompile the page and refresh the browser, you should find that when you click on any Price cell, you can now edit the value. Note the way you can only enter numeric characters! Although you can now change the values, they're only being altered locally. We now need to get the new, edited value to the back-end and into the hands of the programmer who can validate and process the new, edited value if required. This is done by adding a validationScript attribute to the <ext:editorGridPanel> tag. <ext:editorgridpanel datastore="myData" clicksToEdit="1" stripeRows="true" title="Example Ext/EWD Grid" width="400" frame="true" validationScript=" class(ewd.test).setDemoGridData" > Note that you must not specify the method using ##class. Make sure you leave out the two # characters. You must also give the EWD Session datastore read/write permissions. You do this by changing the “r” parameter to “rw” in the createGridDatastore() method that you used in the prePageScript, ie. ClassMethod getDemoGridData(sessid As %String) As %String { s data(1,1)="Apple" s data(1,2)=29.89 s data(1,3)="0.24" s data(1,4)="true" s data(2,1)="Ext" s data(2,2)=83.81 s data(2,3)="0.28" s data(2,4)="true" s data(3,1)="Google" s data(3,2)=71.72 s data(3,3)="0.02" s data(3,4)="false" s data(4,1)="Microsoft" s data(4,2)=52.55 s data(4,3)="0.01" Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 31
  • 32. s data(4,4)="true" d createGridDatastore^%zewdExtJS(.data,"myData",”rw”,sessid) QUIT "" } Now, every time an editable grid cell value is changed and you move away from the grid cell, this method will fire, passing the row number, column number and new value to the programmer. Note that the row and column numbers will be the original values for the cell, so it doesn't matter if the user re-sorts the contents or drags the coumns around. So let's take a look at a simple example of what the programmer might do in the back- end validationScript method: ClassMethod setDemoGridData(sessid As %String) As %String { s row=$$getSessionValue^%zewdAPI("extGridRow",sessid) s column=$$getSessionValue^%zewdAPI("extGridColumn",sessid) s value=$$getSessionValue^%zewdAPI("extGridValue",sessid) i value>99 QUIT "Value is too big!" QUIT "" } When you change a value, EWD instantiates three session variables: extGridRow extGridColumn extGridValue The programmer should pick up these values in his/her script and perform any validation. In the example above we're simply ensuring that the value cannot be greater than 99. In the event of a validation error, the programmer simply QUITs, returning an error message string. EWD automatically uses this to bring up an ExtJS alert. If the value validates OK, the programmer can optionally save the new value. It is the programmer's responsibility to ensure that the row and column numbers provide him/her with sufficient information to save the new value back into the correct place in the database. The modified value does not need to be committed to the database immediately. The modified values reside in an EWD Session Array, in this case named myData. When editing is completed, the programmer can commit all the changed data at once. For example, to access the modified EWD Session values for the grid: Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 32
  • 33. d mergeArrayFromSession^%zewdAPI(.myData,"myData",sessid) The local array myData is exactly the same format as originally created in the getDemoGridData() prePageScript method, but now contains the validated edited values. Note that any new values that failed validation are not changed in the EWD Session array, eg: myData(1,1)="Apple" myData(1,2)=29.89 myData(1,3)="0.24" myData(1,4)="true" myData(2,1)="Ext" myData(2,2)=23 myData(2,3)="0.28" myData(2,4)="true" myData(3,1)="Google" myData(3,2)=44 myData(3,3)="0.02" myData(3,4)="false" myData(4,1)="Microsoft" myData(4,2)=76 myData(4,3)="0.01" myData(4,4)="true" You should now be able to modify your demonstration grid to allow any of the columns to be edited, eg: <ext:editorgridpanel datastore="myData" clicksToEdit="1" stripeRows="true" title="Example Ext/EWD Grid" width="400" frame="true" validationScript=" class(ewd.test).setDemoGridData" <ext:gridColumn header="Company" width="60" sortable="true" tooltip="The company in question" editAs=”text” /> <ext:gridColumn header="Price" type="float" width="30" editAs="number" sortable="true" /> <ext:gridColumn header="Change" type="float" width="30" sortable="true" editAs=”number” /> <ext:gridColumn header="In Stock" type="bool" width="30" editAs=”checkbox” /> </ext:editorgridpanel > Custom Error Processing In the previous example you saw how the user could be given an error Alert message simply by QUIT'ing with a non-null value in the validation script, eg: i value>99 QUIT "Value is too big!" Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 33
  • 34. Although this behaviour will be suitable for many situations, there will be occasions when you want to define the error notification behaviour yourself. This is quite easy. Simply make the first and last characters of the QUIT returnValue { and } respectively, and you can then put any Javascript you like inside these braces. EWD will automatically eval() your Javascript instead of bringing up an alert. For example: i value["x" do QUIT error . s error= "{Ext.Msg.alert('Error','bad value!') ;" . s error=error_"editEvent.record.set(editEvent.field,editEvent.originalValue) ;" . s error=error_"editEvent.cancel = true ;}" In fact this example uses the same code that executes behind the scenes if you use the default mechanism (QUIT with a simple non-null string), and you should note the commands that have been used to cancel the edit and return the original value back to the edited cell. Invoking an Event Handler that Fires when a Row is Selected Provided your grid does not contain any editable cells, you can add an event handler that will fire when you select a row from the grid. You can fire your own method and EWD passes it all the information you need to handle the data relevant to the row within Javascript or in the Caché back-end (via an Event Broker call). Simply add the attribute onRowSelect to the <ext:grid> tag. The attribute's value will be the name of your function, eg <ext:grid datastore="myData" stripeRows="true" title="Example Ext/EWD Grid" width="400" frame="true" onRowSelect="myFunc"> Your event handler function must have two input parameters: • currentRecord an Array containing the values for each column in the selected row • currentRow the row number of the back-end data store that you selected eg: <script language="javascript"> function myFunc(currentRecord,currentRow) { alert(currentRecord + ": " + currentRow) ; } </script> Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 34
  • 35. If you click the third row in our demo grid, currentRow would have a value of 3 and currentRecord would contain: currentRecord[0] = 2 currentRecord[1] = “Google” currentRecord[2] = 71.72 currentRecord[3] = 0.02 currentRecord[4] = false Your function can therefore access and use the values for the current row within Javascript. If you want to return more data from the Caché back-end from within your function, you can make an Event Broker call, eg: <script language="javascript"> function myFunc(currentRecord,currentRow) { ewd:##class(ewd.test).fetchGridRecord(currentRow) ; alert(myRecord) ; } </script> This method might look as follows: ClassMethod fetchGridRecord(currentRow As %Integer, sessid As %String) As %String { // access data related to the record identified by the currentRow number, eg // here is the data returned to Javascript as a hard-coded array QUIT "myRecord = ['This record',12,34,99,true,'Test value'];" } In a real example, you'd use the value of currentRow as an index to look up the appropriate information from the Caché database and return one or more values as Javascript statements, or, as above, as a Javascript array. Alternatively, you might pass the currentRow for use by the prePageScript of an Ajax fragment that you target somewhere into your page, eg: <script language="javascript"> function myFunc(currentRecord,currentRow) { var nvp=”rowNo=” + currentRow; ewd.ajaxRequest(“myFragment”,”myTargetId”,nvp) ; } </script> Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 35
  • 36. In this example, we're fetching an EWD fragment named myFragment.ewd that will replace in the innerHTML of the tag whose id is myTargetId. The prePageScript of myFragment.ewd will be able to access the number of the selected row by accessing the Request value named rowNo, eg: s selectedRowNo = $$getRequestValue^%zewdAPI(“rowNo”,sessid) Note that you cannot fire the onRowSelect Event Handler if you are using the <ext:editableGridPanel> tag. Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 36
  • 37. Menu Trees The ExtJS Tree is another very useful widget. It creates the kind of expanding vertical menu trees that are now a familiar part of graphical user interfaces, eg: Once again, EWD makes it very quick and easy to create these trees, of any size and/or hierarchy depth. First, create an EWD page named treeDemo.ewd that contains the following: <ewd:config isFirstPage="true" prePageScript="##class(ewd.test).getDemoTreeData"> <ext:config path="/ext-2.2" /> <html> <head> <title>Ext JS Tree Example</title> </head> <body> <ext:tree datastore="myTreeData" style="overflow:auto;height:300px;width:200px;" text="Cars" / > </body> </html> Like the grid widget, the contents of the tree widget are contained in a JSON datastore. EWD automates everything for you, reducing the task of the designer to determining the positioning and basic styling of the tree, as above. The task of the programmer is to populate the tree datastore within the prePageScript, in this case using a Caché class method named getDemoTreeData(). Create your own version of this method containing the following: Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 37
  • 38. ClassMethod getDemoTreeData(sessid As %String) As %String { s tree(1)="Ford" s tree(2)="Volvo" s tree(3)="Nissan" s tree(4)="Toyota" s tree(5)="Mercedes" s tree(6)="BMW" d createTreeDatastore^%zewdExtJS(.tree,"myTreeData",sessid) QUIT "" } As you can see, the programmer simply creates a local array containing the menu tree options in the order in which they should appear, and then passes this into the createTreeDatastore() method that is provided by EWD. If you save and compile the treeDemo.ewd page and getDemoTreeData() method, and launch the compiled version of treeDemo in a browser, you should see the tree: Now let's add a few more levels to the tree hierarchy. That's very simple to do. Just express these using the natural hierarchy provided by the local array structure: ClassMethod getDemoTreeData(sessid As %String) As %String { s tree(1)="Ford" s tree(1,1)="Focus" s tree(1,1,1)="Petrol" s tree(1,1,2)="Diesel" s tree(1,2)="Mondeo" s tree(1,2,1)="Petrol" s tree(1,2,2)="Diesel" s tree(2)="Volvo" s tree(2,1)="S40" s tree(2,2)="V70" s tree(2,3)="XC90" s tree(3)="Nissan" s tree(3,1)="Micra" s tree(3,2)="Qashqai" s tree(4)="Toyota" Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 38
  • 39. s tree(4,1)="Corolla" s tree(4,2)="Prius" s tree(4,3)="Yaris" s tree(4,3,1)="2 door" s tree(4,3,2)="4 door" s tree(5)="Mercedes" s tree(5,1)="SL-Class" s tree(5,1,1)="SLK Roadster" s tree(5,2)="A-Class" s tree(5,3)="E-Class" s tree(6)="BMW" s tree(6,1)="3 Series" s tree(6,1,1)="318" s tree(6,1,2)="320" s tree(6,1,3)="325i" s tree(6,2)="5 Series" d createTreeDatastore^%zewdExtJS(.tree,"myTreeData",sessid) QUIT "" } Refresh the page in the browser and you'll now see the new version of the tree which can be expanded out to reveal all the levels you've defined above. Now of course we usually want this kind of tree menu so that we can trigger a specific action depending on the menu option we choose. In the EWD/ExtJS tree, you can add an action automatically to any leaf-node in the tree hierarchy. Let's create a simple Ajax-style interaction. First, change the treeDemo.ewd page as follows: <ewd:config isFirstPage="true" prePageScript="##class(ewd.test).getDemoTreeData"> <ext:config path="/ext-2.2" /> <html> <head> <title>Ext JS Tree Example</title> <script language="javascript"> function selectCar(id,value) { var nvp="id=" + id + "&leafValue=" + value ; ewd.ajaxRequest("showCarDetails","carContent",nvp) ; } </script> </head> <body> <ext:tree datastore="myTreeData" style="overflow:auto;height:300px;width:200px;" text="Cars" onClick="selectCar" /> <hr /> <div id="carContent">Details will be shown here</div> </body> </html> Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 39
  • 40. What we've done here is to add an onClick handler to the tree's leaf nodes that will trigger a Javascript function named selectCar. Notice the interface to this function: function selectCar(id,value) EWD ensures that the id and the text value of the leaf node you clicked is passed through to the function. The format of the id is the text string extTreeData followed by the hierarchy level, with each level separated with the character, eg: extTreeData5x1x1 This repesents the leaf node for tree(5,1,1) which was defined as follows: s tree(5)="Mercedes" s tree(5,1)="SL-Class" s tree(5,1,1)="SLK Roadster" The id therefore provides sufficient information to determine exactly which node in the tree was clicked. Of course, if all the leaf nodes have unique text, the value can be sufficient. In the example above, the variable value would have a value of “SLK Roadster”. By passing you both values, you can determine which you need to determine the subsequent action you want to invoke. In the example above, we're going to replace the innerHTML of the tag <div id="carContent"> with a fragment named showCarDetails.ewd, to which we're going to pass two name/value pairs constructed from the id and value. Now we'll create that fragment. Copy the following into a file named showCarDetails.ewd in the extjsDemo directory. <ewd:config isFirstPage="false" pageType="ajax" prePageScript="##class(ewd.test). getCarDetails"/> <span> Car details selected: <?= #carDetails ?> </span> Now we'll create the prePageScript for this fragment: ClassMethod getCarDetails(sessid As %String) As %String { s id=$$getRequestValue^%zewdAPI("id",sessid) s leafValue=$$getRequestValue^%zewdAPI("leafValue",sessid) d setSessionValue^%zewdAPI("carDetails",id_": "_leafValue,sessid) QUIT "" } Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 40
  • 41. We need to do this because the name/value pairs (id and leafValue) are passed as the third parameter of the ewd.ajaxRequest method, and because this is evaluated at run- time, EWD cannot safely instantiate these extra name/value pairs directly into the EWD Session. So they have to be extracted from the EWD Request. We're then concatenating them together and creating a session variable named carDetails. This can then be displayed in the fragment as <?= #carDetails ?>. So now you have all the building blocks. Compile the new version of treeDemo.ewd and the fragment showCarDetails.ewd, and save and compile the class method getCarDetails(). Refresh the compiled version of the treeDemo page and you should see: Open up one of the menu levels and click a leaf node and you should now see something like: Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 41
  • 42. The fragment has replaced the original text at the bottom of the page with the id and text value of the selected tree leaf node. You're now ready to adapt this simple example into your own Ajax applications! ExtJS Forms ExtJS provides a rich set of form field widgets, and once again EWD makes them easy to use. You have two choices as a developer: • use EWD's “raw” tag-based projection of the corresponding ExtJS classes. • Use EWD's augmented form features which allows you to use most of the automation that will be familiar to anyone who has used EWD with standard HTML form fields. This chapter will concentrate on the second choice, so let's start building an EWD/ExtJS form. First, create a new EWD page named formDemo.ewd in your extjsDemo directory, containing the following: <ewd:config isFirstPage="true"> <ext:config path="/ext-2.2" debug="true"/> <html> <head> <title>Form Demo</title> </head> <body> <ext:ewdForm> <ext:FormPanel width="100%" frame="true" autorender="true" /> </ext:ewdForm> </body> </html> Compile using, eg: d compileAll^%zewdAPI(“extjsDemo”,,”php”) Load this page into a browser and you should just see a very thin blue line. This thin blue line is a specific type of Ext Panel (FormPanel) that is designed to contain forms. Because it doesn't yet contain any fields, it is barely visible. The EWD-specific attribute autoRender=”true” tells EWD to add a <div> tag to the page that is used as the rendering point for the FormPanel. Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 42
  • 43. The special EWD tag, <ext:ewdForm>, which provides a container for ExtJS form tags, tells EWD's compiler to add the additional EWD form automation features to the tags it encloses. Now let's add a simple Text field to the FormPanel. Add a <ext:textField> tag inside the <ext:formPanel>: <ewd:config isFirstPage="true"> <ext:config path="/ext-2.2" debug="true"/> <html> <head> <title>Form Demo</title> </head> <body> <ext:ewdForm> <ext:FormPanel width="100%" frame="true" autorender="true"> <ext:textField fieldLabel="First name" name="firstName" value="*" /> </ext:FormPanel> </ext:ewdForm> </body> </html> Recompile the page and re-load it into the browser. You should now see the field at the top of the page: Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 43
  • 44. Note that unlike HTML form fields, the textField allows you to specify the field label as part of the tag. However, just as in standard HTML text fields, EWD allows you to specify a special value of “*” which tells EWD to automatically add the value of a correspondingly named Session variable. Let's see this in action. First, add a pre-page script reference to your page by modifying the <ewd:config> tag: <ewd:config isFirstPage="true" prepageScript=" ##class(ewd.test).getFormDetails"> Next, create the method in your ewd.test class as follows: ClassMethod getFormDetails(sessid As %String) As %String { d setSessionValue^%zewdAPI("firstName","Rob",sessid) QUIT "" } Re-compile the ewd.test class, recompile the formDemo.ewd page and reload the compiled page into the browser. You should now see “Rob” appear in the textField. Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 44
  • 45. Let's add a second text field: <ext:ewdForm> <ext:FormPanel width="100%" frame="true" autorender="true"> <ext:textField fieldLabel="First name" name="firstName" value="*" /> <ext:textField fieldLabel="Last name" name="lastName" value="*" /> </ext:FormPanel> </ext:ewdForm> Now let's slightly modify the pre-page script: ClassMethod getFormDetails(sessid As %String) As %String { i $$getSessionValue^%zewdAPI("firstName",sessid)="" { d setSessionValue^%zewdAPI("firstName","Rob",sessid) d setSessionValue^%zewdAPI("lastName","Tweed",sessid) } QUIT "" } Recompile the class and page. When you reload it into the browser, you should see the two fields, pre-populated with “Rob” and “Tweed” respectively. Now let's add a submit button to allow us to submit the edited form field values back to Caché. <ext:ewdForm> <ext:FormPanel width="100%" frame="true" autorender="true"> <ext:textField fieldLabel="First name" name="firstName" value="*" /> <ext:textField fieldLabel="Last name" name="lastName" value="*" /> <ext:submitButton text="Submit" id="demoFormBtn" action="##class(ewd.test). saveDemoForm" waitMsg="saving data..." nextpage="demoFormPage2" targetId="responseDiv" failMsgTitle="Form Validation Errors" /> </ext:FormPanel> </ext:ewdForm> <div id="responseDiv" /> We've actually added two tags: • a <ext:submitButton> tag, which is EWD's automation tag for defining a submit button. • a div tag: <div id=”responseDiv” /> which provides the target for the content of the fragment demoFormPage2.ewd that has been specified as the nextpage in the submit button tag. Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 45
  • 46. Now add the action script to your ewd.test class: ClassMethod saveDemoForm(sessid As %String) As %String { s firstName=$$getSessionValue^%zewdAPI("firstName",sessid) i firstName="" d setFieldError^%zewdExtJS("firstName","A first name must be entered",sessid) s lastName=$$getSessionValue^%zewdAPI("lastName",sessid) i lastName="" d setFieldError^%zewdExtJS("lastName","A last name must be entered",sessid) QUIT "" } This is somewhat different from a standard EWD form action script in that it should always Quit with a null return value, and each and every form field validation error is trapped and recorded using the special API method setFieldError^%zewdExtJS. You specify the field name that is in error, and also specify the error message for that field. To see how all the things we've added come into play, save and recompile the ewd.test class and re-compile formDemo.ewd. When you re-load the page into the browser, you should now see the submit button: Try clicking the submit button. If you've done everything correctly, you should see: However, you should have also briefly noticed an ExtJS alert window saying “saving data...” before the “Congratulations” text appeared under the form. That was because, in the <ext:submitButton> tag, we'd specified: waitMsg="saving data...". Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 46
  • 47. Now try forcing validation errors. Refresh the page in the browser and then remove the text from both fields before pressing the Submit button. You should now see an ExtJS alert window telling you that field validation errors have occurred: Notice also that the borders of the two fields have been highlighted in red. Click on the alert window's OK button and now move the mouse over each field. You should see a tooltip come up with the error message we specified for that field: In the <ext:submitButton> tag we specified: failMsgTitle="Form Validation Errors". This was used to define the title for the ExtJS alert window. By default, the alert window displays the message “Validation error(s) were reported”. If you want to change this, set the value of the special EWD Session variable ewd.form.errorMessage in your action script, eg: d setSessionValue^%zewdAPI("ewd.form.errorMessage","It failed!",sessid) That's the basics of EWD's ExtJS forms now working, but there's lots more we can do. First let's try out the various ExtJS form field types that are supported in EWD. Add a combo box to the FormPanel in your formDemo.ewd page as follows: Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 47
  • 48. <ext:ewdForm> <ext:FormPanel width="100%" frame="true" autorender="true"> <ext:textField fieldLabel="First name" name="firstName" value="*" /> <ext:textField fieldLabel="Last name" name="lastName" value="*" /> <ext:comboBox store="#cityList" value="*" fieldLabel="City" typeAhead="true" mode="local" name="city" forceSelection="true" selectOnFocus="true" emptyText="Select a City.." /> <ext:submitButton text="Submit" id="demoFormBtn" action="##class(ewd.test). saveDemoForm" waitMsg="saving data..." nextpage="demoFormPage2" targetId="responseDiv" failMsgTitle="Form Validation Errors" /> </ext:FormPanel> </ext:ewdForm> <div id="responseDiv" /> Next, modify the pre-page script to instantiate a list of cities, eg: ClassMethod getFormDetails(sessid As %String) As %String { i $$getSessionValue^%zewdAPI("firstName",sessid)="" { d setSessionValue^%zewdAPI("firstName","Rob",sessid) d setSessionValue^%zewdAPI("lastName","Tweed",sessid) d deleteFromSession^%zewdAPI("cityList",sessid) d appendToComboBoxStore^%zewdExtJS("London","lon","cityList",sessid) d appendToComboBoxStore^%zewdExtJS("New York","nyc","cityList",sessid) d appendToComboBoxStore^%zewdExtJS("Paris","par","cityList",sessid) } QUIT "" } And finally, modify the validation rules in your action script: ClassMethod saveDemoForm(sessid As %String) As %String { s firstName=$$getSessionValue^%zewdAPI("firstName",sessid) i firstName="" d setFieldError^%zewdExtJS("firstName","A first name must be entered",sessid) s lastName=$$getSessionValue^%zewdAPI("lastName",sessid) i lastName="" d setFieldError^%zewdExtJS("lastName","A last name must be entered",sessid) s city=$$getSessionValue^%zewdAPI("city",sessid) i city="Select a City.." d setFieldError^%zewdExtJS("city","A city must be entered",sessid) QUIT "" } Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 48
  • 49. Save and recompile the ewd.test class and your formDemo.ewd page. Reload the page into the browser and now you should see the comboBox. Click on its arrow button and you'll see the cities you specified in the pre-page script will pop up. If you don't select anything (so you leave “Select a City..” appearing in the combo-box), and click the submit button, you should see the combo box highlighted in red. A tooltip should pop up when you move your mouse pointer over it, with the error message we specified in the action script. Note how the comboBox, being a single-choice device, maps to and from the correspondingly named EWD Session variable (in this case city). If you modify the pre-page script to pre-define a value for city, then you'll see that value automatically selected when you refresh the page in the browser. For example: d setSessionValue^%zewdAPI("city","par",sessid) will cause Paris to be automatically selected. There's another thing you can do with a comboBox: make a fragment get automatically requested when an option in the drop-down list is clicked. EWD makes this easy. Just add a nextpage and targetId attribute, eg: <ext:comboBox store="#cityList" value="*" fieldLabel="City" nextpage="demoFormPage2" targetId="responseDiv" typeAhead="true" mode="local" name="city" forceSelection="true" selectOnFocus="true" emptyText="Select a City.." /> The selected option will be passed as a Request name/value pair, where the name is the same as the comboBox name, in this case city. Therefore the pre-page script of the nextpage (demoFormPage2.ewd) could determine which option was clicked by accessing: s city=$$getRequestValue^%zewdAPI(“city”,sessid) However, in our example, we'll not use this additional facility – we'll just use the comboBox as a means of selecting a city prior to clicking the Submit button. Now let's add a group of radio buttons. Make the following change to the form: Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 49
  • 50. <ext:ewdForm> <ext:FormPanel width="100%" frame="true" autorender="true"> <ext:textField fieldLabel="First name" name="firstName" value="*" /> <ext:textField fieldLabel="Last name" name="lastName" value="*" /> <ext:comboBox store="#cityList" value="*" fieldLabel="City" typeAhead="true" mode="local" name="city" forceSelection="true" selectOnFocus="true" emptyText="Select a City.." /> <ext:radioGroup fieldLabel="Sex"> <ext:radio boxLabel="Female" name="sex" inputValue="f" /> <ext:radio boxLabel="Male" name="sex" inputValue="m" /> </ext:radioGroup> <ext:submitButton text="Submit" id="demoFormBtn" action="##class(ewd.test). saveDemoForm" waitMsg="saving data..." nextpage="demoFormPage2" targetId="responseDiv" failMsgTitle="Form Validation Errors" /> </ext:FormPanel> </ext:ewdForm> <div id="responseDiv" /> Add the following line to the pre-page script to pre-select a sex of Male: d setSessionValue^%zewdAPI("sex","m",sessid) After recompiling the class and page and reloading the page into the browser, it should now look as follows: ExtJS provides number, date and time fields. Let's add an example of each: Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 50
  • 51. <ext:ewdForm> <ext:FormPanel width="100%" frame="true" autorender="true"> <ext:textField fieldLabel="First name" name="firstName" value="*" /> <ext:textField fieldLabel="Last name" name="lastName" value="*" /> <ext:comboBox store="#cityList" value="*" fieldLabel="City" typeAhead="true" mode="local" name="city" forceSelection="true" selectOnFocus="true" emptyText="Select a City.." /> <ext:radioGroup fieldLabel="Sex"> <ext:radio boxLabel="Female" name="sex" inputValue="f" /> <ext:radio boxLabel="Male" name="sex" inputValue="m" /> </ext:radioGroup> <ext:numberField fieldLabel="No of tickets" name="tickets" value="*" /> <ext:dateField fieldLabel="Date of Birth" name="dob" value="*" /> <ext:timeField fieldLabel="Departure Time" name="departTime" value="*" /> <ext:submitButton text="Submit" id="demoFormBtn" action="##class(ewd.test). saveDemoForm" waitMsg="saving data..." nextpage="demoFormPage2" targetId="responseDiv" failMsgTitle="Form Validation Errors" /> </ext:FormPanel> </ext:ewdForm> <div id="responseDiv" /> Pre-set values for these in your pre-page script as follows: d setSessionValue^%zewdAPI("tickets",1,sessid) d setSessionValue^%zewdAPI("dob","08/09/2008",sessid) d setSessionValue^%zewdAPI("departTime","10:40",sessid) ExtJS Checkboxes are handled similarly to the ExtJS Radio buttons, eg: <ext:checkboxGroup hideLabel="true"> <ext:checkbox boxLabel="Matching" id="role1" name="roles" inputValue="1" /> <ext:checkbox boxLabel="Query" id="role2" name="roles" inputValue="2" /> <ext:checkbox boxLabel="User Definition" id="role3" name="roles" inputValue="3"/> <ext:checkbox boxLabel="Site Definition" id="role4" name="roles" inputValue="4" /> </ext:checkBoxGroup> Note that the Id of each checkbox item should be unique, but the name of each checkbox in a group should be the same. The checkboxes are integrated with the EWD back-end just like standard HTML checkboxes: using the EWD Selected Session array, eg to pre-check the checkboxes for “Query” and “Site Definition”: d setCheckboxOn^%zewdAPI("roles",2,sessid) d setCheckboxOn^%zewdAPI("roles",4,sessid) When the form is submitted, you can check whether a checkbox value was checked using: Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 51
  • 52. if $$isCheckboxOn^%zewdAPI("roles",2,sessid) do something Alternatively you can merge the selected array into a local one and process it appropriately, eg: d getCheckboxValues^%zewdAPI(“roles”,.selectedArray,sessid) ExtJS Textarea fields are defined as follows: <ext:textarea fieldLabel="Site Description" name="siteDesc" value="*" height="100" width="250" /> Integration with the EWD back-end is the same as the standard HTML textarea. To pre-populate the textarea from your database: s text(1)=”First line of text” s text(2)=”Second line of text” s text(3)=”Last line” d mergeToTextArea^%zewdAPI(“siteDesc”,.text,sessid) And to access the text when the form is submitted, transfer it out to a local array which you can then process appropriately, eg: d mergeFromTextArea^%zewdAPI(“siteDesc”,.text,sessid) Advanced Form Widgets: ItemSelector The ExtJS ItemSelector is a drag-and-drop enabled widget that allows the user to select one or more items from a pre-determined list of options. It is not part of the mainstream ExtJS widgets, but is in their experimental ux library. Nevertheless it is a fully functional and extremely useful widget which has been made extremely easy to use through an EWD tag: <ext:itemSelector>. In order to use the ItemSelector, you must make sure that the files ExtExtensions.js and multiselect.css are loaded into your container page. You'll find these files in the Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 52
  • 53. EWD download kit's zip file. For example, if you've saved the files to your web- server's root path, load them into your container page using: <link rel="stylesheet" type="text/css" href="/multiselect.css"/> <script src="/ExtExtensions.js" type="text/javascript"></script> Now you can add an itemSelector into your <ext:formPanel>, eg: <ext:itemSelector id="myItemSelector" name="sites" hideLabel="true" msWidth="150" msHeight="120" toLegend="Assigned Sites" fromLegend="Available Sites" fromStore="myStore" fromField="Available" toStore="myToStore"/> This will appear as follows: You can use the arrows to move items into the selected panel, or you can drag and drop them. You can pre-define the “from” list using a datastore, and, if required, you can also pre-define the “to” list using a datastore. You'll do this in the pre-page script of the fragment containing the itemSelector, eg: ClassMethod getUserDefinitionData(sessid As %String) As %String { for i=1:1:4 s data(i)="Test site "_i d createItemSelectorDatastore^%zewdExtJS(.data,"myStore","rw",sessid) for i=1:1:2 s todata(i)="to site "_i d createItemSelectorDatastore^%zewdExtJS(.todata,"myToStore","rw",sessid) QUIT "" } As you can see, EWD makes it easy to create the datastores: just create a local array containing the values you want in the list and save it using the createItemSelectorDatastore() method. Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 53
  • 54. When the form is submitted, the selected items in the to list will appear in the EWD Request using the name you assigned to the ItemSelector: in the example above it will be saved into the Request variable named sites (Note: the current implementation does not automatically save the results from the itemSelector widget into the EWD Session). The selected values are comma-delimited, eg in your form's Action script: ClassMethod saveFormData(sessid As %String) As %String { s storeValues=$$getRequestValue^%zewdAPI(“store”,sessid) // If items 2 and 4 had been selected, storeValues = “2,4” QUIT "" } Laying out Forms So far we've just used a single column of form fields. We could combine several fields within a fieldSet. For example: <ext:ewdForm> <ext:FormPanel width="100%" frame="true" autorender="true"> <ext:fieldSet width="92%" title="Personal Details" autoHeight="true"> <ext:textField fieldLabel="First name" name="firstName" value="*" /> <ext:textField fieldLabel="Last name" name="lastName" value="*" /> </ext:fieldSet> <ext:comboBox store="#cityList" value="*" fieldLabel="City" typeAhead="true" mode="local" name="city" forceSelection="true" selectOnFocus="true" emptyText="Select a City.." /> <ext:radioGroup fieldLabel="Sex"> <ext:radio boxLabel="Female" name="sex" inputValue="f" /> <ext:radio boxLabel="Male" name="sex" inputValue="m" /> </ext:radioGroup> <ext:numberField fieldLabel="No of tickets" name="tickets" value="*" /> <ext:dateField fieldLabel="Date of Birth" name="dob" value="*" /> <ext:timeField fieldLabel="Departure Time" name="departTime" value="*" /> <ext:submitButton text="Submit" id="demoFormBtn" action="##class(ewd.test). saveDemoForm" waitMsg="saving data..." nextpage="demoFormPage2" targetId="responseDiv" failMsgTitle="Form Validation Errors" /> </ext:FormPanel> </ext:ewdForm> <div id="responseDiv" /> If you recompile the page and reload it into the browser, it should now look like this: Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 54
  • 55. We could also split the formPanel into two columns by using column Panels. For example, suppose we want the following appearance: We would define this as follows: <ext:ewdForm> <ext:FormPanel width="100%" frame="true" autorender="true"> <ext:Panel layout="column"> <ext:Panel id="lhs" columnWidth=".5" layout="form"> <ext:fieldSet width="92%" title="Personal Details" autoHeight="true"> <ext:textField fieldLabel="First name" name="firstName" value="*" /> <ext:textField fieldLabel="Last name" name="lastName" value="*" /> </ext:fieldSet> <ext:comboBox store="#cityList" value="*" fieldLabel="City" typeAhead="true" mode="local" name="city" forceSelection="true" selectOnFocus="true" emptyText="Select a City.." /> <ext:radioGroup fieldLabel="Sex"> <ext:radio boxLabel="Female" name="sex" inputValue="f" /> <ext:radio boxLabel="Male" name="sex" inputValue="m" /> </ext:radioGroup> </ext:Panel> <ext:Panel id="rhs" columnWidth=".5" layout="form"> <ext:dateField fieldLabel="Date of Birth" name="dob" value="*" /> <ext:fieldSet width="92%" title="Ticket Details" autoHeight="true"> <ext:timeField fieldLabel="Departure Time" name="departTime" value="*" /> Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 55
  • 56. <ext:numberField fieldLabel="No of tickets" name="tickets" value="*" /> </ext:fieldSet> </ext:Panel> </ext:Panel> <ext:submitButton text="Submit" id="demoFormBtn" action="##class(ewd.test). saveDemoForm" waitMsg="saving data..." nextpage="demoFormPage2" targetId="responseDiv" failMsgTitle="Form Validation Errors" /> </ext:FormPanel> </ext:ewdForm> You can see from this example how EWD makes it very simple to nest Panels within Panels to any depth you wish. Each Panel can be given a unique id, so that it can be used as a target for EWD fragments. You can also hide and display panels from within Javascript using: /* To hide the lhs column */ Ext.getCmp('lhs').hide() ; /* To show the lhs column again*/ Ext.getCmp('lhs').show() ; You can hide and reveal form fields from within Javascript too, by using some pre- built functions that EWD provides for you: /* To hide the Date of Birth field */ EWD.ext.hideField(Ext.getCmp('dob')) ; /* To show the Date of Birth field again */ EWD.ext.showField(Ext.getCmp('dob')) ; Note that in our example form we haven't assigned an id for any of the fields. In fact, as part of EWD's form automation, you only need to specify either a name or id attribute in a form field. EWD will add the missing attribute, assigning the value of the one that is present. So, for example, the Date of Birth field has the attribute name=”dob”. EWD will automatically add id=”dob” to the field at compile time. This means that we can use any of the Javascript methods that identify a form field by its id attribute, without having to explicitly define it. The net result is that we can use all the sophistication of ExtJS form field widgets, and yet define a form in a very succinct and intuitive way, as shown in the final example above. Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 56
  • 57. Modal Windows EWD makes it easy to use ExtJS's modal pop-up windows. Just define a modal window object using the <ext:modalWindow> tag and reference it from within the special EWD function EWD.ext.openWindow() that can be called from any event handler. For example, a simple scenario is a page that contains a button which, when clicked, triggers the creation of the modal window. Copy the page definition below and save it in a file named ModalWindowDemo1.ewd in the extjsDemo application directory. <ewd:config isFirstPage="true"> <ext:config path="/ext-2.2" /> <html> <head> <title>Modal Window Demo</title> </head> <body> <div> <input id="windowBtn" type="button" value="Start Modal window" onclick="EWD.ext.openWindow(theWindow)" /> <ext:modalWindow id="myModalWindow" object="theWindow" title="Demo Modal Window" height="auto" width="300" src="modalWindowContent1" /> </div> </body> </html> In this example, the <ext:modalWindow> tag defines an ExtJS modal window object and instantiates it with a name of theWindow. Normally EWD's compiler automatically assigns names to the objects it creates from the ExtJS tags, but you can over-ride this behaviour and assign your own object name by using the object= attribute. When you assign your own name, EWD doesn't “var” the object name, so it becomes available globally throughout your page. As a result, you can refer to and use the object theWindow anywhere in your page, so in this case we're using it in the OnClick event handler of the Button that we've defined in the page. To open the modal window, we use the special built-in method EWD.ext.open() and pass the theWindow object into it. Note: behind the scenes, EWD ensures that this mechanism cannot be hi-jacked to call up any arbitrary fragment in the modal window. Only the one specified in the page/fragment definition will be allowed to be displayed in the modal window. Now let's create the fragment that contains the content for the modal window. Copy the page definition below and save it in a file named modalWindowContent1.ewd in the extjsDemo application directory: Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 57
  • 58. <ewd:config pageType="ajax" isFirstPage="false"> <script language="javascript"> function okAction() { /* do something here! */ /* then close the window */ EWD.ext.window.destroy() ; } </script> <div> <center> <p>This is a demo of an ExtJS modal window</p> <br /> <ext:button id="OK" text="OK" autoRender="true" handler="okAction()" /> </center> </div> Compile these two pages and load the compiled ModalWindowDemo1 page into your browser. You should see the following: When you click the button you should see: If you click the OK button, the modal window will disappear. The destruction of the window is done by the line of Javascript: Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 58
  • 59. EWD.ext.window.destroy() ; EWD has created the object EWD.ext.window for you which represents the modal window widget. The ExtJS destroy() method removes the window. You can easily add multiple buttons and assign different handlers to them, eg modify modalWindowContent1.ewd as follows: <ewd:config pageType="ajax" isFirstPage="false"> <script language="javascript"> function okAction() { /* do something here! */ /* then close the window */ EWD.ext.window.destroy() ; } </script> <div> <center> <p>This is a demo of an ExtJS modal window</p> <br /> <ext:button id="OK" text="OK" autoRender="true" handler="okAction()" /> <ext:button id="Cancel" text="Cancel" autoRender="true" handler="EWD.ext.window.destroy ()" /> </center> </div> If you save and recompile your pages, you'll now see that the modal window has two buttons. However, they will be rendered one above the other which doesn't look very good: Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 59
  • 60. We can re-arrange these buttons by using the ExtJS renderTo config option for each button, rendering them to two <div> tags that we'll line up by using a table, ie: <div> <p>This is a demo of an ExtJS modal window</p> <ext:button id="OK" text="OK" renderTo="leftx" handler="okAction()" /> <ext:button id="Cancel" text="Cancel" renderTo="rightx" handler="EWD.ext.window.destroy()" /> <table align="center"> <tr> <td id="leftx">&nbsp;</td> <td>&nbsp;</td> <td id="rightx">&nbsp;</td> </tr> </table> </div> Now the buttons will line up nicely: Triggering the opening of a modal window can be done using the event handlers of any tags. For example, we could have used an ExtJS button: <ext:button id="ExtButton" text="OK" autoRender="true" onclick="EWD.ext.openWindow (theWindow)" /> Modal Window Forms One common use of a modal window is to contain a form. Let's examine how this can be done and controlled. We'll demonstrate this with a simple logon window. Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 60
  • 61. Copy the page definition below and save it in a file named modalWindow1d.ewd in the extjsDemo application directory: <ewd:config isFirstPage="true"> <ext:config path="/ext-2.2" /> <html> <head> <title>Modal Window Demo</title> </head> <body onload="EWD.ext.openWindow(loginWindow)"> <div id="contentDiv"> <ext:modalWindow id="myModalWindow" closable=”false” object="loginWindow" title="Logon" height="auto" width="300" src="modalWindowContent1d" /> </div> </body> </html> There's not much difference in this container page from our previous example: however this time we're using the page's onload event hander to trigger the modal window and the modal window content fragment is now modalWindowContent1d.ewd which will contain the logon form. We've also given the <div> tag that surrounds the button an id of “contentDiv” which we'll later use as a target for a fragment. The idea is that if the user logs in correctly, the login button will disappear, to be replaced with the new fragment contents. The modal window is also set not to be closable, so there's no way to bypass this modal login dialogue. Now let's create the login form which will populate the modal window. Copy the page definition below and save it in a file named modalWindowContent1d.ewd in the extjsDemo application directory: <ewd:config pageType="ajax" isFirstPage="false"> <span> <ext:ewdForm> <ext:FormPanel width="100%" frame="true" autorender="true"> <ext:textField fieldLabel="Username" name="username" value="" /> <ext:textField fieldLabel="Password" inputType="password" name="password" value="" /> <ext:submitButton id="logonBtn" text="OK" action="##class(ewd.test).logonTest" waitMsg="please wait..." nextpage="modalWindowContent2d" targetId="contentDiv" failMsgTitle="Logon Error" /> </ext:FormPanel> </ext:ewdForm> </span> The <ext:ewdForm> and <ext:FormPanel> tags are described in detail in the previous chapter on Forms. We're using two textFields for the username and password, the password defined as inputType=”password” to ensure that it doesn't display the password as you type it. Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 61
  • 62. We need to use a submit button, which is provided by the <ext:submitButton> tag. Let's look at what the submit button will do when it is clicked: <ext:submitButton id="logonBtn" text=”OK” action="##class(ewd.test).logonTest" waitMsg="please wait..." nextpage="modalWindowContent2d" targetId="contentDiv" failMsgTitle="Logon Error" /> It will post the form contents to the Caché back-end and invoke the action script method ##class(ewd.test).logonTest which we'll use to validate the username and password. If the validation passes successfully, EWD will return a fragment named modalWindowContent2d which will be targetted into the container page's <div id=”contentDiv”> tag. While the posting and validation is taking place, the user should see an alert message saying “please wait..”. Let's now look at the action script method ##class(ewd.test).logonTest which you should add to your ewd.test class: ClassMethod logonTest(sessid As %String) As %String { s username=$$getSessionValue^%zewdAPI("username",sessid) i username'="rob" d setFieldError^%zewdExtJS("username","Invalid login attempt",sessid) s password=$$getSessionValue^%zewdAPI("password",sessid) i password'="rob" d setFieldError^%zewdExtJS("username","Invalid login attempt",sessid) QUIT "" } For simplicity we've hard-coded the logic to only allow a username and password of rob and rob respectively, but usually you'd authenticate against some kind of look-up table in your database. What this method will do is as follows: • If either or both fields are invalid, it will set a field error that will highlight the username field. If you roll the mouse over the highlighted field, you'll get an ExtJS tooltip saying “Invalid login attempt”. • If a field error is set, then EWD will also automatically pop up an ExtJS alert window telling you that an error occurred. The title of this alert window was defined in the <ext:submitButton> using the failMsgTitle="Logon Error" attribute. OK we're nearly done. The final piece in the jig-saw is the fragment that we'll return if the user successfully logs in. Copy the page definition below and save it in a file named modalWindowContent2d in the extjsDemo application directory: Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 62
  • 63. <ewd:config pageType="ajax" isFirstPage="false"> <script language="javascript"> EWD.ext.window.destroy() ; </script> <div> <p>Congratulations! You've successfully logged in!</p> </div> The important thing to note in this fragment is the Javascript section which destroys the modal window. That's all the bits we need! Save and compile the pages and the class method. Now load the container page into your browser. It should look like this: Now enter an invalid username and password (ie anything other than rob and rob respectively) and click the OK button. You should see the “please wait..” message appear briefly and then you'll get: Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 63
  • 64. When you click on the OK button on the alert window, you should now see the username field highlighted, and if you roll the mouse over it, you'll see: Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 64
  • 65. Now log in correctly (username=rob and password = rob) and click the OK button. The modal window should now disappear and a success message will replace the original login button: That's it! You now have a fully working ExtJS modal form window! Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 65
  • 66. Adding a Progress Bar ExtJS has a very cool progress bar widget that EWD makes very easy to use. Here's how to use it. First, add a <div> tag to your page to provide an anchoring/rendering point for the progress bar. You may want it centered, in which case you could use a table, eg: <table border="0" width="100%" style="table-layout:fixed"> <tr> <td width="10%">&nbsp;</td> <td width="80%" id="progbar" align="center"> &nbsp; </td> <td width="10%">&nbsp;</td> </tr> </table> Now add the progress bar widget anywhere in the page. Initially we'll make it hidden, eg: <ext:progressBar id="progress" width="300" renderTo="progbar" hidden="true" /> Note how we tell it to render itself into the <div> we created. The idea is that we'll make the progress bar appear when an appropriate event handler fires. So in the Javascript function for that event handler, add the following: function submitTheGrid() { var progBar = Ext.getCmp('progress') ; progBar.show() ; progBar.wait({ interval:200, duration:30000, increment:15, text:'Please wait...' }); You can adjust any of the config options in the progBar.wait() method. The duration defines the maximum duration that the progress bar will cycle its animation. ProgBar.show() will make the progress bar appear. So that's the progress bar now on display. How do we turn it off? That's very simple: Ext.getCmp("progress").hide() is the method to use, so we just invoke this at the point at which we know the task has completed. For example, if the initial event triggers the fetching of an EWD fragment, then we can use its <ewd:ajaxOnload> block, ie: Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 66
  • 67. <ewd:ajaxOnload> Ext.getCmp("progress").hide() ; </ewd:ajaxOnload> EWD doesn't execute the Javascript within the <ewd:ajaxOnLoad> block until the fragment has been loaded into the container page, so this is the perfect place to make the progress bar disappear! That's it! You now have a progress bar on your page. Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 67
  • 68. Advanced Use of EWD's ExtJS Custom Tags As you've seen, EWD automates most of the day-to-day use of ExtJS widgets that you're likely to need, but there may be occasions when you want to take more control of what's going on. One way, of course, is to hand-craft your own ExtJS Javascript, but you'll find that this is rarely necessary. You can make use of a lot of the “hidden” tags that EWD's compiler uses behind the scenes when converting ExtJS Custom tags into the final ExtJS Javascript code, in particular allowing you to define your own listeners (the ExtJS equivalent of Event Handlers). You can also harness calls to EWD via ExtJS's own use of the XMLHttpRequest object, and instruct EWD to just send back a raw stream of Javascript without any of the additional EWD-specific code that it would normally add. Adding Listeners To add your own listener to an EWD/ExtJS tag, you first need to consult the ExtJS API manual (http://www.extjs.com/deploy/dev/docs/) to find the specification for the listener you wish to use. You'll find this in the Public Events section. For example, let's add a click listener to an Ext.Button widget. You'll find this listed in the Public Events section as follows: click : (Button this, EventObject e) Fires when this button is clicked So this event passes two objects to the Event Handler that you will specify: the current button object and the event object. Now we can add the listener. In fact an ExtJS object can have multiple listeners, so you specify two nested tags: • <ext:listeners> This provides the container for the set of listeners that you want to add to the object. • <ext:listener> This contains a specific listener. So let's start with our button: <ext:button id="myButton" text="Click me" autoRender="true"> </ext:button> Note: you'll need to specify autoRender=”true” if this is a standalone button which is not nested inside an ExtJS layout widget such as a Panel. Now add the listeners container tag inside the button tag: <ext:button id="myButton" text="Click me" autoRender="true"> <ext:listeners> </ext:listeners> </ext:button> Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 68
  • 69. Now you can add the click listener inside the listeners tag. You specify the name of the listener and its parameters in order, using the attributes param1, param2, ... paramn , making sure you match the documented interface, eg: <ext:button id="myButton" text="Click me" autoRender="true"> <ext:listeners> <ext:listener name="click" param1="buttonObj" param2="event"> <ext:listener> </ext:listeners> </ext:button> Finally, inside the <ext:listener> tag you can specify the Javascript that you want to invoke when the listener fires, eg: <ext:button id="myButton" text="Click me" autoRender="true"> <ext:listeners> <ext:listener name="click" param1="buttonObj" param2="event"> alert(buttonObj.id) ; <ext:listener> </ext:listeners> </ext:button> Compile and run your example and you should see the button and when you click it, you'll get an alert window showing the id of the button: You can add as many individual listeners inside a <ext:listeners> tag. Direct use of ExtJS XHR Events If you want to make use of ExtJS's own XMLHttpRequest object interface, but you want to access the EWD session at the back-end, you can use a special mechanism that instructs EWD to send a raw stream back to ExtJS without all the extra code and markup that EWD will normally add (the additional markup is used by EWD's XHR interface). Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 69
  • 70. To do this, invoke a call to a fragment as usual, but define the fragment somewhat differently. You specify the pageType as rawFragment and wrapper the fragment's content in the <ewd:rawcontent> tag, eg: <ewd:config isFirstPage="false" pageType="rawfragment" prepagescript="##class(ewd.test).getAlert"> <ewd:rawcontent> </ewd:rawcontent> Inside the rawcontent you can specify any Javascript you like. This can be hard- coded, eg <ewd:config isFirstPage="false" pageType="rawfragment" prepagescript="##class(ewd.test).getAlert"> <ewd:rawcontent> Ext.Msg.show({ title:'<?= #alertPrompt ?>', msg: '<?= #alertText ?>', buttons: Ext.Msg.OK, icon: Ext.MessageBox.QUESTION }); </ewd:rawcontent> Or you can generate the entire contents programmatically using an <ewd:execute> tag, eg: <ewd:config isFirstPage="false" pageType="rawfragment"> <ewd:rawcontent> <ewd:execute method="##class(ewd.test).generateContent" param1="#ewd_sessid" type="procedure" /> </ewd:rawcontent> Note the way you can pass the EWD Session Id into your method using param1=”#ewd_sessid”. The advantage of this latter approach is that you can stream as much generated Javascript content as you like into the ExtJS page – it is not limited by, for example, the common Caché maximum string length of 32k. Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 70
  • 71. The EWD/ExtJS Desktop The techniques and widgets described above allow you to use the ExtJS widgets in conventional web and Ajax applications. However, ExtJS can go one better, and provide you with a new way of presenting applications, using the ExtJS web desktop widgets. EWD makes it amazingly simple to make use of these widgets to create your own, fully functioning web desktop applications. In order to use the EWD/ExtJS desktop widgets, you'll need to download the additional customised components from the M/Gateway web site. You'll find these at http://gradvs2.mgateway.com/main/extjs_desktop.zip Copy the contents into your ExtJS Javascript directories, eg /var/www/html/ext-2.2, maintaining the path structure within the zip file. This will create two new subdirectories named desktop and images, ie /ext-2.2/desktop /ext-2.2/images You can now begin developing a desktop. Let's start with a very simple example. Create a new file named desktopDemo.ewd in your extjsDemo directory, containing the following: <ewd:config isFirstPage="true"> <ext:config path="/ext-2.2" /> <html> <head> <title>EWD/Ext-JS Desktop</title> </head> <body> <ext:desktop title="Rob Tweed" iconClass="user" backgroundImage="/ext- 2.2/desktop/ewdExtDesktop.jpg"> <ext:window title="Grids" showOnDesktop="true" desktopIcon="/ext-2.2/images/grid48x48.png" iconClass="panel" width="430" height="300" src="gridDemo2.ewd" /> </ext:desktop> </body> </html> Adjust the image paths according to your ExtJS installation. Compile and run this page in a browser and you should see the following: Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 71
  • 72. You have your first web desktop application up and running! Let's take a look at what the EWD page defined. First, the <ext:desktop> tag creates the desktop container and defines the backdrop image to use for your desktop. If you click on the Start button, you'll also see the username you specified appearing at the top of the start panel. Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 72
  • 73. Everything else is defined in the <ext:window> tags. In this case we've only defined a single main window for the desktop which is associated with the single desktop icon named Grids. The current version of the desktop also mirrors this in the Start panel. Let's take a look at the <ext:window> tag we specified: <ext:window title="Grids" showOnDesktop="true" desktopIcon="/ext-2.2/images/grid48x48.png" iconClass="panel" width="430" height="300" src="gridDemo2.ewd" /> The attributes are as follows: • title Specifies the text to display on the icon • showOnDesktop Display the icon on the desktop if true • desktopIcon Specifies the image file to use as the desktop icon • iconClass Specifies the class that defines the window image icon in the Start panel, the taskbar and the window title bar • width the width of the window that will pop up • height the height of the window that will pop up • src the name of the fragment that will populate the window If you click the Grids icon, a window should pop up with the dimensions you specified (430 X 300), but it will contain the text Please wait... and you should then see an Invalid Request error. This is because we haven't yet created the fragment that will contain the content for the window. We specified this to be src="gridDemo2.ewd" We've already created a grid demo page, but that was a complete web page rather than a fragment, but we can quickly adapt it into a fragment. First, copy gridDemo.ewd to gridDemo2.ewd Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 73
  • 74. Next, edit it to contain the following: <ewd:config isFirstPage="false" pageType="ajax" prePageScript="##class(ewd.test). getDemoGridData"> <span> <ext:grid datastore="myData" stripeRows="true" title="Example Ext/EWD Grid" width="400" frame="true" liveUpdate="true" validationScript="class(ewd.test).setDemoGridData"> <ext:gridColumn header="Company" width="60" sortable="true" tooltip="The company in question"/> <ext:gridColumn header="Price" type="float" width="30" editAs="number" sortable="true" /> <ext:gridColumn header="Change" type="float" width="30" sortable="true" /> <ext:gridColumn header="In Stock" type="bool" renderAs="checkbox" width="30" /> </ext:grid> </span> So now it's just a fragment of markup, without a <head> and <body> section, and it is declared as pageType=”ajax” in the <ewd:config> tag. Compile this new fragment and it should now work. Reload the main desktop page and then click the Grids icon (sometimes it takes a few seconds to become activated, particularly in Firefox). You should now see the following: Now all you need to do is adjust the window and/or grid dimensions and you'll have a great-looking web desktop application, and all built in just a few minutes! Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 74
  • 75. Try adding more desktop icons, and convert some of your other ExtJS examples into fragments to use as contents for your windows. To do this, just add more <ewd:window> tags inside your <ext:desktop> tag in the main container page. Special Use of Trees in the ExtJS Desktop Something that is very useful in the desktop environment is to bring up an initial window that contains a tree menu. When you click any of the leaf nodes, you want a new window to pop up, but the fragment that populates the window should be dependent on the leaf node you clicked. EWD makes this very simple. First, let's add a new icon to our desktop: <ext:desktop title="Rob Tweed" iconClass="user" backgroundImage="/ext- 2.2/desktop/ewdExtDesktop.jpg"> <ext:window title="Grids" showOnDesktop="true" desktopIcon="/ext-2.2/images/grid48x48.png" iconClass="panel" width="430" height="300" src="gridDemo2.ewd" /> <ext:window title="Tree Demo" showOnDesktop="true" desktopIcon="/ext- 2.2/images/about48x48.png" iconClass="panel" width="200" height="200" src="treeDemo2.ewd" /> </ext:desktop> Now create the treeDemo2.ewd fragment that will populate the pop-up window created when we click the Tree Demo icon: <ewd:config isFirstPage="true" pageType="ajax" prePageScript="##class(ewd.test). getDemoTreeData2"> <span> <ext:tree datastore="myTreeData" style="overflow:auto;height:300px;width:200px;" text="Cars" autoWindow="true" windowWidth="400" windowHeight="300" /> /> </span> This will create a tree menu, but notice the autoWindow, windowWidth and windowHeight attributes. These cause a new window to open whenever any leaf node is clicked. Now we need to define the tree via the prePageScript: ClassMethod getDemoTreeData2(sessid As %String) As %String { s tree(1)="Ford"_$c(1)_"treeDemoFrag1" s tree(2)="Volvo"_$c(1)_"treeDemoFrag2" s tree(3)="Nissan"_$c(1)_"treeDemoFrag3" d createTreeDatastore^%zewdExtJS(.tree,"myTreeData",sessid) QUIT "" } Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 75
  • 76. Notice how we can define a fragment name for each leaf node by setting the second piece in each tree node (where the delimiter is ASCII 1) to the name of the required fragment. So, in other words, when we click the Ford option, the window that pops up will be populated by a fragment named treeDemoFrag1.ewd. Now all we need to do is create the three fragments referred to by the prePageScript. Initially let's just create some simple basic content to demonstrate how it will all work: treeDemoFrag1.ewd: <ewd:config isFirstPage="false" pageType="ajax" /> <span> You selected a Ford! </span> treeDemoFrag2.ewd: <ewd:config isFirstPage="false" pageType="ajax" /> <span> You selected a Volvo! </span> treeDemoFrag3.ewd: <ewd:config isFirstPage="false" pageType="ajax" /> <span> You selected a Nissan! </span> Compile all these pages and when you re-load the main container page in the browser, you should then see the following (the tree window has been dragged to the left for clarity): Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 76
  • 77. Now you're all set. You can now modify the three simple fragments and start populating the windows with much more complex content. Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 77
  • 78. Running Separate EWD Applications in Desktop Windows A cool trick with the desktop is to use the pop-up windows to act as containers for completely self-contained EWD applications (or indeed any other web application). Just load the window with a fragment that contains an <iframe> tag. The <iframe> can then load anything it likes into itself. You now have a complete application running in a desktop window! Here's a quick guide to this trick. First add a new icon to your desktop: <ext:window title="ewdMgr" showOnDesktop="true" desktopIcon="/ext- 2.2/images/ewdMgr48x48.png" iconClass="panel" width="800" height="600" src="loadEwdMgr.ewd" /> Now create the fragment named loadEwdMgr.ewd: <ewd:config isFirstPage="false" pagetype="ajax"> <span> <iframe src="/php/ewdMgr/index.php" width="100%" height="100%" frameborder="0"></iframe> </span> You'll probably need to modify the src path for the ewdMgr application for your environment (or use a path to some other existing application). That's all there is to it! Compile the desktopDemo.ewd and loadEwdMgr.ewd pages and it should now work: Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 78
  • 79. There you go! A complete web desktop application, and all built in a matter of a few minutes! Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 79
  • 80. APPENDIX I Mapping of EWD ExtJS tags to ExtJS Objects Tag Name ExtJS Class <ext:button> Ext.Button <ext:checkBox> Ext.form.Checkbox <ext:checkBoxGroup> Ext.form.CheckboxGroup <ext:checkItem> Ext.menu.CheckItem <ext:columnLayout> Ext.layout.ColumnLayout <ext:comboBox> Ext.form.ComboBox <ext:dataArrayReader> Ext.data.ArrayReader <ext:dataArrayReaderRecord> Maps to simple object <ext:dataStore> Ext.data.Store <ext:dateField> Ext.form.DateField <ext:editorGridPanel> Ext.grid.EditorGridPanel <ext:fieldSet> Ext.form.FieldSet <ext:formLabel> Ext.form.Label <ext:formPanel> Ext.form.FormPanel <ext:formSubmit> Maps to simple object <ext:grid> Converted and transformed to <ext:gridPanel> <ext:gridCheckColumn> Ext.grid.CheckColumn <ext:gridColumn> Maps to simple object <ext:gridColumnModel> Maps to simple object <ext:gridEditor> Ext.grid.GridEditor <ext:gridPanel> Ext.grid.GridPanel <ext:gridRowExpander> Ext.grid.RowExpander <ext:gridViewConfig> Maps to simple object <ext:hiddenField> Ext.form.HiddenField <ext:itemSelector> Ext.ux.ItemSelector <ext:layoutConfig> Maps to simple object <ext:listeners> Maps to simple object <ext:menu> Ext.menu.Menu <ext:menuItem> Ext.menu.Item <ext:menuSeparator> Ext.menu.Separator <ext:menuTextItem> Ext.menu.TextItem Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 80
  • 81. Tag Name ExtJS Class <ext:modalWindow> Maps to simple object <ext:numberField> Ext.form.NumberField <ext:panel> Ext.Panel <ext:progressBar> Ext.ProgressBar <ext:radio> Ext.form.Radio <ext:radioGroup> Ext.form.RadioGroup <ext:statusBar> Ext.StatusBar <ext:store> Maps to simple object <ext:tabPanel> Ext.TabPanel <ext:template> Ext.Template <ext:textarea> Ext.form.TextArea <ext:textField> Ext.form.TextField <ext:timeField> Ext.form.TimeField <ext:toolbar> Ext.Toolbar <ext:toolbarFill> Ext.Toolbar.Fill <ext:toolbarSeparator> Ext.Toolbar.Separator <ext:toolbarSpacer> Ext.Toolbar.Spacer <ext:toolbarTextItem> Ext.Toolbar.TextItem <ext:toolbarButton> Ext.Toolbar.Button <ext:triggerField> Ext.form.TriggerField <ext:viewport> Class Ext.Viewport <ext:window> Class Ext.Window Enterprise Web Developer : Using the ExtJS Widgets. Version 4.0.746: 08 December 2008. © 2008, M/Gateway Developments Ltd. All Rights Reserved 81

×