If you’re new to this mini-series on how to create a Suitelet, check out our first part of the series here!

How to Make Suitelets Look Like NetSuite

Suitelets are an incredibly powerful tool. Not only are they great for making completely custom pages in NetSuite (like our “Hello World” example), but they are even better for creating pages that look, smell, and operate like the native NetSuite we all know (and hopefully love!). So how do we do that? Let’s find out!

Simple Suitelet Structure

There are really only two parts of a Suitelet. I hope that sounds simple, because it really is. The two parts are called “Get” and “Post.” First, the Suitelet script “gets” something from the server. Then, once the page has been manipulated to a certain extent by the user, it then “posts” back the new information to the server. The server then can do certain tasks with that new information.

Explaining Get/Post

Here’s an analogy. Imagine that you work at a car mechanic shop.

  • GET: You send out an email to remind a client of their scheduled car maintenance. Once you get the car to your shop, it sits around in the parking lot until you get around to modifying it. When you bring the car in, you replace the tires, the oil, and even one of the tail lights.
  • POST: Once you’re finished and ready to return it to the customer, you decide to drive it to their house since they live right next door. They then assess the changes. They notice the beautiful new tires, the tail light, and the new oil change sticker. Based on the changes that they see, they do something (they pay you). This is what “post” is like.

Code Example

Here’s an example of what the Get and the Post look like in our code:

function onRequest(context) {
    if (context.request.method === 'GET') {
        // Write the page HERE!

    } else if (context.request.method === 'POST') {
        // Do stuff with posted information HERE!
    }
}

Notice that we checked the status of the request method in the context—context.request.method === 'GET'. In the second part, where we check if the context.request.method is ‘post,’ it is common to see simply an else statement without the specification of whether it is ‘post.’ This is because there are only two possibilities—’get’ or ‘post.’ If it’s not the one, it’s the other. But I personally like to be more specific for the sake of clarity.

Add Header-Level Buttons to a Suitelet

This is where things begin to get interesting. To be able to submit our Suitelet (essentially, drive the car back to the customer and get paid), we of course need to add a “submit” button! Thankfully, NetSuite already thought of this and gave us a unique button method for this purpose.

function onRequest(context) {
    if (context.request.method === 'GET') {
        var form = ui.createForm({ title: 'Hello World Suitelet' });
        
        form.addSubmitButton({ label: 'custpage_submit_button' }); // <—— HERE

        context.response.writePage(form);

    } else if (context.request.method === 'POST') {
        log.debug("Suitelet is posting.")
    }
}

In the “get” part, we create our form (ui.createForm), add a submit button (form.addSubmitButton), and write our page (context.response.writePage(form)). The “form” we created is something like a blank canvas we can manipulate in various NetSuite-ish ways. This is also when we need the “N/ui/serverWidget” module! Don’t forget to define it at the top of your script like this:

define(['N/ui/serverWidget'], function (ui) {

We can also add our own custom buttons using the “form.addButton” method. Because this is our own unique button, we must also specify a function that will be called when this button is clicked (a button is supposed to do something, after all).

form.addButton({
    id: 'custpage_say_hello',
    label: 'Say Hello!',
    functionName: 'sayHelloToUser'
});

But we have a problem. We have been building merely what displays on the page, all on the server side. How can we do something dynamically when the user interacts with the button? We can’t . . . unless we use a Client Script, of course! Thankfully, NetSuite has also thought of this and given us a special method:

form.clientScriptModulePath = 'SuiteScripts/hello_world_handler.js';

This method essentially provides a direct link to our client script (in this case called our Suitelet handler). This script will handle all the user interactions with the Suitelet page. Phew!

Once we create a basic client script to handle our Suitelet, we can just add the above method somewhere in the “get” part of the Suitelet. Then we’re good to go.

Add Body-Level Fields to a Suitelet

There are a number of different fields that can be used on a Suitelet. Here’s a list:

  • CHECKBOX
  • LONGTEXT
  • CURRENCY
  • MULTISELECT
  • DATE
  • PASSWORD
  • PERCENT
  • DATETIMETZ
  • PHONE
  • EMAIL
  • SELECT
  • FILE
  • RADIO
  • FLOAT
  • RICHTEXT
  • HELP
  • TEXT
  • INLINEHTML
  • TEXTAREA
  • INTEGER
  • TIMEOFDAY
  • IMAGE
  • URL
  • LABEL

As always, be sure to check the help documentation for more detailed information about all of these.

form.addField({
    id: 'custpage_test_field',
    label: 'Enter Hello...',
    type: ui.FieldType.TEXT,
});

When we’re all said and done, here’s what our script looks like:

define(['N/ui/serverWidget'], function (ui) {
    /**
     * Example Suitelet
     * 
     * @NApiVersion 2.x
     * @NScriptType Suitelet
     * @author Ben Rogol (SuiteRep)
     */
    var exports = {};

    function onRequest(context) {
        if (context.request.method === 'GET') {
            var form = ui.createForm({ title: 'Hello World Suitelet' });
            form.clientScriptModulePath = 'SuiteScripts/hello_world_handler.js';

            form.addSubmitButton({ label: 'Submit!' });

            form.addButton({
                id: 'custpage_say_hello',
                label: 'Say Hello!',
                functionName: 'sayHelloToUser'
            });
            
            form.addField({
                id: 'custpage_test_field',
                label: 'Enter Hello...',
                type: ui.FieldType.TEXT,
            });
    
            context.response.writePage(form);

        } else if (context.request.method === 'POST') {
            log.debug("Suitelet is posting.")
        }
    }

    exports.onRequest = onRequest;
    return exports;
});

We actually haven’t really done anything with the Post quite yet. We will likely talk about that in an upcoming blog post.

Here’s what our actual Suitelet shows:

Conclusion

This was a quick look at how Suitelets can resemble native NetSuite buttons and body-level fields. But there is definitely more that Suitelets can do! The best is yet to come. Stay tuned next week for when we look at the powerful sublist capability Suitelets provide!