24 How do I add a Button to a Record?
Created: November 8, 2018
This is definitely a question I see A LOT! How do we add a button to a record form? We actually have a few options as SuiteScript developers, so let's see how this works.
Add Button via 2.0 Client Script (Edit only)
SuiteScript 2.0 added a very simple way to add new buttons to forms, but that simplicity carries some limitations as well.
If we take a brief step back, we know that if we're making a button, that means we are going to have a user who is working in the user interface. The page is going to load, our button is going to display, and at some point after that, the user will click the button. When they do, we need some code loaded on the page ready to respond to that click.
The only Script type we have for responding to user interactions in the UI like that is a Client Script, so we start by creating one of those.
define([], function () {
/**
* Provides click handler for custom button on Employee
*
* @exports ess/add-button/cl
*
* @copyright 2018 Stoic Software, LLC
* @author Eric T Grubaugh <eric@stoic.software>
*
* @NApiVersion 2.x
* @NScriptType ClientScript
* @appliedtorecord employee
*/
var exports = {};
function pageInit(context) {
// TODO
}
exports.pageInit = pageInit;
return exports;
});
That's all we're going to do with the code right now; create and deploy this Client Script to the Employee record. Once that's done, you should see a Buttons sublist on the Scripts subtab of your Script record. This is the first method of adding Buttons to our records.
Using this sublist, add a row for your button, giving it a Label and the name of
a function to execute when the button is clicked. I've gone
with onButtonClick
. I always prefix my custom event handlers with on
. That's
a naming scheme I picked up a long time ago, but it's not mandatory so name the
function whatever you'd like.
Back in our Client script code, we need to actually build that function now. What is going to happen when the user clicks our button? For this example, we'll stick to something simple and just pop up a message for them.
We start by adding our function with the same name as we specified in the Script record.
define([], function () {
/**
* Provides click handler for custom button on Employee
*
* @exports ess/add-button/cl
*
* @copyright 2018 Stoic Software, LLC
* @author Eric T Grubaugh <eric@stoic.software>
*
* @NApiVersion 2.x
* @NScriptType ClientScript
* @appliedtorecord employee
*/
var exports = {};
function pageInit(context) {
// TODO
}
function onButtonClick() {
// TODO
}
exports.pageInit = pageInit;
return exports;
});
Now because our function lives inside a NetSuite module, just like any other
entry point, it can leverage other NetSuite modules. For displaying our message,
let's leverage NetSuite's N/ui/dialog
module.
define(["N/ui/dialog"], function (dialog) {
/**
* Provides click handler for custom button on Employee
*
* @exports ess/add-button/cl
*
* @copyright 2018 Stoic Software, LLC
* @author Eric T Grubaugh <eric@stoic.software>
*
* @NApiVersion 2.x
* @NScriptType ClientScript
* @appliedtorecord employee
*/
var exports = {};
function pageInit(context) {
// TODO
}
function onButtonClick() {
dialog.alert({
title: "Hello",
message: "You clicked the button!"
});
}
exports.onButtonClick = onButtonClick;
exports.pageInit = pageInit;
return exports;
});
Make sure you add the click handler function to the output of our module as we did with
exports.onButtonClick = onButtonClick;
If you do not do this, your click handler function will not be available for the
browser to call, and you will see an error in the developer console
like custommodule.onButtonClick is not defined
when you click the button.
Upload your changes and open an Employee record in the UI.
The first thing you should notice is that our button does not display in View mode. This is the major limitation of adding a button with this method. Because the button is being added by a Client Script, and because NetSuite only loads Client Scripts when a record is being edited, our button does not show up in View mode.
We'll learn how to get around that shortly. For now just Edit the Employee. You should see and be able to click your button.
There's our message. We now have a working custom button! If you only ever need a button to show up in Edit mode, then you're all done!
Add Button via User Event
The second method for adding a button is far more flexible but does add a little more code.
Adding a button is effectively a modification to the Form object in the user interface. We want to make that modification before the form loads, before the user sees it. There are two possible entry points we know about that run before the page loads:
- Client Script
pageInit
- User Event
beforeLoad
As we just stated, however, Client Scripts do not run in View mode, so
automatically pageInit
is out. We must make a new User Event with
a beforeLoad
entry point.
define([], function () {
/**
* Adds custom button to Employee record
*
* @exports ess/add-button/ue
*
* @copyright 2018 Stoic Software, LLC
* @author Eric T Grubaugh <eric@stoic.software>
*
* @NApiVersion 2.x
* @NScriptType UserEventScript
*/
var exports = {};
/**
* beforeLoad event handler
*
* @gov 0
*
* @param context
* {Object}
* @param context.newRecord
* {record} The new record being loaded
* @param context.type
* {UserEventType} The action type that triggered this event
* @param context.form
* {form} The current UI form
*
* @return {void}
*
* @static
* @function beforeLoad
*/
function beforeLoad(context) {
// TODO
}
exports.beforeLoad = beforeLoad;
return exports;
});
Once again, use this source file to create a new User Event script and deploy it to the Employee record.
Note in the comments for beforeLoad that we get passed a reference to the UI Form Object via the context argument; you can also find this information in the Help page for beforeLoad.
We can leverage the Form Object's addButton method to create our button. The properties will look the same as when we specified it in the UI.
define([], function () {
var exports = {};
function beforeLoad(context) {
context.form.addButton({
id: "custpage_mybutton",
label: "Click Me!",
functionName: "onButtonClick"
});
}
exports.beforeLoad = beforeLoad;
return exports;
});
It's a best practice to prefix the IDs of our custom UI components with custpage_, so we'll do that here. We still need a way to get our Client Script to load on the Form in View mode. To do so, we can leverage the Form Object's clientScriptModulePath property, setting it to the fully qualified path of our Client Script source file.
define([], function () {
var exports = {};
function beforeLoad(context) {
context.form.addButton({
id: "custpage_mybutton",
label: "Click Me!",
functionName: "onButtonClick"
});
context.form.clientScriptModulePath = "SuiteScripts/learn-suitescript/ss2-add-button/ess_emp_clickHandler.js";
}
exports.beforeLoad = beforeLoad;
return exports;
});
This forces our Client Script to be loaded whenever this User Event runs, which will include View mode. You may of course have a different path and file name, depending on where you uploaded your source file in the File Cabinet.
If you forget this step, or you have the wrong path, you will see the very same "custommodule.onButtonClick is not defined Error" in the browser console.
Upload your script changes, open up an Employee record in View mode, and you should see that everything is now working.
With the User Event, you have more flexible control over which Event Types will display your Button. You can either use the context.type property of beforeLoad to conditionally add the button in certain contexts, or use the Event Type field on the User Event's Deployment record.
Conclusion
And there we go! We've now seen two different ways to successfully add a custom button to a record. The first way through a Client script is fast but limited. The User Event option gives us more control but adds more code. It's up to you which method best suits your situation.