Add Sublists to a Suitelet (Build a Suitelet, Part 3)

NetSuite for Developers

With the ‘ui/serverWidget’ module, we can add custom sublists to our Suitelet page. In this tutorial, we will cover the basics of adding Suitelet sublists, as well as some helpful tips to help you along the way.

If you’re new to this mini-series about creating Suitelets, check out our first and second blog posts to catch up to speed!

Add a Sublist

Last week, we learned about using the ‘ui/serverWidget’ module to make a Suitelet resemble NetSuite’s native user interface with fields and buttons. Today, we cover the basics of adding custom sublists to a Suitelet.

Just like last time, we can add a sublist simply by customizing our variable, called “form,” that carries the Suitelet form. One of the methods we can use for customization is form.addSublist.

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

        var mySublist = form.addSublist({ // <—— HERE
            id : 'custpage_my_sublist',
            type : ui.SublistType.LIST,
            label : 'My Sublist'
        });

        context.response.writePage(form);

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

First, we created our form. Then we added a submit button to the form. After that we added a custom sublist and displayed the form to the user. Let’s talk in more detail about the addSublist method.

Method Parameters

According to the help docs, form.addSublist can take 4 parameters, three of which are required:

  • id” (required) — An internal id for the sublist.

    • IMPORTANT: Suitelet sublist and field IDs always must start with “custpage_” in the ID.
  • label” (required) — A label for the sublist.
  • type” (required) — The type of sublist. See below.
  • tab“(optional) — The tab the sublist lives under. “Main” by default.

The “Type” Parameter

There are 3 types of sublists we can use in scripting a Suitelet:

  • LIST (the most common and the static list you see in the NetSuite UI)
  • INLINEEDITOR (an editable sublist, like what you see when creating a Sales Order, for example)
  • EDITOR (a unique layout where you can click a line and edit each value above the sublist)

Add a Sublist Field

After this, we can add columns to our sublist with the sublist.addField method.

 mySublist.addField({
        id: 'custpage_date',
        type: ui.FieldType.DATE,
        label: 'Date'
    });

Add Multiple Sublists

In some cases, it is necessary to include multiple sublists on a Suitelet, like in the following example.

A Small Problem…

As simple as this seems, things can actually begin to get quite complicated behind the scenes. A problem arises when we have similar sublist columns between the two sublists. For example, we might want two sublists, called “Open Purchase Orders” and “Open Sales Orders,” with similar columns in both (transaction name, date, etc.). This is a problem because NetSuite will throw an error if there are duplicate identical sublist field IDs. For instance, if we have a column in sublist 1 with an ID of ‘custpage_date’ and then another column in sublist 2 with ‘custpage_date’ as well, our Suitelet will not work.

A “Small” Solution

Of course, we could just split the two sublists into separate functions and detail every field for each sublist, even though we essentially have the same columns between them. But just the thought should send an icy chill up your spine, since this violates the classic DRY principle of programming (Don’t Repeat Yourself!). We have to be creative with how to make this as concise as possible.

Here is a real life example where I attempted to avoid duplicating code in this case. There may be better ways to do this, but at least this can be a start towards helping us remain concise.

function createSublist(form, sublistName) {
        try {
            var sublistTitle = sublistName == 'printsublist' ? 'Items for Reprint' : 'Ignored Items'
            var sublist = form.addSublist({
                id: 'custpage_' + sublistName + '_price_change_label_printing', // <—— HERE
                type: ui.SublistType.LIST,
                label: sublistTitle
            });
            form.clientScriptModulePath = "SuiteScripts/sr_cli_add_buttons.js";
            sublist.addButton({
                id: 'custpage_' + sublistName + '_mybutton', // <—— AND HERE
                label: "Mark / Unmark All",
                functionName: (sublistName + "OnMarkAllButtonClick")
            });

            sublist.addField({
                id: 'custpage_' + sublistName + '_rec_print', // <—— HERE etc.
                label: 'Print',
                type: ui.FieldType.CHECKBOX
            });
            sublist.addField({
                id: 'custpage_' + sublistName + '_item_id',
                label: 'Item ID',
                type: ui.FieldType.TEXT
            });
            sublist.addField({
                id: 'custpage_' + sublistName + '_internal_item_id',
                label: 'Internal ID',
                type: ui.FieldType.TEXT
            });
            sublist.addField({
                id: 'custpage_' + sublistName + '_item_description',
                label: 'Description',
                type: ui.FieldType.TEXT
            });
            sublist.addField({
                id: 'custpage_' + sublistName + '_item_price',
                label: 'Item Price',
                type: ui.FieldType.CURRENCY
            });

            if (sublistName == 'printsublist') {
                var printField = sublist.addField({
                    id: 'custitem_' + sublistName + '_ignore_price_changed_printing',
                    label: 'Ignore for Reprinting',
                    type: ui.FieldType.CHECKBOX
                });
            }

            return sublist;
        } catch (e) {
            log.error('Error creating sublist - ' + e.name, e.message);
        }
    };

Don’t worry if you find this code challenging to understand. I essentially just pass a variable saying which sublist I am working with into each ID. This way, I can make my IDs dynamically and save space. Looking back at this, I would likely do some additional things to make it more concise, but perhaps we could discuss that in a future tutorial.

Conclusion

In this post we looked at creating Suitelet sublists with the ‘ui/serverWidget’ module. We’re not done yet though! We still need to figure out how to actually populate the sublist now that we have our basic structure.

At SuiteRep, we focus on all things NetSuite so you can focus on better business results. Contact us today to learn how we can partner with you.