Morfik 07 - Working with Forms
From Morfikwiki.com
One of the major differences between Morfik tools and all other development tools for the creation of Web applications is that the WebOS AppsBuilder does not force the developer to understand how a browser works or how remote calls to a server happen. The developer does not need to know how to code HTML, XHTML, CSS, ASP, PHP, SOAP or whatever other acronym that has ever been invented to describe techniques and file formats for web development. Applications for the Web are developed in the same way that common applications are developed using tools such as Borland’s Delphi or Microsoft’s Visual Studio.
When I first tried out Morfik AppsBuilder I was immediately impressed by how easy it was to create the basics of a web application, without actually doing any coding. What is more impressive was that not only did it not ask me to write any HTML or scripting code, but it did not spit these out at me. I have seen many tools that allow you to design HTML form interfaces and generate the corresponding HTML files for you. Up to that moment they had been the pinnacle of web development tools for me. Tools that offered WYSIWYG HTML design and were able to organize your scripting code were the best one could expect. After ten years of intense development efforts by people all around the world that was as far as we had come.
New languages had been created and were flourishing. A major example of this is the PHP scripting language currently in use in thousands, if not millions, of web servers all around the globe. Techniques had been developed and file and data formatting standards created. New terms such as SOAP and XML had come into the everyday life of the software developer, or at least of those trying to stay in synch with what was being developed. Things had been progressing at a frenetic pace, driving us forward into new and unexplored frontiers such as hosted Customer Relationship Management and even Word Processors, available on the web.
[edit] A Problem To Be Solved
The only thing that bothered me was that I always thought that development tools were going about this in the wrong way. Why? Well let’s go back a couple of years... I used to work a lot with Borland’s Delphi and Microsoft’s Visual Basic, two very similar, yet very different development tools. They were similar in the interface that they provided to the developer and in the way you could extend them with user-created components. They were different in how things were implemented under the hood. While Visual Basic was an interpreted language, depending on an extensive runtime library to execute applications and thus limiting what you could build with it (its own add on components had, for a long time, to be built with another language), Delphi was a native compiler which produced first class binary executables for the Win32 platform.
Both of these tools, as well as several others, hid entirely from the developer all the necessary plumbing for getting a Windows application up and running. Using the Windows Software Development Kit (SDK) and a C compiler, you needed to write one hundred and seventeen lines of code just to display an empty blank window, which did nothing. Later tools such as Turbo Pascal for Windows and Visual C would cut that down to twenty to thirty lines, by using extensive and elaborate class libraries (OWL and MFC).
It was into that scenario that Microsoft introduced Visual Basic as a tool for the speedy creation of simple applications for Windows. It totally hid all the complexity of the Windows environment and allowed developers to get an empty window up and running with zero lines of code. It was a major breakthrough and soon developers started flocking towards it. Borland took this new way of developing Windows applications to a whole new level when it introduced Delphi. Delphi offered the same ease of use of Visual Basic but instead of depending on a runtime and interpreted code, had an IDE that generated code, on-the-fly, for using its sophisticated and high-level class library, called the Visual Component Library (VCL). The VCL was entirely written in Delphi and, again, totally hid the details of how the Windows environment worked. It allowed you to create the same zero lines of code window, but it did so as a native binary application which although it still did nothing, did it with a reduced size and better performance. This was the era of visual tools and Rapid Application Development (RAD).
[edit] Taking Visual RAD to the Web
So, why are we talking about developing applications for Windows with tools from Microsoft and Borland when this is a book about Morfik? Well, I want to make a point. Back in the days of the pure C and SDK development for Windows it was important, maybe even cool, to know all the hundreds of functions of the Windows API. (I read the manuals for it.) You had to know how Windows worked in order to be able to develop anything for it. Even the simplest of applications required the understanding of things such as creating a message processing loop, painting text onto the screen, etc, until these visual development tools, I mentioned, came along. When the World Wide Web hit us in the face, in 1995, it was all about text and content. As its convenience and ubiquity grew, it soon became a platform for application development and delivery and so we were back to the time when it was necessary to know how things worked in order to get anything done. This time, instead of needing to know how Windows worked we needed to know how the Web worked. It was studying HTML, JavaScript and server/browser communication instead of the Windows API. One interesting aspect of it was that it all seemed very easy. You could just bring up notepad and type in a web page.
Development tools for the Web soon took us beyond notepad. But as each new tool appeared and evolved it was always about making it easier for you to use the "Web API", and not about hiding it. It seems that people just decided that it was too important that everybody know how this stuff worked - until Morfik came along. The people that started Morfik had the same belief that I had; that it was unacceptable that someone had to learn all that stuff (HMTL, XHTML, JavaScript, Blah, Blah...) in order to be able to write simple applications for the Web. They perceived that the Web had, in fact, become an application platform, as had Windows before it and that people needed a more productive way to develop applications for this platform. Luckily for all of us, they had the resources and the will to apply these, as well as their time, to this problem and bring us to this point.
Now, working with Morfik WebOS AppsBuilder we can go back to talking about forms and controls and business needs without having to worry about learning how the Web works. We have been using it for over a decade and it is about time that we let go of the text files and start developing real applications for this wondrous new platform. This is what this chapter is about: Working with Forms and how it is different from working on legacy web applications. Although Morfik forms are very similar to windows forms at design time they are quite different at run time.
This is quite deceptive and could potentially become an impediment if the distinct run time model for Morfik forms is not understood early in the learning cycle
[edit] A Page By Any Other Name
In the WebOS AppsBuilder we do not write pages, but design Forms. How can that be, when the Web itself works with Pages? Well, we do work with Pages; we just don’t need to think of them quite that way, most of the time. The main interface metaphor used by the AppsBuilder is the Form, as in all major Windows development tools. This is a significant difference because when software development became Page-centric, to accommodate the way things worked on the Web, it missed the point that Web Pages were for delivering text content and not interactive applications. Modern, Ajax enabled, Web applications have few pages, but these pages go through several changes in appearance in order to interact with the user. With Morfik AppsBuilder you design Forms for user interaction and not just text presentation.
Another major difference between Morfik Forms and HTML Pages is that the Forms can be self-containing (both at design time and at run time) and therefore extremely modular. HTML pages are NOT! Though you can use server side to compose a Page from several HTML snippets, you cannot say that you define an HTML Page in terms of other HTML Pages.
Due to this characteristic the layout and, more importantly, the behavior of an arbitrarily complex page can be recursively reduced down to simpler and simpler Form constructs.
In several of the previous chapters of this book, I have used WebOS Forms as examples of how things are done in the AppsBuilder and how you can use your language of choice to develop applications. In this chapter we will go a lot deeper into what Forms are and how they are used.
[edit] Every Page is a Form, But Not All Forms are Pages
One of the most important things to know about Forms is that in the WebOS AppsBuilder all Pages are Forms, but not all Forms are Pages, just as all squares are rectangles, but not all rectangles are squares. This might seem a bit confusing, at first, but it is really simple. Forms can represent not only an entire Page, but portions of a Page. You can actually build Forms that are composed of several other Forms. For every page in your application you will have a "top level" Form which may or may not contain other Forms in SubForm controls. While this might not seem like much at first, you will soon see that this simple feature opens up enormous possibilities in application interface design. This is particularly true because in contrast to the Windows environment where building interfaces based on user created visual components, such as Forms, might have added "weight" to the application, the WebOS AppsBuilder knows how to translate your interface design into the appropriate dynamic HTML code without adding unnecessary weight to your application. The diagram in Figure 1 should give you a general idea of how a Page/Form can be composed of several Forms (in this case called SubForms).
[edit] Where Does an Application Start?
When you create a new project in the Morfik IDE, it already has its first Form. This Form is called Index and it is the default starting Form for you application. This closely parallels the way web servers work, since most expect a Page called Index.html to be present in the directory that is being published. You can change the name of this Form or specify any other Form as the default startup Form for your application by going to the Application tab of the Options dialog and changing the Main Form property It is this project property that tells the Morfik compiler which of the Forms that make up the project will be the entry point for your application.
[edit] Designing a Form
In the Morfik WebOS AppsBuilder it is very easy to build Forms. It is, actually, very much like building Forms in any modern visual development environment for Windows. Once you enter the Form Designer you will see a floating palette of controls that can be used to create the interface of your application. There are several different controls that can be used in combination to achieve very interesting results.
In Figure 1 you can see a view of the toolbox with the available controls. As all who have developed applications in a visual IDE will notice, the main controls are the same as you would have in such a tool. Let’s review some of the basic controls:
| Glyph | Control |
| TextLabel – This control is mainly used for displaying information (text) in the Form/Page being constructed. It can easily be used to represent a hyperlink. | |
| TextEdit – This is a control geared towards editing single-line text. It can be used for entering multi-line text through the configuration of the MultiLine and WordWrap properties. | |
| Button – A clickable button. Normally used to start some sort of action. | |
| OptionButton – generally used to provide choices | |
| CheckBox – This control is used to allow the user to change/display the current state of a boolean type variable. | |
| ListBox – Used to display a list of options for the user to choose from. | |
| ComboBox – Used to display alist of options for the user to choose from, which drops down right bellow a TextEdit.. | |
| DATE/TIME – Single line edit field (such as the TextEdit control) specialized for date information input. | |
| Container – As the name suggests, it is used to "contain" other controls. Different formatting attributes can be applied to group or highlight different elements in a Form. | |
| Image – This control displays an image on the Form. | |
| TabControl – With the TabControl the developer can visually group related controls in different tabs on the Form, providing better UI space management. | |
| Flash – The Flash control allows the developer to insert any Flash element into a Morfik Form. | |
| SubForm – With the use of the SubForm control you can embed Forms within Forms. This allows the creation of sophisticated applications through Form composition. | |
| File Uploader – This control allows the selection and uploading of files. | |
| Timer – The timer control continually generates an event on the browser side of the Form, allowing the developer to update or refresh some portion of the user interface. | |
| Rectangle – This control paints a rectangle on a form and is generally used as a layout/formatting aid. | |
| RSS – This option allows editting or creating a new RSS feed in the current project. |
In order to place any of these controls on a Form, all you have to do is click on the control button and then click on the Form itself. A control will be created on the Form, exactly on the spot you clicked. After the control appears you can drag it on the Form to adjust its position. Once the control is in the desired position you can set its properties in order to select the desired appearance and behavior.
In Figure 3 you can see a view of the Properties Window. It is the configuration of these properties that allow the appearance and behavior of the components you add to the Form.
Properties in the Properties Window are grouped together in Tabs, such as: Format, Data, Event, Other and All. Through the Event tab you get access to a complete list of events for the currently selected component, and can choose to write code to handle any particular one.
You can also use the Properties Window to set properties for the Form itself or any of its bands.
If you double click the empty field besides the name of an event in the Event tab of the Properties Window a code stub for that event will be created and the code editor will be displayed so that the event code can be inserted.
[edit] What is a SubForm?
One important question you might be asking yourself is: what exactly is a SubForm? I have talked a lot about SubForms, but I have not gone into great detail. It is time to remedy this.
SubForms are special controls which can host Forms inside them. When placed on a Form a SubForm is shown as a hashed area, as can be seen in Figure 4. Forms can be linked statically to SubForms, at design time by assigning a form name to the Form property, or at runtime through the use of the OpenForm function.
When statically bound to a Form, the SubForm control displays the Form name in parenthesis, besides its own name.
Why Build Forms with other Forms?
Ok, I have mentioned that you can build Forms from other Forms, as shown in Figure 1. But why would you want to do that? Can’t you simply create your Forms by placing controls directly on them? Of course you can. The idea of breaking things up into smaller parts is directly tied to the concept of modularity. In the WebOS universe, modularity is a key concept for it allows the exchange and reloading of parts of a Page/Form, without having to actually reload the whole Page. This makes for much more flexible and faster interfaces for web based applications,
When you have different elements which will occupy the same space within a Page/Form, at different moments, you will be looking at a case for modularization into SubForms. An example of this behavior can be seen in the following sample application that I have built for this purpose. In this application the Index Form has two SubForms which will work as navigation and information display areas during the application’s runtime. In the screenshot in Figure 4 you can see this application’s Index Form loaded in the Morfik IDE Form editor.
In the screenshot in Figure 4 the thin vertical SubForm on the left of the Form is the NavigationArea SubForm, while the larger one is the MainArea SubForm. These SubForms display the names of the forms that will be automatically loaded into them.
[edit] Forms Have Bands
In the Morfik WebOS Forms have bands, three in all, that are used to divide up the Form for implementing specific behavior. The three bands are: Header, Footer and Detail. In the example in Figure 4 you can see all the three bands in use. Notice that they can totally different formats, including background color.
Figures 5, 6 and 7 show the same page as Figure 4, with different forms displaying inside the MainArea SubForm control. Both the NavigationArea and the MainArea SubForm controls are inside the Detail band of the Index Form.
In Figure 5 you can see the HostingPlansForm being displayed inside the MainArea SubForm control in the Index Form. This Form has a Tabs control which shows a different tab for each of the hosting plans being advertised.
In Figure 6 you see the Index Form after the eMail button on the Navigation bar has been clicked. Now the eMailProductForm is being shown in the MainArea SubForm. Notice that the application (or site) is still in the same page and only the content of the area belonging to the MainArea SubForm control has changed.
In Figure 7 you will see the same Index Form showing the contents of the InfrastructureForm in the MainArea SubForm.
In order to get these results with the WebOS AppsBuilder all we have to do is create separate Forms and then piece them together either statically or dynamically. As this application starts up it will load two distinct Forms into the SubForm controls. One of these is the NavigationForm and the other is the HostingPlansForm. These Forms are loaded statically because I have associated their names to the Form property of their respective SubForm components.
Almost all the functionality in this application/site is automatically provided by the Morfik runtime library. The only code really written in this application at this time is in the code included in the OnClick events for each of the Button controls that are present in the NavigationForm. In each case it is a single line of code that specifies a new Form to be opened inside the MainArea SubForm control.
In Listing 1 you will find the code for the NavigationForm’s browser module. Most of the code is automatically generated by the AppsBuilder, requiring the developer to write, only the appropriate commands to switch the Form that is visible on the page in the browser.
Listing 1 – Browser side code (in Morfik Pascal) for the NavigationForm.
Unit NavigationForm;
Interface
Type
NavigationForm=Class(Form)
TextLabel1 : TextLabel;
HostingButton : Button;
eMailButton : Button;
InfrastructureButton : Button;
Procedure HostingButtonClick(Event: TDOMEvent); Message;
Procedure eMailButtonClick(Event: TDOMEvent); Message;
Procedure InfrastructureButtonClick(Event: TDOMEvent); Message;
Private
{ Private declarations }
Public
{ Public declarations }
End;
Implementation
Procedure NavigationForm.HostingButtonClick(Event: TDOMEvent);
Begin
OpenForm('HostingPlansForm', 'Index:MainArea', '');
End;
Procedure NavigationForm.eMailButtonClick(Event: TDOMEvent);
Begin
OpenForm('eMailProductForm', 'Index:MainArea', '');
End;
Procedure NavigationForm.InfrastructureButtonClick(Event: TDOMEvent);
Begin
OpenForm('InfrastructureForm', 'Index:MainArea', '');
End;
End.
The code in Listing 1 brings us into contact with function/procedure which will be widely used in everyday development of WebOS applications: OpenForm.
[edit] Using the OpenForm Function
The OpenForm function is used for opening forms inside the SubForm components or in place of the current Form. In the example we just saw in Figures 2 through 5 all Forms were displayed inside SubForms.
Observe an example of the usage of the OpenForm function taken from the above example:
OpenForm(’eMailProductForm’, ’Index:MainArea’, ’’);
In this example the eMailProductForm is being ordered to display inside the SubForm MainArea of the Index Form. The empty string in this call is a parameter which allows for the passing of parameters to the Form which will be opened.
It is important to have in mind that a call to the OpenForm function is totally asynchronous. As you will see in the Pre-fetching Forms topic, you can call the function several times in a row and you will start the download of several Forms at the same time.
OpenForm Syntax
OpenForm(form, context, parameters);
| |
| |__ blank - new browser window with new instance of script process (AJAX engine)
| |
| |__ same - same browser window with new instance of script process (AJAX engine)
| |
| |__ FormInstanceName:SubformName[(bandindex)]
| | | |__ if not specified it's set to zero
| | |
| | |
| | |__ special strings: '_' ('_' denotes the containing
| | subform)
| |
| |__ special strings :'self','parent','top'
|
|__ URL (this will result in a new instance of the script process to be instantiated)
|
|__ instancename:classname
|
|__ classname (in this case the instance name is implicitly set to be the same as the class name)
In the Rio de Janeiro Hosting example we have just seen, all uses of the OpenForm function followed a specific pattern: opening a form in the MainArea SubForm. In the line below, taken from the example, the first parameter is the class name for the Form you wish to open, and the second one is the name of the SubForm component where you wish it to appear.
OpenForm(’eMailProductForm’, ’Index:MainArea’, ’’);
In this example the second parameter is specifying that we wish to open the Form in the SubForm MainArea which is in the Form Index.
In this example you do not see any Form being opened in the NavigationArea SubForm. That is because we have statically bound the NavigationForm Form to this SubForm control in the Index Form. This is done, through the Properties Window, by setting the Form property of the SubForm control.
[edit] Pre-fetching Forms
The Morfik Framework and runtime library implement a great caching infrastructure for your application, which allows the developer to download pages before the user comes to need them. This allows for very rapid response times when accessing the application.
This feature allows the developers to create applications that are much more responsive to user interaction and input since they can predict which Forms the user might want to access and download them in the background.
How does this work? Let’s consider, as an example, an application with an initial Form/Page that presents the user with ten choices, of which you know that one of three options will be chosen by 97% of users to start with. In this case, as you finish downloading the main Form/Page you can start the download of those three most commonly used Forms in the background.
While the user is going through the task looking at the options and deciding where to go from there, the browser is fast at work preparing the way for a rapid response by downloading the most likely choices. If the user selects an option before the download process is complete, the application will just continue normally with the download process as it was doing before, only now it knows that it should display the requested option as soon as the download is complete.
Listing 2 – Browser side code (in Morfik Pascal) for pre-fetching 2 Forms before they are actually needed.
Procedure Index.WebFormShow(Var Show: Boolean);
Begin
OpenForm('Form1','Self:MainSubForm','');
If Not DonePrefetch Then
Begin
OpenForm('Form2','Self:MainSubForm','"OpenMode=DONOTACTIVATE"');
OpenForm('Form3','Self:MainSubForm','"OpenMode=DONOTACTIVATE"');
DonePrefetch := True;
End;
End;
[edit] Form Events
Both in Listing 1 and 2 you see Pascal code for handling Form events. This kind of code should be familiar to any developer who has worked with a modern development tool for the Windows Platform, but Morfik’s Forms are not for Windows but for the WebOS and therefore will have different kinds of events.
In order to handle events from the form, or any other control, you should double click the empty field besides the name of an event in the Event tab of the Properties Window. As a result a code stub for that event will be created and the code editor will be displayed so that the event code can be inserted.
Because of the uniqueness of the WebOS environment, it is important that the developer familiarize himself/herself with the Morfik Form Class’ events, in order to know how to take full advantage of its extensive, built-in, capabilities.
Form events can be grouped into six main categories; most events occur on the browser side. Those that relate to the server side are indicated. Here is a table list of all the form events:
Data Manipulation Events
- OnBeforeSubmit
- OnAfterSubmit
- OnBeforeDataChange
- OnAfterDataChange
Data Navigation Events
- OnBeforeDBNavigate
- OnAfterDBNavigate
Date Refresh Events
- OnBeforeRefresh
- OnAfterRefresh
Form Instantiation Events
- OnDestroy
- OnCreate
- OnBeforeExecute (Server Side)
- OnAfterExecute (Server Side)
- OnReady
- OnShow
User Interface Interaction Events
- OnBlur
- OnClick
- OnFocus
- OnKeyDown
- OnKeyUp
- OnMouseDown
- OnMouseMove
- OnMouseOut
- OnMouseOver
- OnResize
- OnScroll
Browser Management Events
- OnReadHistory
- OnWriteHistory
[edit] Data Manipulation Events
These events fire whenever there is a request made to change any data in the database connected to the document. The order of events is as follows:
1. Request to change data (which may be invoked via the user in the browser or programmatically)
2. OnBeforeSubmit
3. The request to alter data is submitted to the database
4. OnAfterSubmit
5. If successful, OnBeforeDataChange
6. Data is changed
7. If successful, OnAfterDataChange.
[edit] Data Navigation Events
These events fire whenever there is a request made to move from one record to another. The order of events is as follows:
1. Request to navigate between records (which may be invoked via the menu navigator or programmatically)
2. OnBeforeDBNavigate
3. DBNavigate procedure
4. If successful, OnAfterDBNavigate
[edit] Data Refresh Events
These events fire whenever there is a request made to refresh the document with the latest data from the database. The order of events is:
1. Request to refresh the data
2. OnBeforeRefresh
3. If the refresh is successful, OnAfterRefresh.
These events are different, and not to be confused with the Refresh or F5 option associated with the browser, for example Internet Explorer.
[edit] Form Instantiation Events
These events fire whenever there is a request made to create and display a new document. Note some of these events are server side as indicated. The order of events is:
1. Request to create and display a new form (which may be invoked via the browser or or programmatically)
2. OnDestroy (of the old form)
3. OnCreate and the document is created at the server end
4. OnBeforeExecute (performed at the server)
5. The document is sent from the server to the browser end
| 6. If successful, OnAfterExecute (performed at the server) |
7. OnReady when the document has been fully received by the browser
8. OnShow (fires when the form first becomes visible)
The OnReady event is associated with the instant that the browser has completed receiving and processing the form and any associated data. Just like the OpenForm function, it serves to enable the developer to easily and almost seamlessly, handle the asynchronous nature of the Web.
An example of when this might be useful is if the developer has created a master-detail relation using a form and subform. It is possible that he or she wishes to activate an event in the subform only when the master form is ready.
[edit] User Interface Interaction Events
These events fire independently in response to user actions.
[edit] OnBlur
The OnBlur event occurs when an visual control (control or document) loses focus either by the pointing device or by tabbing navigation.
[edit] OnClick
The OnClick event occurs when the mouse button, or any other pointing device button, is single-clicked over the control or document.
On a PC-based mouse it specifically corresponds to a left-mouse click
[edit] OnFocus
The onFocus event occurs when a visual control (control or document) receives focus either by the pointing device or by tabbing navigation.
[edit] OnKeyDown
The OnKeyDown event occurs when a key is pressed down over a visual control (a control or document)
[edit] OnKeyUp
The OnKeyUp event occurs when a key is released over a visual control (a control or document)
[edit] OnMouseDown
The OnMouseDown event occurs when the mouse button, or any other pointing device button, is pressed while it is over a visual control (a control or document). On a PC-based mouse, it specifically relates to the left-hand mouse button being depressed.
[edit] OnMouseMove
The OnMouseMove event occurs when the mouse, or any other pointing device button, is moved while it is over a visual control (a control or document).
[edit] OnMouseOut
The OnMouseOut event occurs when the mouse pointer, or any other pointing device button, is moved out (off) of the region defined by a visual control (a control or document).
[edit] OnMouseOver
The OnMouseOver event occurs when the mouse pointer or any other pointing device is over (within the region defined by it) a visual control (a control or document).
[edit] OnMouseUp
The OnMouseUp event occurs when the mouse button, or any other pointing device button, is released over the control or document. On a PC-based mouse, it specifically relates to when the left-hand mouse button being released.
[edit] OnResize
This event is associated with every time the browser window is resized.
[edit] OnScroll
This event is associated with every time the browser scroll bars are being used
[edit] Browser Management Events
[edit] OnReadHistory
The OnReadHistory event allows you to directly interfere with in processing a URI to restore the form’s state. If you have taken some information out of the form’s written history, in the OnWriteHistory event, you can restore it in the OnReadHistory event.
[edit] OnWriteHistory
This event gives the developer an opportunity to the URI for the Form. It can be used to filter out sensitive information, for example.
[edit] Form Band Events
As we have seen, earlier in this chapter, Forms have Bands. Bands are container objects that are present in every Form. As full blown objects, themselves, the Bands have their own events which can be used along with the Form’s events in order to best handle user interaction with your application.
[edit] Browser Side Events
[edit] OnAfterGrowOrShrink
This event is triggered right after a Band object is resized. This event can be used to reposition controls on a band, if necessary.
[edit] OnBeforeGrowOrShrink
This event is triggered immediately before a Band object is resized. This event can be used to reposition controls on a band, if necessary.
[edit] Server Side Events
[edit] OnAfterPrint
The OnAfterPrint event is called right after a band gets "printed" out to the data stream for the client. It can be used for setting control variables.
[edit] OnBeforePrint
This event is triggered immediately before a band is "printed" out to the data stream for the client. You can use this event to change the appearance of objects in the Band for each detail item in a continuous Form.
[edit] OnPrintStyle
The OnPrintStyle event gives the developer an opportunity to override or extend the automatic HTML styles generated for the controls on the form.
[edit] Data Bound Forms
In this chapter we have looked at how to create Forms, using controls and other Forms in order to setup the user interface of an application. Since we did this with a simple, website-like application we had no need for databases, but in the real world most modern applications need to rely, heavily, on databases. The Morfik has taken this need into account right from the start. Database support is not only available, but has been built into the very fabric of the Morfik Framework instead of being added on later as an afterthought.
Now we are going to go back to the Contacts example we started with back in Chapter 2. We are going to elaborate on that example by adding a pair of Forms, one for browsing the contacts and one for editing and inserting a contact. Both of these Forms will be used inside a SubForm control on the project’s Index Form.
You can see what the Index Form will look like, in design mode, in the screenshot in Figure 8. Notice that the Index Form has only three controls in its Detail Band: two Buttons and a SubForm. In both the header and footer bands a single TextLabel control is used for displaying a title and a copyright message.
At runtime this application will present the interface shown in Figure 9 at startup. Notice that what you see in Figure 9 is exactly what is shown in Figure 8, now with the ContactsList Form being exhibited in the SubForm control of Index Form.
On this Form you can see information that is being brought in from the tblContacts table we designed in Chapter 3. Looking at Figure 9 you will see that there is a series of small buttons right under the "gray" area where the data is shown. That is a NavigationBar control and it can help you to navigate elegantly through a dataset.
This brings us back to the topic at hand: Data Bound Forms. Unlike other tools that have data bound controls, the WebOS AppsBuilder has data bound Forms. What this means is that the entire Form is "data-aware" and offers a series of features to help you in building your database centric applications. The NavigationBar control, for example, is not a standalone control, but a property of either the Header or Footer bands of a Form.
[edit] What Makes a Form Data Bound?
What is the difference between a Data Bound Form and any other Form? Well, just the value of the dataset property. Every Form has a dataset property and it is whether or not this property is set that defines if a specific Form is data bound or not.
So, a Form with the dataset property set to the name of one of the project’s tables or queries becomes a data bound Form. It is as simple as that.
So in our contacts example, the Index Form we see in Figure 8 is not a data bound Form. It is the ContactsList Form which appears inside the ContactsArea SubForm control that is a data bound Form.
[edit] Two Kinds of Data Bound Forms
There are two different kinds of data bound Forms: Continuous and Single.
[edit] Continuous Forms
The ContactsList Form, shown in Figure 9, is a continuous data bound Form. This means that it will continuously display data rows until it reaches a limit defined by the developer, then it will paginate. This limit is set by the developer through the PageSize property, which defaults to a value of 10.
Figure 9 – The Contacts application at run time. The Index Form is showing with
the ContactsList Form in display in the ContactsArea SubForm.
When you design a continuous form, you only design how one record is going to be displayed, within the details band, and that gets replicated for each record that is actually shown. The developer controls how many records will actually get shown through the use of the PageSize property.
At runtime, you might wish to perform an action on one specific control or set of controls, like changing their visibility or color. Since you only design one set of controls, but will have many occurrences of them, in practice, you need to select which of the sets you are referring to. This can be done through the use of the BandIndex property of the control you wish access, as shown in the following example:
Procedure form1.TextLabel1Click(Event: TDOMEvent);
Begin
TextLabel5.BandIndex := GetEventSource(Event).BandIndex;
OpenForm('Form2','Form1:SubForm1',
'"ParamId='+TextLabel5.Caption+'"');
End;
In this example, we presume that we want to take action based on the click of a control. The control which was clicked is obtained by the call to GetEvenSource(Event) function call and its BandIndex property is used to set the BandIndex property of the control which we want to manipulate. In this case the TextLabel5 control whose caption is used a parameter for opening a new form.
In case you wish to manipulate more than one control of a specific band you can set the BandIndex of all the controls in one call to the SwitchBandIndex function. This function takes a TDOMEvent object as its parameter and can be easily used by just passing to it the Event object that any event handler method receives as a parameter.
[edit] Single Forms
The second kind of Form is the Single Form and as its name might have given away, it handles data from a single table row. The EditContact Form in the Contacts example, which is displayed at design time in Figure 10, is a Single type, data bound Form.
You saw this Form being created through the "Create Form Wizard" in Chapter 3. It is essentially the same Form, but since it handles only a single row of data at a time, I have substituted the NavigationBar in the Footer band with a set of button controls which are a bit more appropriate to our needs in this case. The screenshot in Figure 10 shows part of the Detail band as well as the Footer band of the EditContact Form with this set of buttons.
In Listing 3 you will find the Browser side code for the EditContact Form. This code shows how to enable and disable controls the current Form and on another Form.
Listing 3 – Browser side code (in Morfik Basic) for EditContact Form.
Imports Index
Namespace EditContact
Public Class EditContact
Inherits Form
Published Label_FirstName As TextLabel
Published Control_FirstName As TextEdit
Published Label_LastName As TextLabel
Published Control_LastName As TextEdit
Published Label_WorkEmail As TextLabel
Published Control_WorkEmail As TextEdit
Published Label_MobilePhone As TextLabel
Published Control_MobilePhone As TextEdit
Published Label_HomePhone As TextLabel
Published Control_HomePhone As TextEdit
Published Label_WorkPhone As TextLabel
Published Control_WorkPhone As TextEdit
Published Label_WorkStreetAddress As TextLabel
Published Control_WorkStreetAddress As TextEdit
Published Label_HomeStreetAddress As TextLabel
Published Control_HomeStreetAddress As TextEdit
Published Label_HomeEmail As TextLabel
Published Control_HomeEmail As TextEdit
Published Label_Company As TextLabel
Published Control_Company As TextEdit
Published Label_ContactID As TextLabel
Published Control_ContactID As TextLabel
Published Label_DateofBirth As TextLabel
Published Control_DateofBirth As DateTimeEdit
Published btnCancel As Button
Published btnOk As Button
Published btnDelete As Button
Published btnPrint As Button
Sub SetEnabled(Enabled As Boolean)
btnOk.Enabled = Enabled
btnCancel.Enabled = Enabled
End Sub
Sub ReturnToList
' Return to "ContactsList" Form
Index2(xApp.Forms("Index")).btnNew.Enabled = True
Index2(xApp.Forms("Index")).btnPrint.Enabled = True
OpenForm("ContactList","Index:ContactsArea", "")
End Sub
Published Message Sub btnCancelClick(Event As TDOMEvent)
SetEnabled(False)
gRefreshContactList = False
If gNewContact Then
DeleteRecord(Nothing)
gNewContact = false
SetEnabled(True)
Else
SetEnabled(True)
End If
ReturnToList 'Return to the List view
End Sub
Published Message Sub btnOkClick(Event As TDOMEvent)
SetEnabled(False)
If (Control_FirstName.Text = "") or (Control_LastName.Text = "") Then
ShowMessage("Empty record.")
SetEnabled(True)
Else
gRefreshContactList = False
SubmitPage(Event)
End If
End Sub
Published Message Sub btnDeleteClick(Event As TDOMEvent)
gRefreshContactList = False
If ConfirmAction("Are you sure you want to delete this record?") Then
SetEnabled(False)
DeleteRecord(Event)
SubmitPage(Event)
End If
End Sub
Published Message Sub btnPrintClick(Event As TDOMEvent)
OpenReport("RptSingleContact", """ContactIDParam=" & gContactID &_
"""")
End Sub
Published Message Sub WebFormShow(ByRef Show As Boolean)
Index(xApp.Forms("Index")).btnNew.Enabled = False
Index(xApp.Forms("Index")).btnPrint.Enabled = False
If Show Then
If gNewContact Then
gContactID = ""
btnDelete.Enabled = False
NewRecord(Nothing)
Else
btnDelete.Enabled = True
End If
End If
End Sub
Published Message Sub WebFormCreate(Sender As TObject)
' Selecting single contact
If gContactID <> "" Then
SQLFilter = """ContactID"" = " & gContactID
End If
End Sub
Published Message Sub WebFormAfterSubmit(Failed As Boolean)
' Getting current ContactID
SetEnabled(True)
If not Failed then
gNewContact = False
gRefreshContactList = True
ReturnToList
End If
End Sub
End Class
End Namespace
We will look into the OpenReport function you see in this example, in more detail in the next Chapter, Working with Reports.
[edit] Positioning the Controls on a Form
The WebOS AppsBuilder IDE’s Form Designer makes designing interfaces quite easy. The designer includes automatic alignment features which make aligning controls to one another and equally spacing them a trivial matter.
Whenever you drag a control around the Form designer, thin blue lines will appear indicating that you are in position for alignment with another control in form. Many lines can actually be shown at the same time as the Form Designer tries to ensure that your controls are all properly aligned.
This behavior can be deactivated as you will see in the next topic.
[edit] Configuring the Form Designer
The Morfik WebOS AppsBuilder offers you a large set of configuration options. These include several options to customize the behavior of the Forms and Report Designer. You can see the General tab of the Options dialog in Figure 12. The options in the column on the left are related to the Forms and Reports designers.
I have found that the automatic alignment of controls is a great enhancer of developer productivity as it allows to you to get great looking forms easily. If, for some reason, this feature is interfering with how you want to position your controls you can disable it by switching from Snap to Smart Grid to Snap to Visible Grid.
When using Snap to Visible Grid you might want to fiddle around with values to find the setting you prefer for the X and Y grid step options. These options control how controls move and align on the Form.
[edit] Wrapping it up
The Morfik WebOS AppsBuilder IDE offers a lot of great features for the creation of Forms and through them the interface for your application. As we have seen in this chapter, you can create Forms that work automatically with datasets and Forms that care nothing for datasets.
It is important to keep in mind that we have just glanced at the possibilities for your applications, so far. We will see more examples and how to do more interesting stuff in the chapters to come.












