How to Read Suitelet Sublist Values After a POST
Use ServerRequest.getLineCount and getSublistValue to process submitted Suitelet rows, with notes on validation, checkboxes and NetSuite’s raw sublist encoding.
A Suitelet can render an editable sublist during GET, but the server still needs to recover those rows when the user submits the form.
The most reliable solution is not to parse request.parameters manually. NetSuite provides two request methods for this job:
ServerRequest.getLineCount()returns the number of submitted lines.ServerRequest.getSublistValue()returns one field value from one line.
Together, they turn the POSTed sublist back into predictable row objects.
Build the sublist during GET
This example creates a small list of invoices from which a user can select rows:
function buildForm(serverWidget) {
const form = serverWidget.createForm({
title: 'Select Invoices',
});
const lines = form.addSublist({
id: 'custpage_invoices',
type: serverWidget.SublistType.LIST,
label: 'Invoices',
});
lines.addMarkAllButtons();
lines.addField({
id: 'custpage_selected',
type: serverWidget.FieldType.CHECKBOX,
label: 'Process',
});
lines.addField({
id: 'custpage_internalid',
type: serverWidget.FieldType.TEXT,
label: 'Internal ID',
}).updateDisplayType({
displayType: serverWidget.FieldDisplayType.HIDDEN,
});
lines.addField({
id: 'custpage_reference',
type: serverWidget.FieldType.TEXT,
label: 'Reference',
});
form.addSubmitButton({ label: 'Process selected' });
return form;
}
Populate the sublist with setSublistValue() before calling response.writePage(form).
Read every submitted line during POST
Use the same sublist and field IDs that were used to construct the form:
function readSubmittedRows(request) {
const group = 'custpage_invoices';
const count = request.getLineCount({ group });
const rows = [];
for (let line = 0; line < count; line += 1) {
rows.push({
selected: request.getSublistValue({
group,
name: 'custpage_selected',
line,
}) === 'T',
internalId: request.getSublistValue({
group,
name: 'custpage_internalid',
line,
}),
reference: request.getSublistValue({
group,
name: 'custpage_reference',
line,
}),
});
}
return rows;
}
Checkbox values arrive as strings, normally 'T' or 'F', so convert them explicitly rather than relying on JavaScript truthiness. The string 'F' is truthy.
Complete GET and POST flow
function onRequest(context) {
if (context.request.method === 'GET') {
const form = buildForm(serverWidget);
populateInvoices(form.getSublist({ id: 'custpage_invoices' }));
context.response.writePage(form);
return;
}
const selectedRows = readSubmittedRows(context.request)
.filter((row) => row.selected);
processInvoices(selectedRows);
context.response.write(`Processed ${selectedRows.length} invoice(s).`);
}
Oracle’s Suitelet examples use the same pattern: obtain the line count, loop from zero, and retrieve each cell with getSublistValue().
Do not trust hidden IDs merely because they came from your form
POSTed fields are user-controlled input. Before changing records:
- Convert internal IDs to the expected type.
- Reject missing or malformed values.
- Load or search the referenced record again.
- Confirm the current user is allowed to act on it.
- Recalculate important amounts on the server.
A hidden field prevents casual editing in the UI; it does not make the value authoritative.
Why sublist data sometimes looks like control characters
When inspecting the raw request parameters, Suitelet sublist data may appear as concatenated text using control characters:
| Character | Meaning observed in raw payloads |
|---|---|
\u0001 |
Separates fields within a row |
\u0002 |
Separates rows |
That encoding is useful when diagnosing a form submission or integrating with old utility code. It should not be the default parsing strategy when getLineCount() and getSublistValue() are available.
Manual splitting depends on field order and undocumented payload details. The request APIs state the intent directly and are much easier to maintain.
Common mistakes
- Using a field ID that differs from the one added to the sublist.
- Treating
'F'as false without comparing the string. - Reading only rows the browser happened to display instead of using the submitted line count.
- Assuming an empty string, zero and a missing value are interchangeable.
- Trusting submitted record IDs or amounts without server-side validation.
Keep the sublist ID and field IDs in shared constants when the form grows. That eliminates an entire class of spelling and refactoring errors.
Record sublists use a different API from serverWidget sublists. For N/record examples, see SuiteScript Standard vs Dynamic Mode: Which Sublist APIs to Use.