Posted: 2017-01-17 in Grid

Have a section “section1”, as grid, there’s a test table in it.
Another section “section2” as a canvas with a button on it.
Code in button:


You could also use


Then click on to the newly added record to populate any fields without defaults.

I’d like to read some values from a grid section eg. column ‘firstname’ from the currently active row. This should be easy to do once I have a reference to the grid, but this is where I am having trouble.
Both below return some kind of object but accessing eg. loGrid.Recno gives ‘Property/Variable ‘RECNO’ not found‘. It does this for any property.

local loGrid = Lianja.get("Supplier.section1")
local loGrid = Lianja.get("Supplier.section1").Grid //Is this is only for grid objects in custom sections?

Try it without the ‘local’

“Lianja is data-centric”

Grids are data bound. You can reference the actual data in the cursor as this is based on the active record as you move between records of the grid.
Why futz about referencing grid cells when you can just work with the underlying data.
Cursors are selected dynamically when refreshing each section. Pages are made up of sections. Sections can be data bound and have an underlying cursor.

in a grid section, I need to correct the value entered by user:
user type “Carry”, I want to replace it with “Barry”.
How can I do it?
In the validatation delegate of field “artcar.descrizione” I’ve put a function validCar(‘{}’)
In this function I do:

If psValue = "Carry"
  replace artcar.descrizione with "Barry"

but not work… I’ve no error, but the value of the field is every “Carry”…
Remember that the ‘Set data mapping’ can call a user defined function and your code determines the return value. e.g.

If psValue = "Carry"
  return "Barry"

Or, use the Section Before or After data update to replace the field value when the row is saved.
Validation is used to check and accept/reject the input value, displaying a message if the input is rejected.


I need to perform a query to see if the text inserted from the user is correct, if not, I need to open a browse/rsp/form or other to simplify the user choice..
in this case I’ve 3 value, but I can have a lot of value.. eg the item list.. or the vendor list..
I can not use the “Section Before or After data update”.. if I’ve more “controlled” field in the grid, I need to check one by one.
So put those operations in the user defined function for the Set data mapping.
e.g. On the orders.customerid column, I specify:

Set data mapping: p_val(“{}”)

param p_typed
++ dmcount  // public memory variable initialized to 0
if mod(dmcount,2) = 0
        m_chosen = p_typed
        m_chosen = customerid
        select orders
return m_chosen
// end

(The check on the dmcount here prevents the showdialogpanel() being called a second time after a new value is returned.)
I enter a value, here ‘MILNE’ and p_val() is called, firing up the Lianja.showdialogpanel() UI Page.

I select a customer and the customerid is returned by p_val().

The Validation is called after the Set data mapping – though I would think any validation should take place in the Set data mapping UDF in this scenario.
Open the App Inspector to the Log tab and put this in your Validation UDF and you should see the call:

Lianja.writeLog("In validation")

for the grid navigation the issue is is that when the grid is not readonly and data fields are readonly, the user can still add new record or delete a record using the buttons (+) and (-). I think that this can cause troubles in the database with the risks of data manipulation when a grid is diplayed like that.
Readonly option on a grid is a good option to prevent record deletion or addition.
Why not uncheck the Show actionbar attribute on the section? If you are using keystrokes, PgUp, PgDn, Ctrl-Home and Ctrl-End provide alternatives to the navigation buttons in the actionbar.

I have a grid section and I want to move the cursor programmatic to refresh.
Select mytable, seek or locate something, then call the refresh of the grid section, does nothing.
Select mytable, goto 100 then call the refresh of the grid section, does nothing.
grid.goto 100 don’t work
delegate section:grid1.section1?action=goto is not available.
Set the activeRow property to position on a row relative to the grid
Use the activeCell() method to position on a cell of the grid
Use the goto() method to position on a specific record within the grid

I have a page1 with section1 with a grid in it.
Section2 canvas section with a commandbutton. In the click event;
I try to move the cursor in section1 and refresh the section grid;
Tried seek, locate, goto, nothing works.

proc page1_section2_field1_click()
Lianja.getElementByID("page1.section1").activerow( 500)
Lianja.getElementByID("page1.section1").activecell (500,1)

All four lines of code don’t work
I Tried;

select address
go 500
oGrid = Lianja.get("scout.log").grid
lnActiveRow = oGrid.rowcount
oGrid.activatecell(lnActiveRow, 1)

this don’t work, but I think it’s maybe a bug. It has something to do with pagination.
If pagination=50 and I run this event, On screen it activates record 50.
If pagination=250 and I run this event, On screen it activates record 250.

You can only set the activeRow or activeCell in the current viewport. If you need to move outside of that then turn pagination off.
Turn pagination off
Use the grid.goto(500) method call

If i have filtered grid like this

Lianja.get("section1").grid.filter = "startsWith(customerid, 'A')"

and I use the code below to move from record to record then it does not work.

sec = Lianja.get("section1")
        grd = sec.grid
        grd.goto(grd.activerow + 1)

It appears that the row is being moved on the filtered gird but I suspect it is moving between rows that are not visible.When the grid is not filtered it works just fine:

Lianja.get("section1").grid.filter = ""

        sec = Lianja.get("section1")
        grd = sec.grid
        grd.goto(grd.activerow + 1)

you are confusing record numbers with rows in the grid. They are two completely different things.

To move rows assign a value to the activeRow property. Goto() is for positioning on a record number that is in the grid data which it clearly may not be when using a filter to restrict the data displayed.


If I change data in a grid section’s cell and hit ‘enter’, the change event doesn’t fire although the database and grid have both been updated. This seems inconsistent because it means grid data can be changed (with the db updated) and if the user navigates away from that page, ‘change’ code would never run.
Navigating to another row or clicking either the grid or page ‘save’ buttons causes the event to fire as expected.
Oh, and out of interest I also looked at the datachanged and afterupdate events – afterupdate behaves as ‘change’ above and datachanged never fires.
Datachanged is fired when you move between rows not when you edit the data. It’s typically used to refresh sections manually based on the current record of the grid.
It fires when the section is related.
The cell is updated. The database is not until the row is flushed as Lianja uses row buffering.
The record in the database is updated when you move off the row or force update it. If you move from one cell to another on the same row it is in the row buffer.

in runtime mode with the App Inspector open. You can see the order of the events,
There is no rowcolchanged delegate in grid sections.
Moving between cells just updates the “dirty” buffer it does not dispatch any delegates nor does it update data in the database.

Clicking the “Save” and “Revert” buttons works as it should so I do not know what you are doing for it not to work, unless you are moving off the record in a delegate.

If I look at the Grid object in the lianja docs it lists these events: afterRowColChange, beforeRowColChange, dragDrop
and the Section Object list no events except the common ones.

Now if I drag a grid section on to the page then I see some other event delegates, like change, after update etc. but not afterRowColChange and the others from the Grid object.
So my question is: where can I get info about the events for a grid section, and where would one access the eg. ‘afterRowColChange’ (is this maybe only for a grid created in a custom section?)
Grid sections are not exactly the same as grid objects in custom sections. Grid objects are there fir VFP 9 UI framework compatibility.

I added a grid section to one of my page, but the database and table sections are greyed out and blank.
If you hold down shift and then click on a table, drag’n drop it onto a page, then the database and table will be populated. These are read only attributes.

In v2.1 I have added several new section attributes for grids and attachment sections to handle dynamic grid row colors dependent on an expression. This is similar to dynamic cell colors for grid columns but affects the whole grid row. It is particularly useful when a grid is being refreshed at intervals and you want to hilite certain rows.


Grids and attachment sections now honor the “Pagination” attribute setting for grids in the web/mobile client so all rows fetched are loaded into the grid if pagination is off.

how calculated columns in a table are refreshed on a grid.
Is the grid aware that the values are auto calculated or does there need to be refreshes in delegates?
in the column attributes of the grid, there is a recalculate checkbox that handles what you mention.

I had a situation where I wanted to populate a grid with a cursor that I had generated; allow the user to edit the data; and have data rules applied from the data dictionary.

What I did was create a table that had a special field in it, cFilterExp C(36). When the user went to the page where that grid resided, I used guid() to create a guid, created the rows in the table which was shared by all users, put the guid() in the cFilterExp of each row, and set the filter of the section to that same guid() value. When the page was used with new data, a routine deleted the records from the table based on the old guid(), etc.

I like working with tables/cursors much more than manually adding data to a grid, and having a real cursor gave me the ability to use dbf() to append the data to the real table. It was actually pretty efficient.

the way to properly replace grid fields with new grid data
My grid is sourced to a data file. I do the updates in the data file and then a skip 0 and refresh of the grid.

The specific code is as follows

Testlu1() &&testlkup8b() && &&LKUPL2('','L') &&DO LKUP2

debugout MSTOCK
debugout invdet.STOCK



REPLA stock with INV.stock,;
invdet.unit with iif(invdet.unit=' ',iif(INV.unit=' ','EA',INV.unit),invdet.unit),;
invdet.act with iif(EMPT(INV.act),MATCD,INV.act),invdet.COST WITH INV.COST

debugout 'REPLACE'

The result is that the stock field which is the current grid field in focus when my valid is called gets updated but none of the other fields chg.
Your replace is attempting to replace values in two different cursors (detail2 and invdet). Keep to one cursor target per replace statement.
REPLACE is by cursor. Make it one or the other. If you remove the invdet. from the rest of the statement, then, it should work.
you are not doing a skip 0 in the invdet cursor so the buffer is not being flushed.
The following command will force write all dirty buffers:

//instead of skip 0


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s