Marty Zigman Marty Zigman
Prolecto Labs Accelerator Templates

Learn the NetSuite SuiteScript 2.0 Pattern to Add a Tab and a Sublist

NetSuite Technical



This article is relevant if you need a NetSuite SuiteScript 2.0 code example to dynamically add a Tab and a Sublist to an existing form.

Background

For one of our clients, we were asked to lead them in the implementation of NetSuite’s Electronics Payments bundle.  The software bundle is fairly locked down for modifications.  In our client’s situation, they sought to have custom batch approval features surrounding electronic payment generation and distribution.

On the provided forms, there was no way to use the point-and-click customization system to add a form and a sublist. So we took matters into our own hands and wrote a script to dynamically generate the tab and the sublist.

Sample NetSuite SuiteScript 2.0 to Create Tab and Sublist

One of our technical consultants, Alex, wrote the following code.  I reviewed it and cleaned it up a bit so that the pattern can help you in your SuiteScript development.  See the related image for how the result came out. Good work Alex!

 

//NetSuite SuiteScript 2.0 function called during the BeforeLoad event
function AddSublist(Context) {
	//create a custom tab to hold our Batch Approver Details
	var tab = Context.form.addTab({ id : 'custpage_batch_approval' ,label : 'Batch Approval Details' });
	
	//get the approval role from a deployment parameter
	var param_BatchApprovalRole = objCurrScript.getParameter({ name:'custscript_btx_batch_approval_role' });
	
	// for the Batch Approver role we want to make the TAB we are adding the first tab on the form
	// here we tell NetSuite to ‘insert’ our tab in front of an existing tab on the form which happens to have the ID ‘custom27’
	// the tab is already on the form, this really moves it rather than inserts it

	if (runtime.getCurrentUser().role == param_BatchApprovalRole) {
		 Context.form.insertTab({tab:tab ,nexttab:'custom27'});
	}


	// add a new custom field to the new TAB before adding the sublist
	var Owner = Context.newRecord.getText('owner');
	var fldOwner = Context.form.addField({ id:'custpage_owner' ,type:ui.FieldType.TEXT ,label:'Batch Owner' ,container:'custpage_batch_approval' });
	fldOwner.defaultValue = Owner;

	// add the custom SUBLST to the TAB
	var objSublist = Context.form.addSublist( {id: 'custpage_sublist1' ,type:ui.SublistType.LIST ,label: 'sublist1' ,tab:'custpage_batch_approval' });

	// run a saved search to get the data for the sublist
	// using a saved search allows sublist columns and data to dynamically be added/removed without modifying the script

	//get saved search via deployment parameter
	var param_SavedSearchId = objCurrScript.getParameter({ name:'custscript_bt_ue_pfa_saved_srch_id' });
	var objSublistSearch = search.load({ id: param_SavedSearchId });

	//in our use case, we want to add another filter to the saved search based on joining to a specific field that is this record's ID
	var fltrPFA = search.createFilter({ name:'custbody_9997_pfa_record' ,join:'applyingtransaction' ,operator:'ANYOF'  ,values:Context.newRecord.id  });
	objSublistSearch.filters.push(fltrPFA);

	
	var SublistSearch = objSublistSearch.run();
	var SublistSearchResults = SublistSearch.getRange(0, 1000);

	//add the columns to the sublist based on the search results, columns with label “nodisplay” are not added to sublist; note:
	//“nodisplay” allows columns we don’t want to see on the form to be in the search results for purposes such as sorting the results in a desired sequence

	//dynamically define the column list based on the saved search definition 
	var c = 0;
	SublistSearch.columns.forEach(function(col){
		c++;
		var colName = 'custpage_col' + c;
		if (col.label != 'nodisplay') {
			objSublist.addField({ id:colName ,label:col.label ,type: serverWidget.FieldType.TEXT });
		}
	});


	//now add rows to the sublist based on the search results, columns with label “nodisplay” are not added to sublist
	//only fill the first 1,000 rows based on early saved search work: do more crafty work if needed
	for (var ix = 0; ix < SublistSearchResults.length; ix++) {
		var result = SublistSearchResults[ix];                   
		var c = 0;
		
		//loop through the columns to fill the data
		for (var k in result.columns) {
			 
			c++;
			var colName = 'custpage_col' + c;                     

			if (result.columns[k].label != 'nodisplay') {
				var fieldValue;
				if ( result.getText(result.columns[k]) ){
					fieldValue = result.getText(result.columns[k]) 
				} else { 
					fieldValue = result.getValue(result.columns[k]) 
				};
				
				if (!fieldValue) { 
					fieldValue = ' '; 
				}
				//add the value to the row / column
				objSublist.setSublistValue({ id:colName ,value:fieldValue ,line: ix });
			}
		 } // where am I? for (var k in result.columns)
	} // where am I? for (var ix = 0; ix < SublistSearchResults.length; ix++)
}

Work with a Great Team of NetSuite Professionals

If you are savvy with the NetSuite business platform, independent-minded, creative, and have strong analytical capacities, perhaps you would like to join a team of professionals that hold high standards for care and ethics? Let’s have a conversation.

Marty Zigman

Holding all three official certifications, Marty is regarded as the top NetSuite expert and leads a team of senior professionals at Prolecto Resources, Inc. He is a former Deloitte & Touche CPA and has held CTO roles. For over 30 years, Marty has produced leadership in ERP, CRM and eCommerce business systems. Contact Marty to set up a conversation.

More Posts - Website - Twitter - Facebook - LinkedIn - YouTube

About Marty Zigman

Marty Zigman

Holding all three official certifications, Marty is regarded as the top NetSuite expert and leads a team of senior professionals at Prolecto Resources, Inc. He is a former Deloitte & Touche CPA and has held CTO roles. For over 30 years, Marty has produced leadership in ERP, CRM and eCommerce business systems. Contact Marty to set up a conversation.

Biography • Website • X (Twitter) • Facebook • LinkedIn • YouTube

11 thoughts on “Learn the NetSuite SuiteScript 2.0 Pattern to Add a Tab and a Sublist

  1. Brent says:

    I am doing something very similar, but I can’t figure out how to access the sublist on afterSubmit so I can save any changes or added lines as new records in system. When I try to access the newly created sublist using: context.newRecord.getSublist({sublistId: ‘custpage_sublist_1″}); it throws as error saying I am missing required parameter ‘sublistId’. I have debugged it all, the parameter is most definitely present. Is this a bug in Netsuite or is this just the completely wrong way to save changes and additions to a custom sublist?

  2. Marty Zigman says:

    Brent,

    That’s a good question. I generally would not think that aftersumbit would work that way. Are you instead loading the record again and then working it in memory (never considered a good practice because of the performance hit by the way)? You can’t modify the aftersubmit record but you can the beforesubmit.

    Marty

  3. Paul Haigh says:

    I love this pattern. It separates the coupling between the saved search and the GUI meaning you can update the saved search without having to redeploy.
    I also love that as an organisation you share code like this strategically and see the business benefit in helping others help themselves. There seems to be an underlying ethos of keeping it close to the chest in the Netsuite dev. world.
    Between yourself and Mr Eric T Grubaughs excellent videos you have made my transition into Netsuite development manageable.
    Thankyou

  4. Marty Zigman says:

    Thank you Paul. If we can give you our tools to help you be more productive, let’s have a conversation.

    Marty

  5. Kevin Patterson says:

    What is the easiest way to add a Customer Sublist (but filtered on a unique text field). I think Netsuite only allows the filtering on a List/Record – would this approach work to created the sublist or is there an easier way to do this? Thanks.

  6. Marty Zigman says:

    Kevin,

    The cut-and-paste custom sublist doesn’t key well on text inputs. But this pattern of using a script will allow you to produce that sublist.

    Marty

  7. AkberAlwani says:

    Hello Marty,
    Need your help.
    I setup the Suilet with 3 input fields, and 2 sublist with Tab control.
    1 Client script is setup which get the fieldChange the input parameter and then fill the sublist.
    I spend too much time but data seems not filling up in Sublist, after commitline I get an error that that typeerror

    rec.insertLine({“sublistId”: “custpage_item_assembly”, “line”: counter});
    rec.selectLine({ sublistId: ‘custpage_item_assembly’, line: counter});
    rec.setCurrentSublistValue({sublistId: ‘custpage_item_assembly’, fieldId: ‘sublist1’, value: internalid,ignoreFieldChange: true});
    rec.setCurrentSublistValue({sublistId: ‘custpage_item_assembly’, fieldId: ‘sublist2’, value: itemid,ignoreFieldChange: true});
    rec.setCurrentSublistValue({sublistId: ‘custpage_item_assembly’, fieldId: ‘sublist3’, value: displayname,ignoreFieldChange: true});
    rec.setCurrentSublistValue({sublistId: ‘custpage_item_assembly’, fieldId: ‘sublist4’, value: salesdescription,ignoreFieldChange: true});
    rec.setCurrentSublistValue({sublistId: ‘custpage_item_assembly’, fieldId: ‘sublist5’, value: unitstype,ignoreFieldChange: true});

    rec.commitLine({sublistId: ‘custpage_item_assembly’});
    rec.save(); //try removing this also

    counter is set as 0

  8. Marty Zigman says:

    Thank you Akber for reaching out for a private conversation at: https://www.prolecto.com/services/innovations/

  9. Slava says:

    Hello Marty,
    Unfortunately I found your post after I spent couple of days to found out solution by myself (I was surprised that it was exactly like yours 🙂 ).
    I faced with another issue. I have some fields where I want to keep both value and text (like posting period, currency, customer……). Fortunately, search result returns those field like object {text,value}.
    The question is, if it is possible to add object to text field (or maybe field need to be with other display type) – in UI user will see the text, but when need I could fetch value from the same field (like sublist which was added via UI with saved search).
    I understand that I can create two columns (one visible for text, and second hidden for value), but I was wondering if there is more simple solution for it.

  10. Maria says:

    hi! i always get an unexpected error when trying to insert the tab right next to an existing custom subtab (not created via script). what i’m trying to achieve is to add a subtab with a sublist using suitescript in between custom subtabs (created via suitebuilder) in a project record.

  11. Marty Zigman says:

    Hello Maria,

    We find that script may be the only way to get control over tab placement. Else, we are subject to whims of the point-and-click customization capabilities.

    Marty

Leave a Reply

Your email address will not be published. Required fields are marked *