SuiteScript : UI Rendering With serverWidget

While there are methods for implementing a modern single page application (SPA) framework into SuiteScript (there are some examples where people have grafted React into their Scriptlets), there are some advantages to using Oracle’s useful, if somewhat anemic, serverWidget library to render the user interface for your app.

Note: Like other NetSuite related posts on this blog, you’ll need to be logged into your NetSuite developer account to be able to access some of the SuiteScript documentation links.

serverWidget.List Objects

These are useful for creating Netsuite looking tables withing your applet. However there are some tricks to keep in mind. Let’s start with the basics.

Setting up the list

  • start with serverWidget.createList() to create your list object, it helps to set a title
  • set the list style to make it all “Netsuite fancy” with something like list.style = serverWidget.listStyle.REPORT
  • add some columns with the list.addColumn() method
  • load up some rows, the fastest way is the list.addRows() married to a N/Search result array

Here is an example WITHOUT the N/Search call that loads up the data array:

       /**
         * Defines the Suitelet script trigger point.
         * @param {Object} scriptContext
         * @param {ServerRequest} scriptContext.request - Incoming request
         * @param {ServerResponse} scriptContext.response - Suitelet response
         *
         * @var {search.Result[]} onlineOrders
         * @var {serverWidget.List} list
         */
        const onRequest = (context) => {
            // -- Fetch online orders
            const onlineOrders = fetchOnlineOrders();

            const list = serverWidget.createList( { title: 'Web Orders' });
            list.style = serverWidget.ListStyle.REPORT;
            list.addColumn( { id: 'id', label: 'ID', type: serverWidget.FieldType.INTEGER });
            list.addColumn( { id: 'tranid', label: 'TxID', type: serverWidget.FieldType.INTEGER });
            list.addColumn( { id: 'entity', label: 'Customer', type: serverWidget.FieldType.INTEGER });
            list.addColumn( { id: 'trandate', label: 'Date', type: serverWidget.FieldType.DATE });

            list.addRows( { rows: onlineOrders } );

            // Output header
            context.response.setHeader({
                name: 'D2C-Testlet',
                value: 'D2CTestlet'
            });

            context.response.writePage(list);

        }

Now is a good time to touch on one of the … let’s call it a nuances… of SuiteScript.

If you want to match your columns for the list object to your search results object, USE LOWERCASE (ironic that is in uppercase).

You will get plenty of generic non-descript error messages back from Oracle SuiteScript if you try to do anything fancy. You know… fancy things like matching the column ID in your addColumn() definition to the actual case that comes back in the search.Result record. For example, try list.addColumn( { id: ‘recordType’, label: ‘Type’, type: serverWidget.FieldType.TEXT } ) in your code and execute will barf with an “invalid ID, it must be unique” error message.

In reality it just cannot have anything but lowercase letters or numbers in the ID.

Despite the search.Result object literally having a property of ‘recordType’ not ‘recordtype’. Which is even more interesting when you realize explicit object keys in JavaScript are case sensitive. But keep in mind this is NOT JavaScript. It is kind of JavaScript but not. There are special things that make it “SuiteScript” that you need to keep track of.

serverWidget Forms

Forms are generally designed to mimic standard HTML forms, however they have some advantages over lists. You can, for example, add an inline HTML element that allows you to do things like add a <script> tag to your page. This can be an easy way to load third party JavaScript resources, like Google Maps, that do not distribute a standard Node library or allow the scripts to be pulled from a CDN.

The Netsuite Forms widget also allows for sublists. These present a similar data presentation to the full-blown serverWidget Lists object noted above, but with a number of limitations over the full list. That is unfortunate as a standard NetSuite list within a form would be very useful and reduce code clutter. You’ll find other article on this site about how to get that working including the manual overhead required to manage a Form Sublist that is not required with top-level NetSuite Lists.

Loading a script on a form

Here is a simple example that loads Google Maps JavaScript API onto a Netsuite form. You’ll need to craft your own URL for the GoogleMapAPIURL variable shown here, based on what the Google Developers console tells you.


        const nsForm = serverWidget.createForm( { title: 'D2C Commission Report' } );

        // Add the Google Maps Script so we can invoke it later.
        nsForm.addField({
            id: 'gmapscript',
            type: serverWidget.FieldType.INLINEHTML,
            label: 'Google Maps Script:',

        })
            .updateLayoutType({
                layoutType: serverWidget.FieldLayoutType.OUTSIDEABOVE
            })
            .defaultValue = `<script defer type="text/javascript" src="${GoogleMapAPIURL}"  ></script>`;

Store Locator Plus® on NetSuite

Or how about putting a Store Locator Plus® location finder map on your NetSuite form? Login to your Store Locator Plus® account and go to “Generate Embed” then past the script into a NetSuite INLINEHTML element like this:

        const nsForm = serverWidget.createForm( { title: 'D2C Commission Report' } );
        //nsForm.clientScriptFileId = nsSupportingScriptID;

        nsForm.addField({
            id: 'gmapscript',
            type: serverWidget.FieldType.INLINEHTML,
            label: 'Google Maps Script:',
        })
            .updateLayoutType({
                layoutType: serverWidget.FieldLayoutType.OUTSIDEABOVE
            })
            .defaultValue = `
                <script id='MySLP' type='text/javascript' 
                    src='https://dashboard.storelocatorplus.com/front-end/location.min.js' 
                    data-api-key='myslp.7125ee2a6ebc9503470888d2dc9803da6810f97779c63b7274ed42398cbb0efd' 
                    data-rest-path='//dashboard.storelocatorplus.com/icecream_at_slp_dot_guru/wp-json/myslp/v2/locations-map' 
                    data-div-id='MySLP-map-wrap' data-presentation='map'></script>`;
Store Locator Plus® in NetSuite

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.