I am trying to upload an image file (http post “multipart/form-data”) to a “storeimage.rsp” to process. However, it returns the following error:

Error message:
ARRAY reference is out of bounds

Error line:

How can i read and store the file with the _files[]?


The array starts from 1 not 0.

There is an example included in the distribution in C:\lianja\cloudserver\tenants\public\wwwroot\examp les\example_upload.html which calls C:\lianja\cloudserver\tenants\public\wwwroot\examp les\example_upload.rsp.

You can run it as

Note that example_upload.html references ‘’ – if you have not enabled port 80 on the Lianja Server (or set up the ISAPI IIS extension), change this to ‘’.

AMEMBERS()  works with object() also:

lo = object()
lo.hank = "here"
lo.yvonne = "over there"
lo.barry = "way over there"
? amembers(awhowhere,lo)
? lo
? awhowhere


Object (refcnt=1)
[hank] => here
[yvonne] => over there
[barry] => way over there
Array (refcnt=1)
[1] = HANK
[2] = YVONNE
[3] = BARRY

It also works with the SCATTER MEMO NAME <name> object.

AMEMBERS() does not work with the UI framework classes.


I’ve a form, with a new container, with a button.

On the “cick” event, I call a procedure “sp_close_handler”

oContBottom.addObject("sp_close", "commandbutton")
sp_close.move(1, 1, 60, 20)
sp_close.text = "Close" = sp_close_handler
proc sp_close_handler()

can I send a parameter on the call?
for example:

oContBottom.addObject("sp_close", "commandbutton")
sp_close.move(1, 1, 60, 20)
sp_close.text = "Close" = sp_close_handler with "aaa"


proc sp_close_handler(m_text)

naturally, this code not work.. 🙂


use use a public variable to pass the text.

If the event to which you you assign sp_close_handler has one or more params, they should be passed to the routine you assign.

However, the click() event does not have params.

You could use a public var for this. In Lianja, where we aren’t creating large monolithic applications, the usual best practice of “don’t use public vars” doesn’t really apply. When I have a lot of them, I do place them on an object() when in VFP, or in a dynamic JavaScript array


goMyVars = object()
goMyVars.Phabio = "lasagna lover"


goMyVars = {};
goMyVars.Phabio = "lasagna lover";





I’m tryng to use the classic “Browse” command
I I wryte:

open database southwind
use example
browse field title:c="MR.Mrs,Miss,Mr",;

proc validate()


in the validate, how can I test the value just insert in the “last_name” field?

if I test “last_value” I see the previous value..


Pass “{}” to the validation proc.



I’m trying to do validation for a Textbox field on a canvas.

Suppose I set Validation to !empty(“{}”) and Error to “Field must not be empty”.

1. When I press the tab key, the error message appears in the yellow error dialog, but the cursor moves to the next field. Is this expected behavior? I would expect the focus to be kept on the offending field.

2. If the field is empty to begin with, tabbing through the field does not generate the error dialog. Is this expected behavior? The field fails the validation, so I would expect the error dialog to appear and focus to remain on the offending field.

3. What is the recommended approach if the validation for a field has multiple components, requiring varying error messages for the field?

4. Are there other preferred alternatives (different delegates, etc.) for doing field level validation?


The Validation expression is checked on exiting the field when the field value has been modified.
This expression can also be a call to a function/procedure/prg, so you could handle your varying error messages their, e.g.

Validation: myfunc(“{}”)

param fld_value
do case
case fld_value = "something"


You also have Section and Page level ‘Valid when’ delegates and the Section ‘Before data update’ delegate where data validation can be carried out:

Users and Roles

Lianja already supports user roles and permissions for UI elements and now in Lianja 3.4 user roles extend into the core of the database engine to provide row level security.

Row Level Security (RLS) is a concept that provides security at the row level within the database layer, instead of at the application layer. With this new feature you can implement RLS without changing your application code.

Row-Level Security enables customers to control access to rows in a database table based on the roles (or groups) of the user accessing data.

Row-Level Security (RLS) simplifies the design and coding of security in your application. RLS enables you to implement restrictions on data row access. For example ensuring that workers can access only those data rows that are pertinent to their department, or restricting a customer’s data access to only the data relevant to their company.

The access restriction logic is located in the database engine rather than away from the data in applications. The database system applies the access restrictions every time that data access is attempted.

While architecting this functionality we looked at how it is implemented in other industry standard SQL engines and found all of them to be overly complex and long winded, so we came up with a simpler approach which is more flexible.

Row level security in Lianja is accomplished using row filters. Each row filter is associated with a tenancy, database, table and role name.

When a user authenticates the tenancy and username determine the roles assigned to the user.

Whenever a database table is accessed, the database engine will lookup the row filters associated with the table based on the roles that the authenticated user has been assigned.

If a user has a specific role and a row filter exists for that named role then the row filter associated with that role is included (OR) from the records that can be read.

If the role name is negated e.g. ~manager and the user does not have manager role, then the row filter is excluded (AND NOT) from the records that can be read.

These row filters operate across native Lianja tables and virtual tables, so you can use them with MSSQL, MySQL, PostgreSQL and other third party SQL databases also.

When defining row filters for Virtual tables you should specify the name of the virtual table as the table e.g. vt_customers.

Row filters are transparent to the application in desktop, web and mobile apps as well as OData API calls. In other words no changes in your applications is required in order to benefit from row level security in Lianja.

You create row filters in the users workspace.

Name:  Screen Shot 2017-02-17 at 12.03.51 PM.jpg Views: 62 Size:  47.9 KB

Row filters are stored in the system!sysrowfilters table.

This table has the following table structure:

Structure for table : sysrowfilters.dbf
Alias : sysrowfilters
Number of records : 2
Date of creation : 02/17/2017
Date of last update : 02/17/2017
DES3 Encrypted : No
CursorAdaptor : No
Field Field Name Type Width Dec Description
1 DOMAIN Character 80 Domain
2 DATABASE Character 80 Database
3 TABLE Character 80 Table
4 ROLE Character 80 Role
5 ROWFILTER Memo 8 RowFilter
** Total ** 329

Because row filters are stored in a database table you can also use standard SQL commands to perform CRUD operations on the row filters.

insert into system!sysrowfilters values (‘public’, ‘southwind’, ‘customers’, ‘bname’, [startsWith(customerid, ‘B’)])

Notice that ‘public‘ is the tenancy that a authenticated user belongs to and ‘bname’ is the role you have assigned to the user. A user can have multiple roles.

If the role you specify is prefixed with a ~ e.g.

insert into system!sysrowfilters values (‘public’, ‘southwind’, ‘customers’, ‘~cname‘, [startsWith(customerid, ‘C’)])

and the authenticated user does not have the cname role, then all rows where the customerid starts with a C are excluded from what the user can see.

You can test data access for different users and roles using the following commands interactively in the console workspace.

open database southwind
use customers
list status

set rowfilter on | off
set rowfilter to <expression>

The list status command now includes the roles and row filters for each table.


in a context of a multi company DB .. I can filter data for company?

Customers Table structure:
CompanyID, customerId, customerName

if the user is assigned to the comapany “A”
i can:
insert into system! sysrowfilters values ( ‘public’, ‘Southwind’, ‘customers’, ‘~ CompanyID’ [= ‘A’])

update …

And the user see and edit only the Customers records where “CompanyId” = “A”?

In this way I can create a multi tenancy app in a easy way..


Lianja already provides you with multi tenancy databases. You could use row filters but having a separate database for each company/tenant is a better choice in my opinion.

Row filters are better suited to providing views on data depending on user roles.

In your example code you would set the ROLE to ‘companya’ and the ROWFILTER to companyid=’A’

Then you assign the companya role to users in that company.


Suppose we have many contract staff who join and go on different date. When I add these new users, how can I auto set it to an “expired role” (i.e. deny further login beyond expiry will prompt “Contract expired.”) say 1 year or 1/2 year from the date of entry?


The users table does not have an expiry date column. You could however add a role e.g. expires20170701 and have a background task running once a day that removes users who have expired. This could be a .rsp page.


I have added an “Expires” column into system!sysroles table in Lianja 3.5. If a user attempt to login and an expiry date has been specified then the login is rejected if it has matured.


UI State

Lianja States provide you with a powerful mechanism for handling complex business processes using a “State machine” which is built into Lianja.

State machines have many interesting uses. States can easily describe user interfaces but they can also be used to model high-level business processes and many other things.

In a Lianja App, each UI element (App, Pages, Sections and FormItems) contains a (optional) comma separated list of “States” that the UI element responds to. In Lianja 3.2 we have added a new delegate called stateChanged(cState) which is called whenever a UI State is changed. This provides you with a programmable hook for managing App state.


Lianja.showDocument(“page: page1?action=changestate&state=namelist”)
Lianja.showDocument(“section:section1?action=chang estate&state=namelist”)

The delegate is called with one argument, the name of the state. Note that the namelist is a comma separated list so you can trigger multiple UI state changes at once.

When a “resetstate:namelist” is applied to the App the delegate is called with a single argument which is preceeded by a “-” sign e.g. “-editing”.

Note that changing UI state is only handled in runtime mode not the development view.




in the example_webapp2 app…

…In the web client this appears to lock the company name field. The user is no longer able to edit the Company Name field on any record. You have to exit the app or edit the whole page and cancel in order for the field to become editable again.

Should the navigation buttons be disabled automatically when a field is in edit mode, as is the case when editing a full record?


You can disable inline editing in the Web Client. There is an App Setting – the last setting under ‘General App Configuration’.


Is there a way to close a browse window using CTRL-W?


No, the window corner x is currently the only way to close the window.


I am looking for a list of all available hot keys in Lianja.


The Hotkey event delegate is triggered by the function keys, Ins, Backspace, Delete, PgUp, PgDn, Home, End and combinations of these with ctrl, alt and shift.…legates#Hotkey

There wasn’t a definitive list, so I have added these to the Hotkey delegate link.


I am also using Left, Right, Up and down arrows (which are working), so I thought perhaps there were other keys.


I had missed the hotkey functionality.

Does this functionality extend to mobile apps? The reason I ask is that “desktop” to us at this point means an Electron app.


Currently desktop (not Electron) only.


How does one set an individual ‘form’ to be a specific size rather than filling the whole screen


custom forms have properties for that.

Pages themselves always adjust to the geometry of the app. Custom forms exist on their own, in effect outside the page object and the App. Custom sections conform to the page width.

Custom forms limit your deployment flexibility: ever see a free-floating form on a mobile app?


You just specify the size of the window using showdialog.Name:  floatingwindow.jpg Views: 28 Size:  67.7 KB

As you can see in the image, I have an app that has a floating window outside the main part of the app.

in a mobile app, you would have to show the dialog panel with the OnTop parameter set to .F.,


In a canvas section, when a TextBox or NumericTextBox field has Editable = False, the background is greyed.

1. Is there a reason why this shouldn’t be the case for DateTextBox and EditBox fields (or possibly others…haven’t tested them all) ?

2. Is there a VFP equivalent to the Enabled property or is Editable the only option?

3. Is there a way to control the Background/Foreground Colors for Non-editable Canvas fields?


If you look in the App Settings there is an attribute which specifies the background color of non-editable/readonly fields.

The Qt UI framework which Lianja uses adapts the controls to the host operating system it is running on. This is so it renders native UI controls whenever available. Some composite UI controls do not have host operating system counterparts so these are custom controls.

The enabled property is not exposed for design reasons. You should use the editable attribute.

UI presentation rules can be used to adjust this dynamically depending on the logged in user.

In Lianja 4.1 I have enhanced the web/mobile framework so that you can embed grids, charts, webviews and pageframes (Tabbed UI) inside a grid cell or FormGrid cell.

I’ve also implemented the Lianja/VFP “form”, “webview” and “pageframe/page” classes in the web/mobile framework.

So now it is simple to show a popup window to edit a grid cell or drill down in a management dashboard.

Here’s some example JavaScript code:

f = createObject("form");
f.caption = "This is a popup form";
f.resize(1024, 600);
f.addObject("wv", "webview");
wv.url = "";;

and the result.

Name:  Screen Shot 2017-10-28 at 3.08.39 PM.jpg Views: 45 Size:  71.3 KB

Clearly using the Lianja Web/Mobile framework is dramatically easier than messing about with HTML/CSS etc and if you have any VFP knowledge you will be right at home with the custom classes available to you.

Remember also that you can addObject() a “container” to the “form” and give that container a “layout” of “grid”, “form”, “vertical” or “horizontal”. These layouts will help you build responsive UI forms that adjust and lay out their “children” UI components automatically.

So you can build complex data entry forms and extract the data from the form in the “afterClose()” delegate to update remote data or update the UI and change its state by selecting other pages using Lianja.showDocument() etc.

Further refinements with custom classes.

Pageframe/Page (tabs)

are now all available in the Web/Mobile client.

Pageframe handles the new “tabposition” property:

tabposition (can be “north”, “south”, “east” or “west” same as in desktop).

Name:  Screen Shot 2017-10-29 at 2.34.33 PM.jpg Views: 40 Size:  56.7 KB

Here is the JavaScript code for that dialog.

f = createObject("form");
f.addObject("pf", "pageframe");
pf.addObject("tab1", "page");
pf.addObject("tab2", "page");
pf.addObject("tab3", "page");
tab1.addObject("wv", "webview");
wv.url = "";
pf.tabposition = "south";;

You can handle Tab navigation yourself to stack up a lot of panels in the UI and raise one into view:

pf.tabbarvisible = false;

// select tab1
pf.activatepage = 0;
// or"tab1");

To provide a better mobile experience you can set the mobilefullscreen form property to true. This is ignored unless the App is running on a phone. On a phone this maximizes the form into the viewport of the phone and removes the border.

Note that you can show the form fullscreen on all devices by setting the “fullscreen” property to true.

f = createObject("form");
f.addObject("pf", "pageframe");
pf.addObject("tab1", "page");
tab1.addObject("wv", "webview");
wv.url = "";
f.fullscreen = true;;


accepted (a property). You describe the events. I can guess what “accepted” means but thought I’d ask just to confirm.


Its a property that is true by default.

You can set it to false in the beforeClose() event to stay in the form if validation fails.


can setAttribute() be used to change an app attribute?


setAttribute() as documented is only relevant to UI page, section, formitem… not App.


Categories UI


if you are doing JavaScript programming, you will do yourself a favor by moving to Typescript. All your JavaScript will still run, but you will gain modern programming features that will help your development.

The best part is that Lianja handles your Typescript compilation behind the scene, so there’s no drag on your development.

And to top it off, there is a very good book (from what reviewers write about it) available for free on Github:

What turned out to suit me best, however, was the TypeScript Handbook (click on Handbook to see and reach the Chapters), which has all the examples I need and moves right along.

You can write in typescript using plain JavaScript. It is automatically compiled for you by Lianja.

We include TypeScript definition files for “Lianja” and the “Lianja Framework”.

It is a very nice language indeed for building enterprise business apps..

There is a good handbook at:…sic-types.html

The benefits of TypeScript are that it is a modern OO scripting language with a high degree is compatibility with ES6 (EcmaScript 2015) but it can be transpiled (as Lianja does for you) into ES5 which is compatible with all current browsers.

Lianja transpiles TypeScript files into JavaScript behind the scenes and in fact will soon be handling jsx files (in the form of TypeScript .tsx files) . This will provide you with the ability to write custom WebViews using React and React-Native.




The UP/DN arrow keys move the highlighted row in a grid (Treegrid) on a canvas section. Is it possible in Lianja to detect when the ENTER key is pressed on a specific row. In VFP, this could be done with the KeyPress() event.


“Enter/Return” key is pressed it is treated as a double click so you can handle this in the doubleClick delegate.