How can you add a button to a record in NetSuite that can be used to trigger a process regardless of whether the record is being viewed or edited ?
Creating a button on a client script does have the problem where it can
only
be accessed when the record is in
EDIT
mode which doesn’t help when you want to trigger a process when the record is in
VIEW
mode.
How can you combat this issue in NetSuite?
User Event Script Buttons
Recently I had a project which required a button to be placed on the Customer record to generate an Estimate based on other linked records and fields. A requirement of the estimate generation was to display to the user warnings and errors if certain pieces of information were missing.
Due to this requirement, a client script was the best fit as it gave access to the
N/ui/message
and
N/ui/dialog
modules which allow you to check whether a user is ready to initiate a process and can provide specific issues on why the desired result was not produced.
Unfortunately, creating everything in a client script did not work as a client script has the limitation of its custom button being available only when the record is in
EDIT
mode. As users are creating records and inserting others at various times in the Customer creation process this functionality wouldn’t work.
Therefore, the only other option available was to create a
User Event Script
and to use the standard
beforeLoad
function which would create a button for the record and if clicked would call the client script function (all wasn’t lost on the code and time spent on the client script!).
Here’s how this all ended up coming together:
Create Client Script
First, create your client script. This doesn’t need to contain all the standard functions of a regular client script with
pageInit
,
fieldChanged
,
saveRecord
(etc) functions. You can just have it contain the functions you would like for the script to run when the button is clicked.
Here’s how this could look:
The above client script imports a few libraries, namely the
N/record
,
N/ui/message
and the
N/url
modules.
The
N/record
is needed to help load the contents of the record being operated on to obtain all the necessary information to process.
(Another means is to pass all the values needed in the client script for the record – see the
fields
section further below as this can reduce the cost of using the
N/record
module by loading the record a second time.)
The
N/ui/message
is used to help warn the end user of insufficient or incorrect values satisfying the requirement mentioned previously.
And the
N/url
module is used to create a link to the resulting estimate record which the end user could click on if they needed to inspect it after its generation.
Notice also that the client script just exposes the sole function
createEstimate
within its record. This script will be uploaded into the File Cabinet but
will not have a subsequent Script Record
in NetSuite.
If somebody does try to create a script record from this client script in the File Cabinet they will be met with an abrupt error:
This should be deliberate by design as this client script separates it from the other standard client scripts that will operate on records directly as this one has other purposes.
Create User Event Script
Next create the User Event Script that will create the button on the record and then once uploaded create a NetSuite script record for this script.
Here’s an example of what I created:
This script uses the standard
beforeLoad
function and inside it contains a
try/catch
block to capture any problems.
Inside the
try/catch
I simply capture the internal id of the customer record and then create a button using the
form.addButton
method giving a unique name with prefix
custpage
and a label that the user will see on the record along with the name of the function.
Notice the function is written with a parameter (I inserted the
custId
value), be mindful if you do not have parentheses after the function name and you don’t provide a value to be passed to the client script nothing from this user event script is sent through.
Also, be mindful of what you are sending through. If you are sending something complex try to wrap everything into a JavaScript object and use
JSON.stringify(obj)
. In my case I just sent through the
id
of the record the user is viewing.
Lastly, you then need to point to where the client script is located using a path string, or if you prefer you could swap out this line for the following if you happen to know the internal id of the client script file in the File Cabinet:
context.form.clientScriptFileId = 123456;
Once you’ve uploaded the script you will need to create a User Event Script Record in NetSuite and you need to Deploy the script on the records you want it loaded.
In my case it was attached to the
Customer
record.
Once the script record is created you can then hop on over to your record and you should see your new shiny button, which once clicked will invoke the process you have connected in the client script.
Easy!
How To Get
fields
Property of Record In User Event
beforeLoad
One other aspect I came across when accessing the fields of a record is that should you try to access these values using
context.newRecord.fields.subsidiary
(for example) it doesn’t capture the variable value, even though when you inspect the
context.newRecord
through
log.debug
you can see the property exists.
A way around this is to
JSON.stringify(o)
the
context.newRecord
object and then to
JSON.parse(s)
the stringified object to return it to a Javascript object. This seems to expose the
fields
property of the record.
Here’s how this looked:
const beforeLoad = (context) => {
try {
const r = JSON.parse(JSON.stringify(context.newRecord));
const custId = r.id;
const subId = r.fields.subsidiary;
context.form.addButton({
id: "custpage_customer_create_estimate",
label: "Create Estimate",
functionName: `createEstimate(${custId},${subId})`
});
context.form.clientScriptModulePath = "SuiteScripts/XYZ/cs_create_estimate.js";
} catch(e) {
log.debug({title: 'UE Error', details: e});
}
}
As you can see from the above code the
context.newRecord
object is wrapped by the
JSON.stringify()
function which is then wrapped with the
JSON.parse()
function to transform the string back into an object.
Upon adding this line I was able to access the
subsidiary
field on the record which I could then subsequently pass through to the client script as a second parameter.
Here’s how the updated client script looked:
As you can see from the above refactored client script I removed the
N/record
module as all values needed from the original Customer record for the client script are passed through as parameters into the
createEstimate
function. This negates the need of loading the record a second time and reduces the governance cost of your script.
In addition, I added a new second parameter
subId
to capture the subsidiary value needed from the Customer record.
Summary
A button can be created on a record in NetSuite using both a custom client script and a user event script that points to the client script. By using the
form.addButton
method in the user event script as well as
form.clientScriptModulePath
(or
form.clientScriptFileId
) to direct which client script to run you can easily achieve what you need with a button that is available in
viewing
or
editing
modes.
Finally, if you do want to send through some parameters to your client script (as defined in the
functionName
property) remember to append a set of parentheses with your parameter values. If you don’t insert any parameters
nothing
will be passed through from the user event script to the client script.