onAction() should accept a parameter as a field value

Questions and answers on designing your Servoy solutions, database modelling and other 'how do I do this' that don't fit in any of the other categories

onAction() should accept a parameter as a field value

Postby Bernd.N » Sun Oct 16, 2016 10:38 am

I have a tableField that shows the name of the person that created the record.
With a click on that field I want to open that person's record.

So I created a small generic gotoPerson() function that performs this task.
Code: Select all
/**
* @param {JSEvent} event
* @param {String} sUUID - UUID of a person
* @public
* @properties={typeid:24,uuid:"B4D8147E-ACA5-468B-95CD-AD41140567C1"}
*/
function gotoPerson(event, sUUID) {
   
   if (sUUID) {
      
      scopes.nav.showForm('frm_person_general_dtl', sUUID);
   }
}


When I want to hook my onAction() event of the tableField to gotoPerson(), my problem is that my second parameter creation_user_id is assumed to be a string and automatically surrounded by quotes.
But I want to provide the value of this field to the function, but how?
I already tried to put %% around it, but that gets also surrounded by quotes.
(What I want to avoid is to code an explicit function inside the form.js for this simple task, instead I want to call the function directly by using the onAction() property.)
Attachments
gotoPerson.png
gotoPerson.png (5.72 KiB) Viewed 8635 times
Bernd Korthaus
LinkedIn
Servoy 7.4.9 SC postgreSQL 9.4.11 Windows 10 Pro
User avatar
Bernd.N
 
Posts: 544
Joined: Mon Oct 21, 2013 5:57 pm
Location: Langenhorn, North Friesland, Germany

Re: onAction() should accept a parameter as a field value

Postby ROCLASI » Sun Oct 16, 2016 1:52 pm

Bernd.N wrote:(What I want to avoid is to code an explicit function inside the form.js for this simple task, instead I want to call the function directly by using the onAction() property.)

Not sure I understand your reasoning. Why would the following code be too explicit? You already pass all the info you need with the JSEvent.
Code: Select all
/**
* @param {JSEvent} event
* @public
* @properties={typeid:24,uuid:"B4D8147E-ACA5-468B-95CD-AD41140567C1"}
*/
function gotoPerson(event) {
   if (forms[event.getFormName()].foundset.creation_user_id) {
      scopes.nav.showForm('frm_person_general_dtl', forms[event.getFormName()].foundset.creation_user_id);
   }
}


Or are you saying this column name might be different per form?
Then you do pass the name of the column as you already are doing:
Code: Select all
/**
* @param {JSEvent} event
* @param {String} columnName
* @public
* @properties={typeid:24,uuid:"B4D8147E-ACA5-468B-95CD-AD41140567C1"}
*/
function gotoPerson(event, columnName) {
   if (forms[event.getFormName()].foundset[columnName]) {
      scopes.nav.showForm('frm_person_general_dtl', forms[event.getFormName()].foundset[columnName]);
   }
}


Hope this helps
Robert Ivens
SAN Developer / Servoy Valued Professional / Servoy Certified Developer

ROCLASI Software Solutions / JBS Group, Partner
Mastodon: @roclasi
--
ServoyForge - Building Open Source Software.
PostgreSQL - The world's most advanced open source database.
User avatar
ROCLASI
Servoy Expert
 
Posts: 5438
Joined: Thu Oct 02, 2003 9:49 am
Location: Netherlands/Belgium

Re: onAction() should accept a parameter as a field value

Postby Bernd.N » Sun Oct 16, 2016 2:32 pm

Thanks, Robert, that is a solution that will solve my task.
I am still curious if it would be possible to pass a field value directly to a function that I call in a form event, but if not, I can still use this generic solution you provided.

I would rename the function then formGotoPerson(), because it may be called only in the context of a form that holds that field, as it relies on that.
Bernd Korthaus
LinkedIn
Servoy 7.4.9 SC postgreSQL 9.4.11 Windows 10 Pro
User avatar
Bernd.N
 
Posts: 544
Joined: Mon Oct 21, 2013 5:57 pm
Location: Langenhorn, North Friesland, Germany

Re: onAction() should accept a parameter as a field value

Postby ROCLASI » Sun Oct 16, 2016 2:54 pm

Hi Bernd,

As far as I know you can only pass a literal this way. If you really want to pass objects or merge-codes I suggest you file a feature request.
Robert Ivens
SAN Developer / Servoy Valued Professional / Servoy Certified Developer

ROCLASI Software Solutions / JBS Group, Partner
Mastodon: @roclasi
--
ServoyForge - Building Open Source Software.
PostgreSQL - The world's most advanced open source database.
User avatar
ROCLASI
Servoy Expert
 
Posts: 5438
Joined: Thu Oct 02, 2003 9:49 am
Location: Netherlands/Belgium

Re: onAction() should accept a parameter as a field value

Postby Bernd.N » Sun Oct 16, 2016 4:10 pm

There is a property where it is already possible to tell Servoy to use the field value instead of a literal, that is the toolTipText property of a field.
I use it often when a table column is potentially too small, and put %%field_name%% into it.
Then the tooltip does not show "field_name" but it shows the full content of that field.
This works with relations too, like %%orders_to_customers.cus_name%%

The same mechanism/notation might be handy for such event parameters.
Maybe if someone from Servoy reads this, he/she might want to comment if a feature request would be promising.

The advantage of such a mechanism is that one spares to code explicit functions in the form.js
Bernd Korthaus
LinkedIn
Servoy 7.4.9 SC postgreSQL 9.4.11 Windows 10 Pro
User avatar
Bernd.N
 
Posts: 544
Joined: Mon Oct 21, 2013 5:57 pm
Location: Langenhorn, North Friesland, Germany

Re: onAction() should accept a parameter as a field value

Postby mboegem » Sun Oct 16, 2016 5:31 pm

Bernd.N wrote:The advantage of such a mechanism is that one spares to code explicit functions in the form.js


That depends on your skills as a programmer.
Having to bind parameters over and over again to make your code work isn't the solution: easy to forget, hard to write unit tests for, absence of JSDocs, etc., etc.
The JSEvent is added by default, and the amount of work to write just a bit of code to extract the dataprovider from the JSEvent is next to nothing.

When you need this a lot, the extraction part should be a scoped function itself, so you don't even have to think about it.
Combine this with some unit-tests and you'll be faster and safer than ever writing your code.
Marc Boegem
Solutiative / JBS Group, Partner
Servoy Specialist
• Servoy Certified Developer
• Servoy Valued Professional
• Freelance Developer

Image
User avatar
mboegem
 
Posts: 1752
Joined: Sun Oct 14, 2007 1:34 pm
Location: Amsterdam

Generic extraction function

Postby Bernd.N » Sun Oct 16, 2016 5:53 pm

Good idea, Marc, I added a second function for extraction and it works fine.
getFormFieldValue() is so far without any safeguard that checks the existence of forms[event.getFormName()].
I want to wait and look if that is ever needed.

What kind of unitTests would you write for this two functions?

Code: Select all
/**
* @param {JSEvent} event
* @param {String} sUUIDField - field name that holds the UUID of a person
* @public
* @properties={typeid:24,uuid:"B4D8147E-ACA5-468B-95CD-AD41140567C1"}
*/
function formGotoPerson(event, sUUIDField) {

   var sUUID = getFormFieldValue(event, sUUIDField);

   if (sUUID) {
      
      scopes.nav.showForm('frm_person_general_dtl', sUUID);
   }
}

/**
* @param {JSEvent} event
* @param {String} sFieldname
* @public
* @properties={typeid:24,uuid:"1C794292-5E5C-4634-A5BE-D7325E6D1C57"}
*/
function getFormFieldValue(event, sFieldname) {

   return forms[event.getFormName()].foundset[sFieldname];
}
Bernd Korthaus
LinkedIn
Servoy 7.4.9 SC postgreSQL 9.4.11 Windows 10 Pro
User avatar
Bernd.N
 
Posts: 544
Joined: Mon Oct 21, 2013 5:57 pm
Location: Langenhorn, North Friesland, Germany

Re: onAction() should accept a parameter as a field value

Postby mboegem » Sun Oct 16, 2016 6:07 pm

unit tests are specific functions that can test the behaviour of the functions you write.
So in case you change any existing functions, you can easily re-test the behaviour and when all tests pass, you know your solution will not break.

I'm just wondering what the dataProvider is of the field you click on.
I would expect that to be the creationUserID and you show the name using a relation or valuelist.
In this case you should strip down your code even more and use the event.getSource() function to find out the element.
Based on the element you can grab the dataprovider.
Marc Boegem
Solutiative / JBS Group, Partner
Servoy Specialist
• Servoy Certified Developer
• Servoy Valued Professional
• Freelance Developer

Image
User avatar
mboegem
 
Posts: 1752
Joined: Sun Oct 14, 2007 1:34 pm
Location: Amsterdam

Dataprovider

Postby Bernd.N » Sun Oct 16, 2016 7:18 pm

You are right, I use a relation, in this case the dataprovider of that table field is weblinks_to_persons.clcs_ps_full_name
(clcs is our prefix notation for calculated stored field, so that we know that it is a stored calculation)
Bernd Korthaus
LinkedIn
Servoy 7.4.9 SC postgreSQL 9.4.11 Windows 10 Pro
User avatar
Bernd.N
 
Posts: 544
Joined: Mon Oct 21, 2013 5:57 pm
Location: Langenhorn, North Friesland, Germany

Re: onAction() should accept a parameter as a field value

Postby mboegem » Sun Oct 16, 2016 10:01 pm

Then I'd do something like this:

Code: Select all
/**
* @param {JSEvent} event
*
* @properties={typeid:24,uuid:"13A523BF-EB6B-4366-B56E-AA32AF0ACCDD"}
*/
function getOnActionDataProviderValue(event) {
   if(event) {
      var _value;
      var _sForm = event.getFormName();
      var _source = event.getSource();
      if(_source && _source.getDataProviderID()) {
         var _sDataProvider = _source.getDataProviderID();
         
         if(_sForm) {
            _value = forms[_sForm].foundset[_sDataProvider];
         }
      }
   }
   
   return _value;
}


And then:
Code: Select all
/**
* @param {JSEvent} event
* @public
* @properties={typeid:24,uuid:"B4D8147E-ACA5-468B-95CD-AD41140567C1"}
*/
function gotoPerson(event) {
   var _sID = getOnActionDataProviderValue(event);
   if (_sID) {
      scopes.nav.showForm('frm_person_general_dtl', _sID);
   }
}


The getOnActionDataProviderValue function can be used over and over again for similar situations without changing 1 single bit of code.
Marc Boegem
Solutiative / JBS Group, Partner
Servoy Specialist
• Servoy Certified Developer
• Servoy Valued Professional
• Freelance Developer

Image
User avatar
mboegem
 
Posts: 1752
Joined: Sun Oct 14, 2007 1:34 pm
Location: Amsterdam

Re: onAction() should accept a parameter as a field value

Postby Bernd.N » Mon Oct 17, 2016 10:09 am

I tried the code, but I get the dataprovider weblinks_to_persons.clcs_ps_full_name and not the needed value of creation_user_id, as that is not inside the dataprovider of that table field.
But to give the function a hint with a second parameter as done above, is totally fine and no work at all.
Thanks a lot to all contributers for all the tips!
Bernd Korthaus
LinkedIn
Servoy 7.4.9 SC postgreSQL 9.4.11 Windows 10 Pro
User avatar
Bernd.N
 
Posts: 544
Joined: Mon Oct 21, 2013 5:57 pm
Location: Langenhorn, North Friesland, Germany

Re: onAction() should accept a parameter as a field value

Postby mboegem » Mon Oct 17, 2016 11:37 am

Bernd.N wrote:I tried the code, but I get the dataprovider weblinks_to_persons.clcs_ps_full_name and not the needed value of creation_user_id, as that is not inside the dataprovider of that table field

Ah yes, overlooked that bit.
You can get around that by using a valuelist of users in order to have the username displayed from the user_id.
That might even have positive effects on performance in tableviews as Servoy doesn't need to re-evaluate the relation for each record.

However, I don't know if you allow find/search on this field, but this will probably change that behaviour...
Marc Boegem
Solutiative / JBS Group, Partner
Servoy Specialist
• Servoy Certified Developer
• Servoy Valued Professional
• Freelance Developer

Image
User avatar
mboegem
 
Posts: 1752
Joined: Sun Oct 14, 2007 1:34 pm
Location: Amsterdam

Re: onAction() should accept a parameter as a field value

Postby Bernd.N » Mon Oct 17, 2016 12:59 pm

Yes, we do find/search on all fields in a table with a generic quicksearch function, and with a more advanced filtering function when more than one field is involved.

Do valuelists also improve the performance when they are large? One of our customers has 800 users, so I would hesitate to build that valuelist.
I would hope that when Servoy builds the foundset for that table form, it will do so by using a normal SQL Join and not re-evaluate the relation for each record separatly.

When it comes to business partners, there are > 6.000, and I would fear that such large valuelists would need too much server or client memory (though I do not know so far where such valuelists are created and stored, but my guess is inside the server).

Therefore, due to my feeling, I ask my developers to avoid such big valuelists. And inside the UI we use a picklist component when it comes to pick a customer or person.

But anyway, the previous solution with the additional parameter works perfect. :)
Bernd Korthaus
LinkedIn
Servoy 7.4.9 SC postgreSQL 9.4.11 Windows 10 Pro
User avatar
Bernd.N
 
Posts: 544
Joined: Mon Oct 21, 2013 5:57 pm
Location: Langenhorn, North Friesland, Germany

Re: onAction() should accept a parameter as a field value

Postby rafig » Tue Oct 25, 2016 12:12 pm

Bernd, with regard to the value lists, assuming that they don't change during the course of a 'session', you can call a method 'onStartup' that loads the value lists using SQL and then they are always ready & Servoy doesn't need to dynamically load them every time they appear on a form.
I do this for one of my client solutions and it really improved the performance.

Here are the basic steps
1) create empty value lists (i.e. set to custom value, but with nothing in it
2) in your onStartup call a method, like loadValueLists
3) in function loadValueLists call each method that loads each value list
4) you can load either single value lists, or ones that have display & return values, like this
Code: Select all
function loadPaidUsingValueList ( )
{
   var query = "SELECT paid_using FROM vl_paid_using ORDER BY sort_order ASC";
   var dataset = databaseManager.getDataSetByQuery ( server_name, query, null, 1000 );
   application.setValueListItems ( 'vl_paid_using', dataset );
}

function loadProductsValueList ( )
{
   var query1 = "SELECT item_number + ' ' + description FROM stock WHERE (archived = 0) AND (item_number IS NOT NULL) ORDER BY item_number";
   var dataset1 = databaseManager.getDataSetByQuery ( server_name, query1, null, 10000 );
   var displayDataArray = dataset1.getColumnAsArray ( 1 );
   var query2 = "SELECT stockid FROM stock WHERE (archived = 0) AND (item_number IS NOT NULL) ORDER BY item_number";
   var dataset2 = databaseManager.getDataSetByQuery ( server_name, query2, null, 10000 );
   var realDataArray = dataset2.getColumnAsArray ( 1 );
   application.setValueListItems ( 'ProductsUnarchived', displayDataArray, realDataArray );
}

This also overcomes Servoy's limitation of number of values...

Rafi
Servoy Certified Developer
Image
rafig
 
Posts: 708
Joined: Mon Dec 22, 2003 12:58 pm
Location: Watford, UK

Re: onAction() should accept a parameter as a field value

Postby Bernd.N » Tue Oct 25, 2016 7:56 pm

Thanks for the tip!
Is a valuelist really loaded fresh from DB each time when a form shows, or just only once at form.onShow/firstShow ?
When the first is true, I can imagine that it slows down a solution, while the second is totally fine, as then a valuelist is loaded only when it is needed.
Bernd Korthaus
LinkedIn
Servoy 7.4.9 SC postgreSQL 9.4.11 Windows 10 Pro
User avatar
Bernd.N
 
Posts: 544
Joined: Mon Oct 21, 2013 5:57 pm
Location: Langenhorn, North Friesland, Germany

Next

Return to Programming with Servoy

Who is online

Users browsing this forum: No registered users and 33 guests