Difference between revisions of "Working with Forms in Lianja"

From Lianjapedia
Jump to: navigation, search
(Created page with "'' Under Construction'' Lianja provides the ability to visually create forms that will run on Desktop, Web and Mobile devices. If you come from a VFP background this is the...")
 
Line 1: Line 1:
 
'' Under Construction''
 
'' Under Construction''
 
+
==Overview==
 
Lianja provides the ability to visually create forms that will run on Desktop, Web and Mobile devices.  
 
Lianja provides the ability to visually create forms that will run on Desktop, Web and Mobile devices.  
  
Line 8: Line 8:
  
 
You can visually build forms that use any of the following scripting languages as the Lianja UI framework is scripting language independent across Desktop, Web and Mobile Apps.
 
You can visually build forms that use any of the following scripting languages as the Lianja UI framework is scripting language independent across Desktop, Web and Mobile Apps.
 
 
 
* LianjaScript/VFP
 
* LianjaScript/VFP
 
* Python
 
* Python
 
* JavaScript
 
* JavaScript
 
* Typescript
 
* Typescript
 
  
 
This article builds a form that uses Python as its scripting language.
 
This article builds a form that uses Python as its scripting language.
Line 23: Line 20:
  
 
Forms can optionally contain (attribute settings in the TabView):
 
Forms can optionally contain (attribute settings in the TabView):
 
 
 
* A menubar
 
* A menubar
 
* A toolbar
 
* A toolbar
Line 30: Line 25:
 
* A statusbar
 
* A statusbar
  
 
+
==Creating a new form==
Creating a new form
+
 
+
 
You can create a new form from the "Home" workspace::
 
You can create a new form from the "Home" workspace::
  
Line 61: Line 54:
 
[ATTACH=CONFIG]2830[/ATTACH]
 
[ATTACH=CONFIG]2830[/ATTACH]
  
Modifying an existing form
+
==Modifying an existing form==
 
+
 
You can modify an existing form from the "Component/Form Manager":
 
You can modify an existing form from the "Component/Form Manager":
  
Line 73: Line 65:
 
</code>
 
</code>
  
The lifecycle of a form
+
==The lifecycle of a form==
 
+
 
During development you customize the forms and activate them by clicking the "Desktop App View" icon:
 
During development you customize the forms and activate them by clicking the "Desktop App View" icon:
  
Line 110: Line 101:
 
</code>
 
</code>
  
Creating the menubar dynamically
+
==Creating the menubar dynamically==
 
+
 
The quickest way to layout the Menubar is to assign a layout string to the menubarlayout property like this:
 
The quickest way to layout the Menubar is to assign a layout string to the menubarlayout property like this:
  
Line 134: Line 124:
 
</code>
 
</code>
  
Creating the Toolbar dynamically
+
==Creating the Toolbar dynamically==
 
+
 
The quickest way to layout the Toolbar is to assign a layout string to the toolbarlayout property like this:
 
The quickest way to layout the Toolbar is to assign a layout string to the toolbarlayout property like this:
  
Line 150: Line 139:
 
</code>
 
</code>
  
Hiding and showing the Actionbar dynamically
+
==Hiding and showing the Actionbar dynamically==
 
+
 
You can hide and show the actionbar dynamically using:
 
You can hide and show the actionbar dynamically using:
  
Line 162: Line 150:
 
This is typically done in the toolbarclick delegate as you hide and show Tabs of the TabView container in the Form.
 
This is typically done in the toolbarclick delegate as you hide and show Tabs of the TabView container in the Form.
  
Referencing UI controls dynamically
+
==Referencing UI controls dynamically==
 
+
 
You can dynamically reference UI controls in the Form like this:
 
You can dynamically reference UI controls in the Form like this:
  
Line 184: Line 171:
 
When referencing objects by name you should use the fully qualified name e.g. "page1.section1.field1". All objects in the form and its child containers will be introspected and an object reference to the UI control will be returned.
 
When referencing objects by name you should use the fully qualified name e.g. "page1.section1.field1". All objects in the form and its child containers will be introspected and an object reference to the UI control will be returned.
  
Dynamically setting attributes
+
==Dynamically setting attributes==
 
+
 
You can dynamically reference the attributes of a UI element using:
 
You can dynamically reference the attributes of a UI element using:
  
Line 196: Line 182:
 
Each time a "Form" is activated the activated delegate is called and each time it is deactivated the deactive delegate is called.
 
Each time a "Form" is activated the activated delegate is called and each time it is deactivated the deactive delegate is called.
  
Dynamically binding delegates
+
==Dynamically binding delegates==
 
+
 
Delegates are normally specified in the Assistant (or the Attributes) for a UI element.
 
Delegates are normally specified in the Assistant (or the Attributes) for a UI element.
  
Line 233: Line 218:
 
</code>[SIZE=1]
 
</code>[SIZE=1]
  
Understanding events and delegates
+
==Understanding events and delegates==
 
+
 
Custom Forms are built in the Canvas Designer. You drag and drop UI controls onto the canvas. Clicking on the border of a UI control (a formitem in Lianja terminology) selects the control and its caption in the "Assistant" and the "Attributes". You can then customize the appearance and the behavior of the UI control.
 
Custom Forms are built in the Canvas Designer. You drag and drop UI controls onto the canvas. Clicking on the border of a UI control (a formitem in Lianja terminology) selects the control and its caption in the "Assistant" and the "Attributes". You can then customize the appearance and the behavior of the UI control.
  
Line 261: Line 245:
 
thisform.controls("page1.section1.formitem1")
 
thisform.controls("page1.section1.formitem1")
  
Handling click events from the menubar
+
==Handling click events from the menubar==
 
+
 
You normally specify a menubarclick delegate for the form in the TabView section attributes.
 
You normally specify a menubarclick delegate for the form in the TabView section attributes.
  
Line 317: Line 300:
 
</code>
 
</code>
  
Handling click events from the toolbar
+
==Handling click events from the toolbar==
 
+
 
You normally specify a toolbarclick delegate for the form in the TabView section attributes.
 
You normally specify a toolbarclick delegate for the form in the TabView section attributes.
  
Line 359: Line 341:
 
</code>
 
</code>
  
Handling click events from the actionbar
+
==Handling click events from the actionbar==
 
+
 
You can specify a actionbarclick delegate for the form in the TabView section attributes. If the TabView has a recordsource data navigation is automatically handled for the form without any coding requirement. See Data Binding below.
 
You can specify a actionbarclick delegate for the form in the TabView section attributes. If the TabView has a recordsource data navigation is automatically handled for the form without any coding requirement. See Data Binding below.
  
Line 434: Line 415:
 
thisform.hideMessage()</code>
 
thisform.hideMessage()</code>
  
Data binding  
+
==Data binding==
 
+
 
Specifying a "Data source" in the formitem attributes in the Canvas Designer binds a control to a table.column.
 
Specifying a "Data source" in the formitem attributes in the Canvas Designer binds a control to a table.column.
  
Line 458: Line 438:
 
refresh()
 
refresh()
  
Responsive UI using anchors  
+
==Responsive UI using anchors==
 
+
 
The UI elements (formitems) that you add to Canvases in your form are not responsive to changes in geometry of screen sizes (e.g. phones, tablets, maximising the form window etc). To make your forms responsive you can use anchors which you will find in the Assistant.
 
The UI elements (formitems) that you add to Canvases in your form are not responsive to changes in geometry of screen sizes (e.g. phones, tablets, maximising the form window etc). To make your forms responsive you can use anchors which you will find in the Assistant.
  
Line 467: Line 446:
  
  
Dynamically referencing UI controls in delegates
+
==Dynamically referencing UI controls in delegates==
 
+
 
The best way to reference UI controls on forms is to use the fully qualified name with Lianja.get(). This works in LianjaScript, Python and JavaScript.
 
The best way to reference UI controls on forms is to use the fully qualified name with Lianja.get(). This works in LianjaScript, Python and JavaScript.
  
Line 476: Line 454:
  
  
Building a standalone form executable  
+
==Building a standalone form executable==
 
+
 
You can build a form as a standalone executable.
 
You can build a form as a standalone executable.
  
 
See [[Standalone Executables on Windows]] for details.
 
See [[Standalone Executables on Windows]] for details.
  
Using forms in Web and Mobile Apps
+
==Using forms in Web and Mobile Apps==
 
+
 
Forms and Components are generated when you save an App. The Form is also saved as a component that can be used in Web Apps with Lianja.showDialog(), Lianja.showDialogPanel() and Lianja.showDialogForm(). To use this in Web Apps they should be developed in JavaScript or Python.  
 
Forms and Components are generated when you save an App. The Form is also saved as a component that can be used in Web Apps with Lianja.showDialog(), Lianja.showDialogPanel() and Lianja.showDialogForm(). To use this in Web Apps they should be developed in JavaScript or Python.  
  
 
Forms are based in TabView sections inside an App with the same name as the form. The app if javascript or Python is the selected scripting language will also run in the Web or can be generated as an Electron App or (coming soon) a React Native mobile App.
 
Forms are based in TabView sections inside an App with the same name as the form. The app if javascript or Python is the selected scripting language will also run in the Web or can be generated as an Electron App or (coming soon) a React Native mobile App.

Revision as of 06:18, 12 April 2024

Under Construction

Overview

Lianja provides the ability to visually create forms that will run on Desktop, Web and Mobile devices.

If you come from a VFP background this is the equivalent of the VFP form designer.

[ATTACH=CONFIG]2832[/ATTACH]

You can visually build forms that use any of the following scripting languages as the Lianja UI framework is scripting language independent across Desktop, Web and Mobile Apps.

  • LianjaScript/VFP
  • Python
  • JavaScript
  • Typescript

This article builds a form that uses Python as its scripting language.

Forms are based on a tabview section which contains canvas, grid or webview based sections in its tabs.

Forms can be displayed as a modal or non modal dialog.

Forms can optionally contain (attribute settings in the TabView):

  • A menubar
  • A toolbar
  • An actionbar
  • A statusbar

Creating a new form

You can create a new form from the "Home" workspace::

[ATTACH=CONFIG]2825[/ATTACH]

or alternatively from the "Develop menu":

[ATTACH=CONFIG]2826[/ATTACH]

or from the "Command window" or the "Command" workspace by typing using the CLI:

[CODE] create form [<form_name>] </code>

The form will be created in its own App as a TabView section with one Canvas section Tab. You can then add other Canvas, Grid, or Webview based sections to it.

Once the new form is created you should specify the scripting language that you want to use for the delegates in the form:

[ATTACH=CONFIG]2831[/ATTACH]

You can then add new "Tabs" to the form by clicking on the "+" icon in the TabView TabBar.

[ATTACH=CONFIG]2829[/ATTACH]

Note that you can "Hide TabBar" in the TabView attributes and programatically show Tab Panels programatically (typically from the menubar or the toolbar) e.g.

[ATTACH=CONFIG]2830[/ATTACH]

Modifying an existing form

You can modify an existing form from the "Component/Form Manager":

[ATTACH=CONFIG]2827[/ATTACH]

or from the "Command window" or the "Command" workspace by typing:

[CODE] modify form [<form_name>] </code>

The lifecycle of a form

During development you customize the forms and activate them by clicking the "Desktop App View" icon:

[ATTACH=CONFIG]2828[/ATTACH]

In code, Forms are activated (made visible) using Lianja.showForm():

[CODE] Lianja.showForm("Window title", "component:/mycomponents/form_name")

or

Lianja.showForm("Window title", "app:/form_name/form_name")

or

Lianja.showForm("Window title", "form_name") which activates "app:/form_name/form_name"

or

Lianja.showForm("form_name") which activates "app:/form_name/form_name" with the default window title

</code>

When a form is activated the initform delegate is called. This is where you can open a database and its tables and dynamically create the menubar and the toolbar.

In this delegate thisform references the form itself.

You can reference the menubar, toolbar and actionbar like this:

[CODE] thisform.menubar thisform.toolbar thisform.actionbar </code>

Creating the menubar dynamically

The quickest way to layout the Menubar is to assign a layout string to the menubarlayout property like this:

[CODE]thisform.menubarlayout = "File(Open...,Save),Reports(Customers,Orders,Order Details)"</code>

Note that a menuitem may also have an icon associated with it. e.g.

lib:/images/mycustomersicon.png@Customers

When you click a menuitem the menubarclick delegate of the form is called with the fullpath of the menuitem clicked. The fullpath is a | separated list.

e.g

"Reports|Customers|Save as XML..."

You can hide and show the menubar dynamically using:

[CODE] thisform.menubar = 1 or thisform.menubar = 0 </code>

Creating the Toolbar dynamically

The quickest way to layout the Toolbar is to assign a layout string to the toolbarlayout property like this:

[CODE]thisform.toolbarlayout = "lib:/images/mycustomobersicon.png@Customers,lib:/images/myordersicon.png@Orders"</code>

When an icon is clicked the "Tooltip" e.g. "Customers" is passed as an argument to the toolbarclick delegate.

You can hide and show the toolbar dynamically using:

[CODE] thisform.toolbar = 1 or thisform.toolbar = 0 </code>

Hiding and showing the Actionbar dynamically

You can hide and show the actionbar dynamically using:

[CODE] thisform.actionbar = 1 or thisform.actionbar = 0 </code>

This is typically done in the toolbarclick delegate as you hide and show Tabs of the TabView container in the Form.

Referencing UI controls dynamically

You can dynamically reference UI controls in the Form like this:

[CODE]otabview = thisform.controls( 1 )</code>

You dynamically reference UI elements in the Form by by objectname using:

[CODE] el = thisform.controls ( cname )

// or

el = thisform.getElementByID ( cname )

// or

el = thisform.get ( cname ) </code>

When referencing objects by name you should use the fully qualified name e.g. "page1.section1.field1". All objects in the form and its child containers will be introspected and an object reference to the UI control will be returned.

Dynamically setting attributes

You can dynamically reference the attributes of a UI element using:

[CODE]el.attribute = expression </code>

e.g

[CODE]el.text = “hello world”</code>

Each time a "Form" is activated the activated delegate is called and each time it is deactivated the deactive delegate is called.

Dynamically binding delegates

Delegates are normally specified in the Assistant (or the Attributes) for a UI element.

If required you can dynamically bind delegates like this:

Python:

[CODE] def myafterclose(self):

   # place your code here
   pass

thisform.afterclose = myafterclose </code>

LianjaScript:

[CODE] proc myafterclose()

   // place your code here

endproc

thisform.afterclose = myafterclose </code>

JavaScript:

[CODE] function myafterclose() {

   // place your code here

};

thisform.afterclose = myafterclose; </code>[SIZE=1]

Understanding events and delegates

Custom Forms are built in the Canvas Designer. You drag and drop UI controls onto the canvas. Clicking on the border of a UI control (a formitem in Lianja terminology) selects the control and its caption in the "Assistant" and the "Attributes". You can then customize the appearance and the behavior of the UI control.

A UI control handles events e.g. Click of a CommandButton, InteractiveChange of a ComboBox or Change of text in a TextBox using "Delegates". Delegates are scripting language independent event handlers.

You edit delegates by selecting them in the "Delegates" combobox of the "Assistant" or in the "Attributes".

When an event occurs e.g. Change the text in a TextBox the event delegate is executed. In the event delegate you can reference the UI control (the formitem) that the event occurred for using:

Python:

In Python use self.

LianjaScript:

In LianjaScript/VFP use this.

JavaScript:

In JavaScript use this.

You can get an object reference to other UI controls on the form using:

thisform.get("page1.section1.formitem1") or thisform.controls("page1.section1.formitem1")

Handling click events from the menubar

You normally specify a menubarclick delegate for the form in the TabView section attributes.

When you click a menubar item the menubarclick delegate of the form is called with the fullpath of the menuitem clicked. The fullpath is a | separated list.

e.g

"Reports|Customers|Save as XML..."

You can edit the menubarclick delegate in the Canvas Designer attributes.

Python:

[CODE] def mymenubarclick(action):

   action = action.lower()
   if (action == "file|open..."):
       # handle action    
       pass

thisform.menubarclick = mymenubarclick </code>

LianjaScript:

[CODE] proc mymenubarclick(action)

   action = lower(action)
   if action = "something"
       // handle action  
   elseif action = "something else" 
       // handle action
   endif

endproc thisform.menubarclick = mymenubarclick </code>

JavaScript:

[CODE] function mymenubarclick(action) {

   action = lower(action);
   if action == "something"
   {
       // handle action  
   }
   else if action == "something else" 
   {
       // handle action
   }

} thisform.menubarclick = mymenubarclick; </code>

Handling click events from the toolbar

You normally specify a toolbarclick delegate for the form in the TabView section attributes.

When you click an toolbar button the toolbarclick delegate of the form is called with the text of the tool button tooltip that was clicked. In this delegate you typically show Tab panels containing the UI elements of your form..

You can edit the toolbarclick delegate in the Canvas Designer attributes.

Python:

[CODE] def mytoolbarclick(action):

   action = action.lower()
   if (action == "something"):
       # handle action    
   elif (action == "something else"):
       # handle action      
  

thisform.toolbarclick = mytoolbarclick </code>

LianjaScript:

[CODE] proc mytoolbarclick(action)

   // place your code here

endproc

thisform.toolbarclick = mytoolbarclick </code>

JavaScript:

[CODE] function mytoolbarclick(action) {

   // place your code here

};

thisform.toolbarclick = mytoolbarclick; </code>

Handling click events from the actionbar

You can specify a actionbarclick delegate for the form in the TabView section attributes. If the TabView has a recordsource data navigation is automatically handled for the form without any coding requirement. See Data Binding below.

When you click an actionbar button the actionbarclick delegate of the form is called with the text of the tool button tooltip that was clicked. In this delegate you can navigate, add, update and delete records.

You can edit the actionbarclick delegate in the Canvas Designer attributes.

Python:

[CODE] def myactionbarclick(action):

   action = action.lower()
   if (action == "add"):
       # handle Add action    
   elif (action == "delete"):
       # handle Delete action    
   elif (action == "refresh"):
       # handle Refresh action    
   elif (action == "first"):
       # handle First action
   elif (action == "previous"):
       # handle Prev action    
   elif (action == "next"):
       # handle Next action 
   elif (action == "last"):
       # handle Last action    
   elif (action == "edit"):
       # handle Edit action    
   elif (action == "save"):
       # handle Save action    
   elif (action == "cancel"):
       # handle Cancel action    
  

thisform.actionbarclick = myactionbarclick </code>

LianjaScript:

[CODE] proc myactionbarclick(action)

   // place your code here

endproc

thisform.actionbarclick = myactionbarclick </code>

JavaScript:

[CODE] function myactionbarclick(action) {

   // place your code here

};

thisform.actionbarclick = myactionbarclick; </code>

You can update the recno and the reccount in the actionbar like like:

[CODE]thisform.actionbar.recno = nExpr thisform.actionbar.reccount = nExpr</code>

You can update the statusbar like this:

[CODE]thisform.message = "Hello world"</code>

You can provide user feedback like this:

[CODE]thisform.showSuccessMessage("Operation succeeded") thisform.showErrorMessage("Operation failed") thisform.showWarningMessage("Operation succeeded with warnings") thisform.showInfoMessage("Operation is being performed. Please wait.") thisform.hideMessage()</code>

Data binding

Specifying a "Data source" in the formitem attributes in the Canvas Designer binds a control to a table.column.

In the initform delegate for the form you can assign a database!table or a SQL statement to the recordsource property of the TabView.

As you navigate records in the form by clicking the icons in the actionbar, the bound controls will automatically be refreshed on the form.

All CRUD (Create, Read, Update, Delete) operations will be handled automatically for you.

Alternatively, you can call the recordsource data navigation methods manually on the container if you have your own navigation controls on the form as custom commandbuttons.

The relevant methods available on a container are:

add() delete() first() next() previous() last() save() cancel() refresh()

Responsive UI using anchors

The UI elements (formitems) that you add to Canvases in your form are not responsive to changes in geometry of screen sizes (e.g. phones, tablets, maximising the form window etc). To make your forms responsive you can use anchors which you will find in the Assistant.

You can check the top, botton, left and right anchors to make the UI control adjust its geometry and respond to changes in display geometry.

[ATTACH=CONFIG]2835[/ATTACH]


Dynamically referencing UI controls in delegates

The best way to reference UI controls on forms is to use the fully qualified name with Lianja.get(). This works in LianjaScript, Python and JavaScript.

e.g.

Lianja.get("page1.section1.field1").text = "Hello world"


Building a standalone form executable

You can build a form as a standalone executable.

See Standalone Executables on Windows for details.

Using forms in Web and Mobile Apps

Forms and Components are generated when you save an App. The Form is also saved as a component that can be used in Web Apps with Lianja.showDialog(), Lianja.showDialogPanel() and Lianja.showDialogForm(). To use this in Web Apps they should be developed in JavaScript or Python.

Forms are based in TabView sections inside an App with the same name as the form. The app if javascript or Python is the selected scripting language will also run in the Web or can be generated as an Electron App or (coming soon) a React Native mobile App.