Reposting because my original reply got flagged as spam.
I’m uploading a sample form template that shows what I mean. It has two fields in it, a text field and a script field. I also included the form logger script with an update that prints out field ID’s in Javascript variable syntax. That’s used at the top top populate the field ID’s because by default the script editor doesn’t expose script fields. I also use this syntax because it includes the form name which makes it easy to keep track of variables in larger documents with lots of forms and lots of fields. There’s a commented line to ensure that Tap Forms registers this script to the field that works even if the line is commented out. I then grab the text field and the contents of the script field.
For the script field, I check to see if it is set and provide a default dictionary if it isn’t set already. If it is set to a value, I assume it’s JSON and parse it back into an object.
Then at that point it’s a quick comparison of the deserialised JSON payload and your new one. I added a message in so you can see a note, always useful after the fact for some of these scripts even if you hide the field by default, you can unhide it to see what it has in it.
Lastly the script field ends with JSON.stringify to return a JSON string as the fields contents. This object can obviously contain what ever you want in it so if you have multiple values instead of setting multiple fields, you just return a value at the end of your field script with the data you need to keep track of from each execution.
Sample execution: 
Field script:
// Script Field State
var script_field_state_formID = "frm-86fd53d1f9ab47548636fc2e2d1d0d35";
var script_field_state__main_field_fldID = "fld-2177d4bf8500482d8fc6242faa80c5e6"; // text
var script_field_state__watcher_fldID = "fld-7e997368aef740f68f126d2c8509d148"; // script
// Make sure the field is watched to pick up changes.
//var main_field = record.getFieldValue('fld-2177d4bf8500482d8fc6242faa80c5e6');
var main = record.getFieldValue(script_field_state__main_field_fldID);
var state = record.getFieldValue(script_field_state__watcher_fldID);
if (!state)
{
state = {'previous':undefined,'message':'Initial setting'};
}
else
{
state = JSON.parse(state);
}
if (state['previous'] != main)
{
state['message'] = `Field value changed from '${state['previous']}' to '${main}'`;
state['previous'] = main;
}
JSON.stringify(state);
Attachments:
You must be
logged in to view attached files.
It is possible that your script can be re-entrant if it watches multiple fields and you call setFieldValue on one of those fields. There is a third parameter to setFieldValue that controls if scripts are executed, flip it to a falsy value and scripts won’t be executed from that setFieldValue invocation. I used to write my own guards because Javascript instance is reused so you can share variables between the other scripts triggered by setFieldValue. Photo fields can also exhibit the same behaviour but I there isn’t a flag to disable them. For those I try to ensure that the field ID is obscured to prevent Tap Forms from triggering my script field for it.
I am writing a script that touches (read/write) several fields on the form. I am guessing at this point but I think that as each of these fields are touched within the script they are invoking the script again on their own which is causing strange results. Can anyone confirm that this is either possible / not possible and if it is possible how can I stop this behavior so that a script is only executed when one of the fields that are being touched invokes the script?
I use a hidden field to save state of what fields used to be and then compare the new field value against the old one. There is no before change data so you have to grab it yourself.
I also have another technique where with the script field, you can return a value. So you can use the script field itself to store the previous state and by accessing the script field with getFieldValue, you can then get at the previous value. When you finish up your script field, you return the previous value. If you have a few different values you want to track, you can use JSON.stringify and JSON.parse to serialise and unserialise the field value into an object in JSON.
Hopefully that helps.
Richard, is your ‘Notes’ field of type text or note? Brendan’s description is for a note type field.
Cheers, Daniel
---
See https://lab.danielleu.com/tapformspro/ for scripts and tips&tricks
If you have a Script field and you use record.getFieldValue(field_id) within the script, Tap Forms will add that field_id to a watch list. So when the value of that field changes, the script will execute.
I am having difficultly making this work for me – would Brendan or another user be able to provide a simple worked example how this operates?
I am finding JavaScript difficult and general guides are not, at least for me, helping in understanding how to apply much of the example snippets that Tap Form provides.
Any help would be very gratefully received.
Greetings,
Is there a way that I can detect when a text field that uses a pick list has had a value change? Say for example it used to be ‘ABC’ and now it is ‘DEF’. How can I catch when the value has changed so I can script it? I suppose a hidden field could be used as a form of global variable but that seems like a hack.
Got it working just wrote a script for it.
From a script you can call form.getTotalOfField(field_id) to get the grand total value. There’s also an equivalent one for saved searches: `search.getTotalOfField(field_id)’
However, it wouldn’t work for a Table field. I guess I need to add those functions to the Table field. You’d just have to write a script that loops through the records and totals the value of the sub-field and displays it on the parent form.
However again, the Calculation field does have the ability to give you the total of a field from within a Table field. Just double-click on any numeric type field in your Table field on the formula editor and Tap Forms should print something out like TOTAL::Table Field::Sub-Field. That’ll give you the result you want.
That worked perfectly so one more follow-up question. Can I through script or calculation field access the auto sums/totals that the table creates for me? I need that value to feed another script on my form.
Table fields are sort of like forms themselves, but they don’t belong to any actual form. So you can’t write a Form Script attached to a Table Field.
But what you can do is add a Script Field to your Table Field that checks the value of your Checkmark field and returns a sum if the Checkmark field returns 1. 1 is On, 0 is Off.
Then you could simply tell Tap Forms to total up the result of your Script Field which will give you the grand total of only the checked items.
Greetings,
Yes I was able to get things working but it did bring up a new question. Contained within my field of type ‘table’ I have a child field of type ‘checkmark’. The question is how do I respond to the click event (if this exists) so that I can run a script?
Currently the table is giving me a sum of one of the numeric child fields which is usually great. What I need to do is a SUMIF so that a given row in the table is added to the total only if its checkmark field is checked. I am okay if I need to write a script to do the math but I don’t know where to put the script so that it responds to the checkmark click event. I would rather automate this if I can and not be required to manually fire a form level script.
So I am playing around with the following script:
record.setRecordColor(‘#ff0000’);
Based upon given conditions I set the color I want and it works. The problem is when no conditions are met I don’t know how to reset the record back to the default color it is given when it was created. Any ideas how to do this? Also I am unsure how the text color is being set as this function seems to set the background color.
In the Script Editor, the linked form should show up on the left as an option. If you double click on the name of the form, it will insert the field ID for the Link to Form field. You can then use record.getFieldValue with that field ID and it will give you an array of records that are linked.
If you look in the snippets at the bottom, there is a “child records loop” snippet. If you select a field from the child record and click on this, it’ll insert a premade loop for you that will iterate over all of the child records and also pull out the selected record.
On the other side of a 1:M, record.getFieldValue can be used with a Link From Form field (enabled via “Show Inverse Relationship”) to retrieve the parent form.