Trigger a client script on a button clicked on a Suitelet? - netsuite

I am trying to update the values on a custom record based on the button clicked on a suitelet
This will have 3 or 4 different buttons.
There is only one set up page that can be loaded on click of the button.
For example, 'recurring' is clicked on the suitelet. This will load a custom record page and set the parameters.
If 'fortnightly invoice' button is clicked, this will also load the same custom record page and set the parameters.
Where I am getting stuck: I have a suitelet with the buttons that are designed to load the custom record by calling a client script function
Instead, as soon as the suitelet loads, the custom record page loads and is stuck in an infinite loop reloading again and again
This is my suitelet script:
/**
*#NApiVersion 2.x
*#NScriptType Suitelet
*/
define(["N/ui/serverWidget"], function (ui) {
var exports = {};
function onRequest(context) {
if (context.request.method === "GET") {
var form = ui.createForm({
title: "Consolidated Invoicing Type",
});
// form.clientScriptModulePath =
// "SuiteScripts/sdf_ignore/Consolidated Invoice Client Script.js";
form.clientScriptFileId = 2659;
form.addButton({
id: "recurring",
label: "Recurring",
functionName: "pageInit",
});
context.response.writePage(form);
} else if ((context.response.method = "POST")) {
log.debug({
title: "request method type",
details: "suitelet is posting",
});
}
}
exports.onRequest = onRequest;
return exports;
});
This is the client script:
/**
*#NApiVersion 2.x
*#NScriptType ClientScript
*/
define(["N/record", "N/runtime", "N/url"], function (
record,
runtime,
url
) {
/**
* #param {ClientScriptContext.pageInit} context
*/
function pageInit(context) {
var scriptObj = runtime.getCurrentScript();
var recordType = scriptObj.getParameter("custscript_ci_suitelet_record");
var pageUrl =
"https://tstdrv.app.netsuite.com/app/common/custom/custrecordentry.nl?rectype=143&id=1&e=T";
var url = new URL(pageUrl);
window.location.href = url;
}
return {
pageInit: pageInit,
};
});
Do I need to use another script type to set the values on the custom record? (i.e not a client script)
How would I link a userevent script to the suitelet so that it is triggered on button click?
Why would the client script be automatically initiated on loading the suitelet page if it is supposed to be tied to a button on the form?
Thanks

The page keeps reloading because the "pageInit" function in your client script will be executed automatically by Netsuite, because "pageInit" is a default Netsuite Entry function. If you just rename your function it will work:
On the Suitelet:
form.addButton({
id: "recurring",
label: "Recurring",
functionName: "executeRecurring",
});
On the client script:
/**
*#NApiVersion 2.x
*#NScriptType ClientScript
*/
define(["N/record", "N/runtime", "N/url"], function (
record,
runtime,
url
) {
/**
* #param {ClientScriptContext.pageInit} context
*/
function executeRecurring() {
var scriptObj = runtime.getCurrentScript();
var recordType = scriptObj.getParameter("custscript_ci_suitelet_record");
var pageUrl =
"https://tstdrv.app.netsuite.com/app/common/custom/custrecordentry.nl?rectype=143&id=1&e=T";
var url = new URL(pageUrl);
window.location.href = url;
}
function pageInit(context) { // you need to keep at least one Netsuite Entry function, otherwise you will get an error
}
return {
pageInit: pageInit,
executeRecurring: executeRecurring
};
});
Also if the parameter custscript_ci_suitelet_record is a parameter on the Suitelet script, then you won't be able to get its value on the client script, you must get the value on the Suitelet script and pass it as parameter during the button call:
Suitelet:
/**
*#NApiVersion 2.x
*#NScriptType Suitelet
*/
define(["N/ui/serverWidget", "N/runtime"], function (ui, runtime) {
var exports = {};
function onRequest(context) {
if (context.request.method === "GET") {
var form = ui.createForm({
title: "Consolidated Invoicing Type",
});
// form.clientScriptModulePath =
// "SuiteScripts/sdf_ignore/Consolidated Invoice Client Script.js";
form.clientScriptFileId = 2659;
var recordType = runtime.getCurrentScript().getParameter("custscript_ci_suitelet_record");
form.addButton({
id: "recurring",
label: "Recurring",
functionName: "executeRecurring('" + recordType + "')",
});
context.response.writePage(form);
} else if ((context.response.method = "POST")) {
log.debug({
title: "request method type",
details: "suitelet is posting",
});
}
}
exports.onRequest = onRequest;
return exports;
});
Client script:
/**
*#NApiVersion 2.x
*#NScriptType ClientScript
*/
define(["N/record", "N/runtime", "N/url"], function (
record,
runtime,
url
) {
/**
* #param {ClientScriptContext.pageInit} context
*/
function executeRecurring(recType) {
var pageUrl =
"https://tstdrv.app.netsuite.com/app/common/custom/custrecordentry.nl?rectype=" + recType + "&id=1&e=T";
var url = new URL(pageUrl);
window.location.href = url;
}
function pageInit(context) { // you need to keep at least one Netsuite Entry function, otherwise you will get an error
}
return {
pageInit: pageInit,
executeRecurring: executeRecurring
};
});

Related

Netsuite Print Button - "error.SuiteScriptError","name":"MISSING_PDF_PARAMETERS",

I have created a print button to print an advanced PDF from a sales order, so the client can get a commercial invoice generated. I have done this for other clients with success but I am running into an issue where the standard templates will print a pdf from the button but the customized ones will not. Where am I going wrong in the code here:
Suitelet:
function onRequest(context) {
var custom_id = context.request.parameters.custom_id;
var tempid = context.request.parameters.tempid;
log.debug("id", custom_id);
log.debug("id", context.request.parameters);
var pdfFileName = "Commercial Invoice";
var renderer = render.create();
var content = renderer.addRecord({
templateName: 'record',
record: record.load({
type: record.Type.SALES_ORDER,
id: custom_id
})
});
renderer.setTemplateByScriptId(tempid);
var pdfFile = renderer.renderAsPdf();
log.debug ("pdf", pdfFile)
context.response.writeFile(renderer.renderAsPdf(),true);
}
return {
onRequest: onRequest
}
});
Client Script:
function onButtonClick() {
var suiteletUrl = url.resolveScript({
scriptId: 'customscript_commercialinv_so_sl',
deploymentId: 'customdeploy_commercialinv_so_sl',
returnExternalUrl: true,
params: {
custom_id: currentRecord.get().id, tempid: "CUSTTMPL_109_4753601_SB1_795"
},
});
window.open(suiteletUrl,"_blank");
}
exports.onButtonClick = onButtonClick;
exports.pageInit = pageInit;
return exports;
});
My user script looks solid. I am getting this error when I direct the Client script to a custom template as referenced above:
{"type":"error.SuiteScriptError","name":"MISSING_PDF_PARAMETERS","message":"Missing parameters required to generate PDF","stack":["renderAsPdf(N/render)","onRequest(/SuiteScripts/MegWebb/cust_SOprinttemplate_SL.js:28)"],"cause":{"type":"internal error","code":"MISSING_PDF_PARAMETERS","details":"Missing parameters required to generate PDF","userEvent":null,"stackTrace":["renderAsPdf(N/render)","onRequest(/SuiteScripts/MegWebb/cust_SOprinttemplate_SL.js:28)"],"notifyOff":false},"id":"","notifyOff":false,"userFacing":false}
Any help would be much appreciated!

Submit button and Client script button conflicting on Suitelet. SS 2.0

i have 2 buttons on my suitelet form, Standard Submit Button and Client Script button. The submit button does not execute if i have the clientScriptModulePath in my suitelet code. once i remove the clientScriptModulePath , the submit button starts working. Anyone have any idea what could be the reason?
Suitelet:
function onRequest(context) {
log.debug('request type', context.request.method);
var form = serverWidget.createForm({ title: 'Item Search' });
if (context.request.method === 'GET') {
var rec_id = context.request.parameters.id;
log.debug('rec id', rec_id)
form.addButton({
id: 'custpage_btn_goback',
label: 'Go Back',
functionName: 'onBackButtonClick'
});
form.clientScriptModulePath = '../client/mx_itemsearch_filter_cs.js';
form.addSubmitButton({
label: 'Submit'
});
context.response.writePage(form);
}
else {
log.debug('POST', 'POST')
}
}
Client script function:
function onBackButtonClick() {//TODO:
try {
console.log('in back button')
var currRec = currentRecord.get();
var suiteletUrl = url.resolveScript({
scriptId: 'customscript_mx_itemsearch_sl',
deploymentId: 'customdeploy_mx_itemsearch_sl'
});
console.log(suiteletUrl)
window.open(suiteletUrl, '_self');
} catch (e) {
log.error({ title: fx, details: 'Error - Code: ' + e.code + ', Message: ' + e.message });
}
}
You need to add one valid client side endpoint function. The endpoint function can just be a blank function. Example
function pageInit (context) {};
The your client script should have export the client endpoint function and your custom function.
return { pageInit: pageInit, onBackButtonClick: onBackButtonClick};

Why is this Advanced PDF template not populating the terms from the object that I am passing to it?

So, basically I am trying to get the XML template for the PDF and I plan to eventually add some additional XML in the code after getting the template working in this manner. However, when I attempt to pass a data source object to the PDF it is not working. Does anyone know the cause of this issue, and what I am doing incorrectly here?
XML template (stripped out everything but the variable in the table for testing):
<?xml version="1.0"?><!DOCTYPE pdf PUBLIC "-//big.faceless.org//report" "report-1.1.dtd">
<pdf>
<!--removed lengthy head to make code more readable-->
<body footer="nlfooter" footer-height="20pt" padding="0.5in 0.5in 0.5in 0.5in" size="Letter">
<table class="body" style="width: 100%; margin-top: 10px;">
<tr>
<td>${jsonObj.terms}</td>
</tr></table>
</body>
</pdf>
Script:
/**
* #NApiVersion 2.x
* #NScriptType UserEventScript
* #NModuleScope SameAccount
*/
define(['N/error','N/render','N/file','N/record','N/log'],
/**
* #param {error} error
*/
function(error, render, file, record, log) {
function beforeSubmit(context) {
log.debug('After submitting invoice, create advanced PDF detail layout', context);
var isInvoice = context.newRecord.type == 'invoice';
// Create advanced PDF
if (isInvoice){
log.audit('Creating invoice');
renderRecordToPdfWithTemplate(context.newRecord);
}
else{
error.create({
name: 'ERROR_RECEIVED',
message: 'Cannot create advanced PDF from this record type'
});
log.audit(error.name,error.message);
}
}
return {
beforeSubmit: beforeSubmit
};
function renderRecordToPdfWithTemplate(context) {
var jsonObj = {
terms: "test terms"
};
var templateId = '7959'; // ID of the XML
var templateFile = file.load({id: templateId});
var renderer = render.create();
renderer.templateContent = templateFile.getContents();
/*
renderer.addRecord({
type: record.Type.INVOICE,
record: context
});
*/
renderer.addCustomDataSource({
format: render.DataSource.OBJECT,
alias: "jsonObj",
data: jsonObj
});
log.debug('Rendering as PDF');
var renderXmlAsString = renderer.renderAsString();
log.debug('Added record to PDF', context);
var invoicePdf = render.xmlToPdf({
xmlString: renderXmlAsString
});
invoicePdf.name = 'Testpdf2.pdf';
invoicePdf.folder = -15;
try{
var fileId = invoicePdf.save();
log.debug('Saved PDF to file '+fileId);
}
catch(e){
alert('Error saving file');
log.debug('Error saving file');
debugger;
}
}
});
You don't need the renderer.renderAsString(); since you're already loading the XML from the file cabinet.
function renderRecordToPdfWithTemplate(context) {
var jsonObj = {
terms: "test terms"
};
var templateId = '7959'; // ID of the XML
var templateFile = file.load({id: templateId});
var renderer = render.create();
renderer.templateContent = templateFile.getContents();
renderer.addCustomDataSource({
format: render.DataSource.OBJECT,
alias: "jsonObj",
data: jsonObj
});
log.debug('Rendering as PDF');
var invoicePdf = renderer.renderAsPdf();
invoicePdf.name = 'Testpdf2.pdf';
invoicePdf.folder = -15;
try{
var fileId = invoicePdf.save();
log.debug('Saved PDF to file '+fileId);
}
catch(e){
alert('Error saving file');
log.debug('Error saving file');
debugger;
}
}

Netsuite, update value and save record

I want to edit a record, then click "Save" and the field "custitem_con" to be updated with a new value and the record saved.
/**
*#NApiVersion 2.0
*#NScriptType ClientScript
*/
define(['N/currentRecord'],
function(currentRecord) {
function saveRecord (){
var objRecord = currentRecord.get();
var con = 'Success!...but record is not saved :(';
objRecord.setValue({
fieldId: 'custitem_con',
value: con,
});
}
return {
saveRecord: saveRecord
};});
However while the field custitem_con gets the value, the record is not saved, but remains in edit mode. How do I get the record saved?
In order to allow the record to be submitted, you need to return true from the saveRecord() function, thus:
/**
*#NApiVersion 2.0
*#NScriptType ClientScript
*/
define(['N/currentRecord'],
function(currentRecord) {
function saveRecord (){
var objRecord = currentRecord.get();
var con = 'Success!...but record is not saved :(';
objRecord.setValue({
fieldId: 'custitem_con',
value: con,
});
return true;
}
return {
saveRecord: saveRecord
};});

Creating form in netsuite using suitscript 2.0

var formData = new FormData();
formData.append("name", "John");
formData.append("age", "31");
for (var value of formData.values()) {
log.debug(value);
}
but when i want to log form values using formData api. It's giving below error.
ReferenceError: "FormData" is not defined.
FormData is a client side API managed under XMHttpRequest
UserEvent scripts are server side scripts with no browser based APIs available at all.
So you could use FormData in a client script to send info to a Suitelet or RESTlet but it's not present in a UserEvent script.
If you want to create a form in a Suitelet using SS2.0 you can use the following as a sample:
/**
*#NApiVersion 2.x
*#NScriptType Suitelet
*/
define(["N/log", "N/redirect", "N/runtime", "N/ui/serverWidget", "N/url", "./kotnRECBCFilters"],
function (log, redirect, runtime, ui, url, kotnRECBCFilters_1) {
function showPropertiesForm(context) {
var form = ui.createForm({
title: 'Property Trust Ledger'
});
var req = context.request;
var fromLoc = form.addField({
id: 'custpage_loc',
type: ui.FieldType.SELECT,
label: 'For Property',
source: 'location'
});
fromLoc.updateLayoutType({ layoutType: ui.FieldLayoutType.NORMAL });
fromLoc.updateBreakType({ breakType: ui.FieldBreakType.STARTCOL });
if (req.parameters.custpage_loc) {
fromLoc.defaultValue = req.parameters.custpage_loc;
}
var notAfterDate = form.addField({
id: 'custpage_not_after',
type: ui.FieldType.DATE,
label: 'On or Before'
});
if (req.parameters.custpage_not_after) {
notAfterDate.defaultValue = req.parameters.custpage_not_after;
}
form.addSubmitButton({
label: 'Get Detail'
});
//... bunch of stuff removed
context.response.writePage(form);
}
function onRequest(context) {
if (context.request.method === 'POST') {
var currentScript = runtime.getCurrentScript();
var params = {};
for (var k in context.request.parameters) {
if (k.indexOf('custpage_') == 0 && k.indexOf('custpage_transactions') == -1) {
if ((/^custpage_.*_display$/).test(k))
continue;
params[k] = context.request.parameters[k];
}
}
redirect.toSuitelet({
scriptId: currentScript.id,
deploymentId: currentScript.deploymentId,
parameters: params
});
return;
}
showPropertiesForm(context);
}
exports.onRequest = onRequest;
});

Resources