8

I have a suitelet with a sublist button and I am trying to get the button to execute a function on a custom module. I can not get it to work. I get an error "Cannot call method "receive" of undefined" Any Ideas?

Snippet of code to add button

define(['N/error', 'N/record', 'N/search', 'N/ui/serverWidget','./lib1'],


function(error, record, search, ui, lib1) {
//... some code here
searchSublist.addButton({
   id: 'custpage_recievepayment', 
   label: 'Receive Payment',
   functionName: "lib1.receive()"});
}

Snippet of custom Module

define(['N/redirect'],
  function(redirect){
 function receive(){

      var deal = '497774';
      var url = redirect.toSuitelet({
       scriptId: 'customscript_deal_entry_2_0',
       deploymentId: 'customdeploy1',
       returnExternalUrl: false,
       params: {
        prevdeal: url
       }
      })
 }
 });
kdub
  • 205
  • 1
  • 6
  • 14

5 Answers5

4

I was able to get this to work with out the client script or exporting it to the global object that was suggested. The key was to modify my custom module to return the function I wanted to use on the button and calling the custom module file with form.clientScriptFileId

//suitelet
define(['N/error', 'N/record', 'N/search', 'N/ui/serverWidget'],
function(error, record, search, ui) {
   
    // other code here
        form.clientScriptFileId = 78627;//this is the file cabinet internal id of my custom module
        var searchSublist = form.addSublist({
            id: 'custpage_deals',
            type: ui.SublistType.LIST,
            label: 'Deals'
        })
        searchSublist.addButton({
            id: 'custpage_receivepayment', 
            label: 'Receive Payment',
            functionName: "receive()"
                });
  
  //custom module
  
  define(['N/url','N/error'],

function(url, error) {
    return{
          receive: function(){
                               //function code here
                             }                 
          }
})
Community
  • 1
  • 1
kdub
  • 205
  • 1
  • 6
  • 14
  • 1
    That worked for me too. Have you been successful using the form.clientScriptModulePath() method?. btw I noticed you have parens in the functionName property. When I did that I had a error logged to the console. A quick text search in the Sources tab discovers `function(mod){ mod.myFunc()(); }`. I should work better as `functionName: "receive"` – tzvi Aug 17 '16 at 17:22
3

For suitescript 2.0, you'll need to define the file that actually contains your function.

/**
 *@NApiVersion 2.x
 *@NScriptType UserEventScript
 */
define([],
  function() {
    function beforeLoad(context) {
      if(context.type == "view") {
        context.form.clientScriptFileId = 19181;
        context.form.addButton({
          id: 'custpage_dropshippo',
          label: 'Generate Dropship PO',
          functionName: 'generateDropshipPurchaseOrder'
        });
      }
    }
    return {
      beforeLoad: beforeLoad,
    };
  }
);

In that example, the value 19181 is the file cabinet ID of the following file (which doesn't need a deployment but does need a script record):

/**
 *@NApiVersion 2.x
 *@NScriptType ClientScript
 */
define([],
  function() {
    function pageInit() {
    }
    function generateDropshipPurchaseOrder() {
      console.log("foo");
    }
    return {
      pageInit: pageInit,
      generateDropshipPurchaseOrder: generateDropshipPurchaseOrder
    };
});
2

Thanks for sharing this information. I finally made it to work by using the "file cabinet internal id" not the "client script" internal id, as mentioned by someone in this thread.

Also i noticed through the chrom developer tool that "scriptContext" is not automatically passed over to the client script function as i had expected. So i had to manually pass in the data i need in the client script through the following way:

function beforeLoad(scriptContext) {
    var form = scriptContext.form;
    form.clientScriptFileId = 33595032;
    form.addButton({
        id: 'custpage_reprocessinvoice',
        label: 'Reprocess Invoice',
        functionName: 'reprocess(' + scriptContext.newRecord.id + ')'
    });
}

Hope this may help someone and save him/her a bit of time.

Sharon Xie
  • 21
  • 1
  • this works! but be careful, the "file cabinet internal id" can change depending if you are in sandbox or production. – Morris S Dec 06 '17 at 15:24
1

Button click handlers is something of an issue (at least, in my opinion) in 2.0. You are getting this error because lib1 is not defined on the client side.

What I have had to do is create a Client Script that exports my click handlers to the global object to make them accessible. Something like:

// Client script
define(['my/custom/module'], function (myModule) {
    window.receive = myModule.receive;
});

// Suitelet
define(...
    // some code...
    searchSublist.addButton({
        id: 'custpage_recievepayment', 
        label: 'Receive Payment',
        functionName: "receive"
    });
// other code...

It's not ideal, and certainly not good practice in general to export to the global space, but I do not know any other way to reference a function within a module on a button click.

erictgrubaugh
  • 8,519
  • 1
  • 20
  • 28
  • Thanks for your help! What entry point should I use for the Client Script. I would assume that I would need to input window.receive = myModule.receive I can get the code snippet to work if I just call myModule.receive from the pageinit entry point but I only want it to run at the push of the button so I added a function under pageinit function so that it does not fire when the page loads but then I am right back to where I started I can not call the new function nested under the pageinit function. – kdub Jun 16 '16 at 03:29
  • I don't think you need any event handler at all; I've been successful with exactly the script shown above. It's basically equivalent to `pageInit`, though. – erictgrubaugh Jun 16 '16 at 03:53
  • I have tried your exact code except changed the path to the file I have in the file cabinet. The file is called lib.js and is located in the same folder as the suitelet so I am using define(["./lib"]) I am getting the following error: Uncaught TypeError: Cannot read property 'receive' of undefined – kdub Jun 16 '16 at 18:10
  • This is not how it has to be done. Check this article to see an example: https://netsuite.custhelp.com/app/answers/detail/a_id/61236/kw/functionName and this one https://netsuite.custhelp.com/app/answers/detail/a_id/63272/kw/serverWidget%20addButton – B. Assem Aug 15 '17 at 12:10
0

After not getting this to work after multiple tries I filed a defect with Netsuite (Defect 390444) and they have just told me that this has now been fixed and tested and will be in the next major release.

kdub
  • 205
  • 1
  • 6
  • 14
  • This is not a solution: the solution is to use Form.clientScriptModulePath or form.clientScriptFileId : https://netsuite.custhelp.com/app/answers/detail/a_id/61236/kw/functionName and https://netsuite.custhelp.com/app/answers/detail/a_id/63272/kw/serverWidget%20addButton – B. Assem Aug 15 '17 at 12:13