View Full Version : Getting the mobile app / server data clear

2019-09-10, 17:51
Hi Guys

Still trying to get our heads around this.

We believe :

The app running on the tablet knows nothing about data.
When a JS delegate is called to then call a server side VFP proc, we cannot assume anything about data, record pointers etc.

The VFP server side proc should use PUSH/POP DATASESSION which makes sense if we were changing/opening tables.

Problem :

If we wanted to replace some data in the curent datasession (say using the results of a postcode lookup), how do we tell the server side proc which record to update?

RECNO() doesn't seem to work as a passed parameter - presumably because there is no record number as the tablet doesn't know anything about data.

It works well in desktop mode because the databound controls will update.

In mobile - how do we reference the current record to then tel the VFP proc which record to change?

We have tried the following but no good

// Event delegate for 'dialogbutton' event
function page1_section2_field12_dialogbutton()

var lrecno = RECNO();

var result = Lianja.evaluate("serverside('{lrecno}')");

Any thoughts?

Being a newbie is great sometimes - not sure that is today !!



2019-09-10, 22:49
Hi Simon,

It's Lianja: you've got options. :)

1) <section>.getCursor() retrieves the current record, where you can <cursor>.getData(<field>) and <cursor>.setData(<field>,<data>) You can then do a <section>.save() and (probably will need to) <section>.refresh()

2) You can call a VFP prg with a) the PK of the record and b) the data needing to be changed. This is handy if you need to munge the data for particular purposes. In this case, you will need to get the new data, which can involve <section>.reopenTable() and a <section>.refresh(). My experience in doing this is with a parameterized VT, so I also reset the params on the section, then reopen and then refresh.

The browser debugger is your friend: once you pull up the source, you can set a breakpoint, and then can issue these commands and see what happens.


2019-09-11, 02:38
Hi Simon,

When coding in JavaScript you need to remember that it's a case sensitive language so NAME() and name() are two different functions.

I can see your confusion is coming from building desktop apps where the data and the code reside on the same machine. recno() is a VFP Desktop function that relies on a desktop cursor being selected and is only valid in desktop or server side code.

As hank mentions you should use a unique primary key and pass that as a parameter to your server side function.

Can you please explain what it is exactly that you want your app to achieve so that something straightforward does not get made unnecessarily complicated.

Is all you want to do is have a data entry form which looks up address details based on a post code and then adds a new record on the server when all data is input? Or are you editing existing data and looking up the post code to update the record?

We can build a quick sample app that does that for you and provide it so that you can build on from that. If you want that please contact me directly. I don't want to see you fumbling around for days trying to do something which can be achieved in hours.

2019-09-11, 08:37
Hi Guys

Thank you for you input - all made sense.

Barry - we are trying to edit / update existing data

Now spent hours searching web trying to find required info - not easy. JS Lianja Developer is very helpful but there is always just a bit missing.

We cannot find the examples we need to understand so we are guessing as to how to send parameters to server side procs and receive a return value and are also guessing that section.refresh etc should be called from the mobile device and not from the server. There was a video about this (maybe Hank) but we cannot find it now.

We just cannot get the server side code to fire unless it is in desktop mode. Now we have rewritten the calling delegate completely dependiant on JS, we can't get it to fire at all. It is probably just a syntax issue.

Hank - thank you but there is no <section>.getCursor() method in the documentation so no idea how to accomplish that. We cannot get hold of the data to pass it to the server side function. As the mobile device doesnt know anything about data, how does getCursor() work?

Barry - we know we are just 2 "aha moments" away from this being easy but cannot afford to spend days and days counting to 3.

Will post delegate function - can you show us the error of our ways? We are sure it is blindingly obvious.

Hoped to have had this nearly done by now .....

Thanks in advance

************************************************** ***********************

Delegate :

// Event delegate for 'dialogbutton' event
function page1_section2_txtPostcode_dialogbutton()

var cust = Lianja.getCursor("cust"); table cust
var lcustid2 = cust.getData("cust_id"); character field

Lianja.showMessage(lcustid2); this only fires if we use the first Lianja.evaluate below

var result = Lianja.evaluate("LookUpPostcode('{lcustid2}')"); sends {lcustid2} as parameter - how do we get to the memvar?
//var result = Lianja.evaluate("LookUpPostcode(lcustid2)"); does not run LookUpPostcode
//var result = Lianja.evaluate("LookUpPostcode({lcustid2})"); crashes Lianja

// if (result = 1) {
// Lianja.showSuccessMessage("Success");
// } else {
// Lianja.showErrorMessage("Fail");
// }


2019-09-11, 09:52
I have included an example_pclookup app in the next build for you.

Open it, run it in a web browser and study the code for the dialogbutton delegate and the getAddressDetails() server side proc.

You can then use the same code in your App.

2019-09-11, 10:29
Thanks Barry - that's great.

Any idea when next build might be up?

I'm pretty sure we were almost there - we've just ended up going round and round in circles.

It will ceatinly help others as JS examples of parameterised function calls and their return values are so hard to find. THe VFP side should be pretty straight forward

Wonder what the issue with the vanishing canvas sections and static images was.

As soon as we have the demo - will let you know.

Thanks again


2019-09-11, 10:35
In a nutshell.


2019-09-11, 10:37
Oops: it's Lianja.getCursor.

Have you looked at: https://www.lianja.com/doc/index.php/Working_with_data_in_JavaScript ? Lianja.getCursor() is in the first part. The part about recordset is for people who want to work with data on the backend (e.g., a .jssp page) instead of VFP.


2019-09-11, 10:49
There is a new build uploaded already. It's RC54.

I have no idea what you did with the "vanishing" canvas. I have not been able to reproduce that.

2019-09-11, 13:18
Hi Hank

Yes thanks - read that.



2019-09-11, 13:31
Hi Barry

We get the idea thanks. That uses field display values rather than table data. In a tablet scenario that makes sense.

Done that way, it would be easy to change a single field value in a single call. What about bulk changes of several field at the same time on the serverside?

Wish we coud make out the text clearly in the screenshot but looks like you are using + or * chars around the variable ie + var + or maybe * var * with something outside that. We've spent all day trying to guess the syntax !!

Is the new example in RC54? Can't see any of the normal example apps in this build. What have you called it and we will search the hard drive.



2019-09-11, 13:55
It's in the build as I said. Example_pclookup

Read the code if you cant read the screenshot. It's basic JavaScript adding strings together just as you would do in your VFP code.

Changing multiple fields is clearly just a repeat of the statement that sets the text of the field based on the JSON object returned from the getAddressDetails() server side proc. If you follow the url I pasted in as a comment it will let you subscribe to their API for looking up address details for a given post code.

You can pass complex objects back to the client from the server using json_encode() and reference the members of the object in the client as I demonstrate in the example code.

As has already been explained you can either update the cursor or update the field in the UI which will result in the cursor associated with the controlsource being updated on the server when the section is saved.

Run the example and read the code you will learn from that.

2019-09-12, 08:21
Hi Barry

Works well - thank you. We would never have found the right syntax by trial & error.

One question... when we change the value of the textbox, is there a way to commit the changes other than writing the data separately for each field using cursorname.setData("fieldname", newvalue)?

When we call Lianja.get("pagen.sectionn").save() or Lianja.get("pagen.sectionn").refresh() the data reverts to the old values.

Can we commit either the section or the page or the lot in a single command?



2019-09-12, 10:08
See screenshots below.

As I mentioned previously. You can save() the section or update() the underlying cursor.

You are probably seeing data reverted back in desktop as you are not in "edit" mode on the section.



2019-09-13, 08:58
Thanks Barry

Something is not right here...

Runtime and in edit mode (manually from bottom toolbar). Page set to full page edit

Lianja.getCursor("cust").update(); - still reverts when you press save on bottom toolbar

Error: Method 'save' undefined on this object

and to ensure it's not a case issue
TypeError: Result of expression 'Lianja.get("page2.section2").Save' [undefined] is not a function.

Don't know why because "save" is a method in the documentation

The only way we can get it to save is :

var cust = Lianja.getCursor("cust");

cust.setData("adl1", addrDetails.adl1);
cust.setData("adl2", addrDetails.adl2);

So we can't update the cursor and we can't save the section. Is there some "master edit mode" we have to be in first? Is the edit button on the bottom toolbar not enough?

What are we missing?



2019-09-14, 06:21
Normally you "edit" from the form action bar and "save" or "cancel" from there.

Normally you don't need to work at a low level writing in JavaScript as Lianja does it all for you.

save() on a section when hand coding javascript was not exposed. It is in the latest build as is cancel().

Try the example i provided to you. If it works there then study the code I provided.