Script as field – how to get the output ?

Tap Forms – Organizer Database App for Mac, iPhone, and iPad Forums Script Talk Script as field – how to get the output ?

Viewing 18 reply threads
  • Author
    Posts
  • October 11, 2019 at 4:57 AM #37052

    Marcus
    Participant

    Hi Script Guys,

    It’s more or less not a scripting question but how to use it in TapForms.

    I do have a form with a script field, the script behind, just as simple example:

    function Script() {
    var hello_world = "Hello World"; 
    return hello_world;
    }
    
    Script();

    I assumed TapForms will set this field value to “Hello World” when a recordset is added or changed ?
    But it’s empty, independant of which type of value (text, number, …)
    The console log shows the value, but the field stays empty.

    I additional added document.saveAllChanges; without any change.

    Or is such a script field to be used only to set another field value by using recordset.setFieldValue(ID,value) ?

    October 11, 2019 at 8:33 AM #37055

    Sam Moffatt
    Participant

    I believe script fields are only executed when a referenced field is changed. Because the default snippet doesn’t reference any fields, by default it doesn’t execute. Perhaps it could be considered a bug it doesn’t run on a new record creation, calculation fields run after creation.

    What you could do is get the value of every field in the form, then a change will trigger the script every time those fields change. Alternatively you can manually refresh the record after creation and it’ll force the execution of every script and calculation field. The manual refresh is done by clicking the “Recalculate formulas” button at the bottom of your record, by selected “Record” > “Refresh Selected Record” when the record is selected in the layout or you can refresh your entire form by clicking “Refresh record list” under the list view area.

    When running in the script editor, not everything is persisted. If you’re working with just a single record you’ll need to manually refresh it per the above but if you want the new script field code to apply to all of your existing records you should tick “Update records when saving” next to “Done”/”Save” buttons at the bottom right of the script editor.

    I’ve not found this too problematic in practice, generally you’re picking up field values to work with and when those are populated the script should execute. What is your use case for running a script at form creation?

    October 11, 2019 at 8:47 AM #37056

    Marcus
    Participant

    My use case is to calculate days between 2 dates.
    I was never able to use a calculation field to get a value as number.

    October 11, 2019 at 11:02 AM #37057

    Marcus
    Participant

    By using an additional number field that works:

    function calcdays() {
    var today = new Date();
    var date_id = 'fld-db4e94e8bb1a46e7b886afba72a6f2df';
    var bought = record.getFieldValue(date_id);
    var days=today.getTime() - bought.getTime();
    var days=days / (1000*3600*24);
    var res = record.setFieldValue('fld-1737a7de921041b3a2d6d90340537480',days);
    document.saveAllChanges();
    }
    calcdays();

    But is the right way to use a script field ?
    The general question I have:
    Is such a script field able to have a output (value) directly ?

    October 11, 2019 at 9:29 PM #37058

    Sam Moffatt
    Participant

    The built in calculation field has a DAYS function that will give you the number of days between two dates and put it in the field.

    The field ID detection code I think is triggered by getFieldValue('fld-etc') and using the var date_id syntax is tripping it up. It’s a little bit magical, I made my piece with it once I figured it out.

    In the script editor when I run the code (though changing the field ID), I also get an error reporting TypeError: bought.getTime is not a function. (In 'bought.getTime()', 'bought.getTime' is undefined), column:46, line:4. Take out the getTime()

    You don’t need the document.saveAllChanges() in this context, however in your example what you’re missing is a return days; at the end. Something like this I think would work better for you:

    function calcdays() {
        var today = new Date();
        var bought = record.getFieldValue('fld-018ce5f02f7a4655be3e8f4377592f8b');
        var days = today - bought;
        var days = days / (1000*3600*24);
        return days;
    }
    calcdays();
    

    Here’s what that script looks like:

    And in the default layout it looks like this:

    That said once that script runs once, unless the “bought” field changes or your refresh the record then the script field value won’t change. There isn’t a way to automatically recalculate the value. This makes sense because Tap Forms is generating the value and saving it so that it doesn’t have to recalculate it every time. I suspect it also helps the search system by not having to regenerate the value when you search or sort too.

    Another thread on age calculations is here: https://www.tapforms.com/forums/topic/age-calculations/

    Attachments:
    You must be logged in to view attached files.
    October 11, 2019 at 10:00 PM #37062

    Brendan
    Keymaster
    var date_id = 'fld-db4e94e8bb1a46e7b886afba72a6f2df';
    var bought = record.getFieldValue(date_id);

    the above code should still trigger the script to execute when the date field changes values.

    @sam, shouldn’t your example formula and script return a Number value?

    The DAYS() function returns a Number. Your sample is returning Text.

    October 11, 2019 at 10:09 PM #37065

    Sam Moffatt
    Participant

    The numbers convert over to text just fine, going the other way doesn’t work generally. I reused the calc field in this test form that was already a “text” type though because the default for calc fields is number.

    I could use number though for this since they’re all number, just didn’t because lazy :D

    October 11, 2019 at 11:46 PM #37068

    Marcus
    Participant

    Hi Guys,

    thanks so far, but I‘m not sure if we‘re talking about the same.

    @Sam: This Built-In calculation field is not available on an iPhone !
    I do not have this TypeError like you.

    My screenshot shows a working method,
    but I‘ve to use a script field and additional a „days“ field. What I‘d like to know if only a script field would be necessary to return the value ?

    However, independent of the calculation of days,
    that‘s a general question:

    Assuming I have a simple script field:

    function Script() {
    return 'Hello';
    }
    Script();

    1. shouldn’t the field value „Hello“ ?
    2. when a script is triggered ?

    Attachments:
    You must be logged in to view attached files.
    October 12, 2019 at 9:19 AM #37072

    Sam Moffatt
    Participant

    Calculation field exists on iOS, all of the field types are supported on both Mac and iOS. There’s a slight difference that on iOS it wraps the field name in square brackets so it’d look like `DAYS(
    [Bought];TODAY())` or similar.

    To your question:

    1. That should return Hello
    2. Script is triggered when a dependent field is changed or you refresh the field. On iOS, pull the record down to refresh the calculation manually.

    Looking at your screenshot, you’re still missing the return statement at the end. You can do return days; as the last line of the method similar to the return 'Hello'; and it should work properly.

    Attachments:
    You must be logged in to view attached files.
    October 12, 2019 at 10:28 AM #37079

    Marcus
    Participant

    I was (not yet) aware about the fx in a calculation field, using version 5 since some days.

    Refresh the recordset to get a value from a script field is tricky.

    Thanks, Sam.

    October 12, 2019 at 2:16 PM #37081

    Sam Moffatt
    Participant

    No worries, happy to help! The Calculation field is pretty powerful, it has a bunch of built in functions for simple operations from the fx menu item.

    The script field is a bit tricky however you can press the “play” button in the editor above the keyboard and it’ll run the script for you and you can see it’s output. There is also an option for a console log as well to see any debugging output. That enables you to do some iteration and testing as you go.

    Attachments:
    You must be logged in to view attached files.
    October 13, 2019 at 12:01 AM #37102

    Marcus
    Participant

    Ya, got it.
    I already created a bunch of helpful scripts,
    I only was stuck hanging to automate with a script field rather than execute it manually.

    One last question:
    Is there a possibility to get filtered recordsets only ?

    This returns ALL records:

    var records=form.getRecords();

    October 13, 2019 at 12:11 AM #37104

    Sam Moffatt
    Participant

    Check out the JavaScript API page: https://www.tapforms.com/help-mac/5.3/en/topic/javascript-api

    If you have a named search then you can get that via form.getSearchNamed('Search Name') and then you can call getRecords() on what it returns to you.

    October 13, 2019 at 2:59 AM #37109

    Marcus
    Participant

    Thanks.
    I saw that already, but thought there‘s a possibility to apply a loop over visible (already filtered) items.

    I do have a search called „ToDo“, it‘s filtering 21 records.

    This returns nothing:

    function Test() {
      var records=form.getSearchNamed('ToDo');
      return records.length;
    }
    
    Test();

    What‘s wrong ?

    October 13, 2019 at 9:33 AM #37114

    Sam Moffatt
    Participant

    The call to getSearchNamed just returns a search object, you need to call getRecords() on it to get a list of records, e.g. form.getSearchNamed('ToDo').getRecords().

    October 13, 2019 at 10:51 PM #37121

    Marcus
    Participant

    Ok, that sounds logical.
    Unfortunately it returns just a 0

    `function Test() {
    var records=form.getSearchNamed(‘ToDo’).getRecords;
    var L = records.length;
    // is ZERO:
    return records.length;
    }

    Test();’

    October 14, 2019 at 12:04 AM #37124

    Brendan
    Keymaster

    @Marcus, check that form returns something and that form.getSearchNamed('ToDo') returns a search object. If the search is not called ‘ToDo’, then your code won’t work.

    October 14, 2019 at 2:53 AM #37125

    Marcus
    Participant

    Oh man.

    getRecords; vs. getRecords();

    getRecords();

    October 14, 2019 at 12:05 PM #37128

    Brendan
    Keymaster

    Oops… I missed noticing that in your code. Yup, parentheses are required since getRecords(); is a function call and not an object property.

Viewing 18 reply threads

You must be logged in to reply to this topic.