Skip to content

Lesson 6. Writing an OnFieldState ruleset

Updated pdexter 2022-12-19

In this lesson, we are going to make an improvement on the laying out of our rules so far.

One of the more significant usages for having multiple rulesets called by a single event on a document is where we need to maintain fieldstates for our document.

"Field States" is the process/context in which the state of fields within a document depend on the values of other fields within the document.

Example:

When a checkbox field labeled "Requires Verification" is checked, then the fields labeled "Verification Details" and "To be verified by" should be enabled and made mandatory for saving the document.

OnFieldState is not actually a document event that we respond to with a ruleset; however it can be said that it is needed both in OnLoad, OnFieldChange and PostSaveClient.

Under the OnFieldChange event, we need to change the states of fields when another field it depends on is changed.

We also need to make the same changes under the OnLoad event. Even though we made changes under OnFieldChange in a previous browser session, those changes do not persist with the document over separate page sessions, so we need to reapply those changes when we load a document.

Step 1. Pretesting

  • Open an existing Rental Car document.
  • Enter a Decommissioned date; the field "Reason Decommissioned" appears.
  • Save the document.
  • Reload the document.

You will see that even though the Reason Decommissioned field was shown before, it is hidden now.

Step 2. Create a new Ruleset

  • Open the Ruleset Editor for a new Ruleset

https://your-formbird/form/224bc62858d73ce57a9cb85e

  • Set the name of the RuleSet : Acme Rental Car - OnFieldState

  • Group can be set to acme, or your organisation name

  • Save your new ruleset.

The script pane will show the following:

{
#include "JayRule Ruleset Overlay JS",

    ruleset : {
        name : 'Acme Rental Car - OnFieldState',

        ruleInitialise : {
            ruleCondition : true,

            ruleAction : function(ntf) {
            }
        }
    }
}
  • Link this ruleset to the "Rental Car" template, event "OnLoad", using the techniques described in Lesson 1. Double check with the template editor or the Ruleset Linker Overlay that the OnFieldState ruleset is second to the current OnLoad ruleset.

  • Link this ruleset to the "Rental Car" template, event "OnFieldChange", using the techniques described in Lesson 1. Double check with the template editor or the Ruleset Linker Overlay that the OnFieldState ruleset is second to the current OnFieldChange ruleset.

Step 3. Move any fieldstate rules from OnLoad and OnFieldChange to OnFieldState

  • Determine which rules in the OnFieldChange ruleset should be transferred to the OnFieldState ruleset.

For our example so far, those rules would be ruleShowReasonDecommissioned from the OnFieldChange ruleset, and ruleMandateMainFields from the OnLoad ruleset.

  • Take the rules ruleMandateMainFields and ruleShowReasonDecommissioned out of their respective rulesets, and copy them into the ruleset "Acme Rental Car - OnFieldState". Save the old rulesets.

Now that we are in a ruleset called by both OnLoad and OnFieldChange events, we need to modify our rules slightly to work.

  • Open the ruleset
  • Under rule ruleInitialise, ruleAction function, code the following:
ruleAction : function(ntf) {
    ntf.isOnLoad = !ntf.context.fieldChanged;
}

Here we are performing a little trick to determine if we are in OnLoad or OnFieldChange. OnLoad does not receive a value for ntf.context.fieldChanged, so if ntf.context.fieldChanged is a defined string, ntf.isOnLoad will be set to false; if ntf.context.fieldChanged is not defined, ntf.isOnLoad will be set to true.

ntf.isOnLoad will be set for the entire ruleset from now on.

nb : ntf.isOnLoad will be true also on the event PostSaveClient (as there was no field changed in this event). In general, this assumption will work within PostSaveClient.

  • Under the ruleCondition function for rule ruleMandateFields, change the code to:
ruleCondition : { 
    ntf : { isOnLoad : true }
}

So this rule will now only run when the document is loading (or reloading), not whenever a field is changed.

  • Under the ruleCondition function for ruleShowReasonDecommissioned, change the code to as follows:
ruleCondition : { 
    fieldChanged : ['ON_LOAD', 'decommissionedDate']
}

This tells the rule to run either on the document loading, or later when the field "decommissionedDate" has changed.

The fieldChanged 'ON_LOAD' value tells the rule to run when there is no fieldChanged value, that is, it is under the event OnLoad or PostSaveClient

The full ruleset should look as follows:

{
#include "JayRule Ruleset Overlay JS",

    ruleset : {
        name : 'Acme Rental Car - OnFieldState',

        ruleInitialise : {
            ruleCondition : true,

            ruleAction : function(ntf) {
                ntf.isOnLoad = !ntf.context.fieldChanged;
            }

        },

        ruleMandateMainFields : {
            ruleCondition : { 
                ntf : { isOnLoad : true }
            },

            ruleAction : function(ntf) { 
                var ft3 = ntf.scope;
                ft3.mandateField('carMake', true);
                ft3.mandateField('carModel', true);

                ft3.enableField('createdByUser', false);

                ft3.showField('reasonDecommissioned', false);
            }
        },

        ruleShowReasonDecommissioned : {
            ruleCondition : { 
                fieldChanged : ['ON_LOAD', 'decommissionedDate']
            },

            ruleAction : function(ntf) { 
                var ft3 = ntf.scope;
                // if decommissioned date is set, set flag true, else false
                var flag = ntf.document.decommissionedDate ? true : false;

                ft3.showField('reasonDecommissioned', flag);
            }
        }

    }
}

Step 4. Testing

  • Open a new or existing Acme Car Rental document. If already open, reload the page to refresh the ruleset in memory.

  • Select a date in the "Decommissioned Date" field.

  • The field "Reason Decommissioned" should be displayed.

  • Clear the date in "Decommissioned Date"

  • The field "Reason Decommissioned" should vanish.

  • Again, select a date in the "Decommissioned Date" field.

  • The field "Reason Decommissioned" should be displayed.

  • Save the document.

  • Reload the document.

  • The document should now open with the field "Reason Decommissioned" displayed.

If the above is true, you have successfully set up your OnFieldState ruleset!

Lesson Items covered

  • The OnFieldState ruleset concept
  • OnFieldState condition coding.
  • Use of multiple rulesets for a document event.
  • Sharing of common rulesets over multiple document events.