Code Examples

If actions combine database functions with user interface, window interaction, and status functions, you must separate them into client-side and server-side actions. See the following example:

Original Action

New Actions

                    //A. Loads the file
loadFile('MyFolder/myFile.txt').done(function(data) {
    //B. Shows the message
    showMessage(data);
}); 

                  

Server-Side Action

                    //A. Server-side action (Check the Run on server box)
//Loads the file
loadFile('MyFolder/myFile.txt').done(function(data) {
    //Saves file data to the scratchpad variable
    scratchpad.fileContent = data;
}); 

                  

Client-Side Action

                    //B. Client-side action
//Shows the message stored in the scratchpad variable
showMessage(scratchpad.fileContent); 

                  

The original action loads a file from the File Cabinet and shows its content in a popup window on the user interface. The function loadFile() interacts with the database and must be stored in a server-side action, while showMessage() works with the user interface and requires a client-side action.

After checking the Run on server box on the action record, edit the action by adding the scratchpad variable (scratchpad.fileContent) where you save the file data to be sent to the client. Then, remove the showMessage() function and create a client-side action to store it. The client-side action obtains data from the scratchpad variable and displays the file content through a popup window on the user interface.

The previous example shows a simple use case. The following code examples help you implement client-side and server-side actions for other most common use cases:

Transferring Data Using Questions and Answers

Client-side and server-side actions can share information using questions and answers. With questions and answers, you can share information from the server to the client and the other way around. During the migration, you may need to create the questions and answers that will store the data to be transferred. For more information about questions and answers, see Gathering Information with Questions and Answers.

Transferring Data from Server to Client Using Questions and Answers

The following example shows how to transfer data from the server to the client with questions and answers.

Original Action

New Actions

                        //A. Obtains customer data
var currentCustomer = getValue("NS", "ENTITYID");
getData({
    type: 'customer',
    filter: ['internalid', 'is', currentCustomer],
    fields: ['companyname']
}).done(function(data) {
    var customer = data[0];
    //B. Displays customer data on the user interface
    showMessage(customer.companyname);
}); 

                      

Server-Side Action

                        //A. Server-side action (Check Run on server box) 
//Obtains customer data 
var currentCustomer = getValue("NS", "ENTITYID");
getData({
    type: 'customer',
    filter: ['internalid', 'is', currentCustomer],
    fields: ['companyname']
}).done(function(data) {
    var customer = data[0];
    //Saves customer data in an answer
    setValue('DATA', 'CUSTOMER', customer.companyname);
}); 

                      

Client-Side Action

                        //B. Client-side action 
//Obtains customer data from the answer
var companyname = getValue('DATA', 'CUSTOMER');
//Displays customer data on the user interface
showMessage(companyname); 

                      

The original action is obtaining customer information through the getData() function—a server-side function. Then, the customer information is displayed on the user interface through a popup window using the showMessage() function—a client-side function.

Because the original action combines a server-side function and a client-side function, it must be separated into a server-side and a client-side action. After obtaining the customer data through the getData() function, the new server-side action A saves the information to the DATA/CUSTOMER answer through the universal function setValue(). Storing the customer information in an answer makes it available for client-side action. The new client-side action B obtains the customer information from the DATA/CUSTOMER answer through the universal function getValue() and displays it in a popup window.

Transferring Data from Client to Server Using Questions and Answers

The following example shows how to transfer data from client to server with questions and answers.

Original Action

New Actions

                        //A. Asks users to provide the item SKU
var sku = prompt('Enter item SKU');
//B. Searches for items with the provided item SKU
getData({
    type: 'item',
    filter: ['itemid', 'is', sku],
    fields: ['itemid', 'displayname']
}).done(function(data) {
    setValue('DATA', 'ITEMS', data);
}); 

                      

Client-Side Action

                        //A. Client-side action
//Asks users to provide the item SKU
var sku = prompt('Enter item SKU');
//Saves the item SKU in an answer
setValue('ITEM', 'SKU', sku); 

                      

Server-Side Action

                        //B. Server-side action(Check Run on server box)
//Obtains the item SKU from the answer
var sku = getValue('ITEM', 'SKU', sku);
//Searches for items with the provided item SKU
getData({
    type: 'item',
    filter: ['itemid', 'is', sku],
    fields: ['itemid', 'displayname']
}).done(function(data) {
    setValue('DATA', 'ITEMS', data);
}); 

                      

The original action asks users to provide the item SKU through the prompt() function—a JavaScript client-side function. Then, the original action searches for the items with the provided SKU through getData()—a server-side function. Finally, the item SKU is saved to the answer DATA/ITEMS.

Because the original action combines a client-side function and a server-side function, it must be separated into a server-side action and a client-side action. After asking the user to provide the item SKU, the new client-side action A saves the information to the answer ITEM/SKU through the universal function setValue(). Storing the item SKU in an answer makes it available for the server-side action. The new server-side action B retrieves the item SKU from the answer through the universal function getValue(), searches for the item SKU, and saves it to an answer.

Transferring Data Using the Scratchpad Variable

Client-side and server-side actions can share information using the scratchpad variable. With the scratchpad variable, you can share information from the server to the client and the other way around.

Transferring Data from Server to Client Using the Scratchpad Variable

The following example shows how to transfer data from the server to the client with the scratchpad variable.

Original Action

New Actions

                        //A. Obtains customer data 
var currentCustomer = getValue("NS", "ENTITYID");
getData({
    type: 'customer',
    filter: ['internalid', 'is', currentCustomer],
    fields: ['companyname']
}).done(function(data) {
    var customer = data[0];
    //B. Displays customer data on the user interface
    showMessage(customer.companyname);
}); 

                      

Server-Side Action

                        //A. Server-side  action (Check Run on server box) 
//Obtains customer data
var currentCustomer = getValue("NS", "ENTITYID");
getData({
    type: 'customer',
    filter: ['internalid', 'is', currentCustomer],
    fields: ['companyname']
}).done(function(data) {
    var customer = data[0];
    //Saves customer data to the scratchpad variable
    scratchpad.companyname = customer.companyname;
}); 

                      

Client-Side Action

                        //B. Client-side action
//Obtains data from the scratchpad variable and displays it on the user interface
showMessage(scratchpad.companyname); 

                      

The original action is obtaining customer information through the getData() function —a server-side function. Then, customer information is displayed on the user interface through a popup window using the showMessage() function—a client-side function.

Because the original action combines a server-side function and a client-side function, it must be separated into a server-side and a client-side action. After obtaining the customer data, the new server-side action A saves the information to the scratchpad variable (scratchpad.companyname). The customer information becomes available for the new client-side action B. The client-side action B retrieves the customer information from the scratchpad variable and displays it in a popup window.

Transferring Data from Client to Server Using the Scratchpad Variable

The following example shows how to transfer data from client to server with the scratchpad variable.

Original Action

New Actions

                        //A. Asks users to provide the item SKU
var sku = prompt('Enter item SKU');
//B. Searches for items with the provided item SKU
getData({
    type: 'item',
    filter: ['itemid', 'is', sku],
    fields: ['companyname']
}).done(function(data) {
    setValue('DATA', 'ITEMS', data);
}); 

                      

Client-Side Action

                        //A. Client-side action
//Asks users to provide the item SKU and saves data to the scratchpad variable
scratchpad.sku = prompt('Enter item SKU'); 

                      

Server-Side Action

                        //B. Server-side action (Check Run on server box)
//Searches for items by otbtaining the item SKU from the scratchpad variable
getData({
    type: 'item',
    filter: ['itemid', 'is', scratchpad.sku],
    fields: ['companyname']
}).done(function(data) {
    setValue('DATA', 'ITEMS', data);
}); 

                      

The original action asks users to provide the item SKU through the prompt() function—a JavaScript client-side function. Then, the original action searches for the items with the provided SKU through getData(), which is a server-side function. Finally, the item SKU is saved to the answer DATA/ITEMS.

Because the original action combines a client-side function and a server-side function, it must be separated into a server-side action and a client-side action. After asking the user to provide the item SKU, the new client-side action A saves the information to the scratchpad variable (scratchpad.sku). The item SKU becomes available for the server-side action B. The new server-side action B retrieves the item SKU from the scratchpad variable and searches for the item SKU.

Transferring Data from Server to Client with QTables

You can transfer data from server to client using qTables. See the following example:

Original Action

New Actions

                      //A. Asks users to provide the beginning of the item SKU
var sku = prompt('Enter the beginning of the item SKU');
//B. Searches for items by the begining of the item SKU
getData({
    type: 'item',
    filter: ['itemid', 'startswith', sku],
    fields: ['itemid']
}).done(function(data) {
    //B1. Stores the found items in a qTable and displays it on the user interface
    var t = getQTable('ITEMS');
    t.setRowCount(data.length);
    for (var i = 0; i < data.length; i++) {
        t.set('ITEM', i + 1, data[i].itemid);
    }
}); 

                    

Client-Side Action

                      //A. Client-side action
//Asks users to provide the beginning of the item SKU and stores the user input in the scratchpad variable
scratchpad.sku = prompt('Enter the beginning of the item SKU'); 

                    

Server-Side Action

                      //B. Server-side action (Check Run on server box)
//Searches for items by the begining of the item SKU
getData({
    type: 'item',
    filter: ['itemid', 'startswith', scratchpad.sku],
    fields: ['itemid']
}).done(function(data) {
    //B1. Stores the found items in a qTable
    var t = getQTable('ITEMS');
    t.setRowCount(data.length);
    for (var i = 0; i < data.length; i++) {
        t.set('ITEM', i + 1, data[i].itemid);
    }
}); 

                    

Client-Side Action

                      //C. Client-side action
//Refreshes the user interface to display the found items in the qTable
renderView(); 

                    

For more information about qTables, see QTable Questions.

The original action asks users to provide the beginning of the item SKU through the prompt() function—a JavaScript client-side function. Then, the original action searches for the items with the provided characters through getData()—a server-side function. Finally, the found item SKUs are saved to a qTable and displayed on the user interface.

Because the original action combines a client-side function, a server-side function, and displays the qTable on the user interface, it must be separated into a server-side action and multiple client-side actions. After asking the user to provide the beginning of item SKU, the client-side action A saves the information to the scratchpad variable ( scratchpad.sku).

The information saved to the scratchpad variable becomes available for the server-side action. The new server-side action B obtains the information from the scratchpad variable and searches for item SKUs matching the user input. The found items are saved in a qTable. To update the qTable on the user interface, the client-side action C refreshes the user interface through the renderView() function and displays the found item SKUs in the qTable.

Transferring Data from Server to Client with CE-Generated Tables

You can transfer data from the server to the client using CE-generated tables automatically created with data from your account. See the following example:

Original Action

New Actions

                      //A. Asks users to provide the beginning of the item SKU 
var sku = prompt('Enter the beginning of the item SKU');
//B. Searches for items by the beginning of the item SKU
getData({
    type: 'item',
    filter: ['itemid', 'startswith', sku],
    fields: ['itemid']
}).done(function(data) {
    //B1. Stores the found items in a CE-generated table
    var t = getTable('ITEMS');
    t.set(data);
    t.setStatus('ready');
}); 

                    

Client-Side Action

                      //A. Client-side action 
//Asks users to provide the beginning of the item SKU and stores the user input in the scratchpad variable
scratchpad.sku = prompt('Enter the beginning of the item SKU'); 

                    

Server-Side Action

                      //B. Server-side action (Check Run on server box)
//Searches for items by the beginning of the item SKU
getData({
    type: 'item',
    filter: ['itemid', 'startswith', scratchpad.sku],
    fields: ['itemid']
}).done(function(data) {
    var t = getTable('ITEMS');
    t.set(data);
    t.setStatus('ready');
}); 

                    

For more information about CE-generated tables, see Creating Code Exec Generated Tables.

The original action asks users to provide the beginning of the item SKU through the prompt() function—a JavaScript client-side function. Then, the original action searches for the items starting with the provided characters through getData(), which is a server-side function. Finally, the found item SKUs are saved to a CE-generated table and can be used, for example, in an input box popup table answer.

Because the original action combines a client-side function and a server-side function, it must be separated into a server-side action and a client-side action. After asking the user to provide the beginning of the item SKU, the newclient-side action A saves the information to the scratchpad variable ( scratchpad.sku). This information becomes available for the server-side action. The new server-side action B obtains the information from the scratchpad variable and searches for item SKUs matching the user input. The found items are saved in a CE-generated table and available to be used in client-side actions. For example, client-side actions using input box popup table answers.

Performing Multiple Server Requests

Your current implementation may include single actions that require database functions to perform multiple operations. However, server-side actions are limited in the number of server operations they can perform in a single request without failing. To overcome this limit, you can create a client-side action including a loop where you call a sever-side action. With the loop, the client-side action will make multiple calls to the server-side action. The server-side action must only perform a few server operations, for example, creating one item record. See the following example:

Original Action

New Actions

                      //A. Creates multiple records
(async function() {
    var records = getValue('DATA', 'RECORDS'),
        created = [];
    for (var i = 0; i < records.length; i++) {
        var newRecord = await createRecord(records[i]);
        created.push(newRecord.id);
    }
    setValue('DATA', 'CREATED', created);
})(); 

                    

Client-Side Action

                      //A. Client-side action
(async function() {
    var records = getValue('DATA', 'RECORDS'),
        created = [];
    for (var i = 0; i < records.length; i++) {
        setValue('DATA', 'TO_BE_CREATED', records[i]);
        await runAction('CREATE_RECORD');
        var newRecord = getValue('DATA', 'NEW');
        created.push(newRecord.id);
    }
    setValue('DATA', 'CREATED', created);
})(); 

                    

Server-Side Action

                      //B. Server-side action (Check Run on server box)
//Creates a single record
var record = getValue('DATA', 'TO_BE_CREATED');
createRecord(record).done(function(newRecord) {
    //Stores the record internal ID in an answer
    setValue('DATA', 'NEW', newRecord);
}); 

                    

The original action stores the list of records to be created in the answer DATA/RECORDS. Then, the action loops through the list and creates the records one by one. The createRecord() function makes a request to the server to create one record in each request.

There is no information about how many records the answer stores. If you implement the for loop in a server-side action, the action may fail because the required operations may exceed the execution limit.

The new client-side function A creates a loop to iterate through the records to be created. The new record to be created is stored in the answer DATA/TO_BE_CREATED. Then, the client-side action calls the server-side action through the runAction() function. As you can see from the example, client-side actions can use JavaScript ES6 resources like the async and await keywords.

The new server-side action B retrieves the information about the record to be created from the answer DATA/TO_BE_CREATED, creates a record, and stores its internal ID to the answer DATA/NEW.

After the server-side action has completed its task, the client-side action takes the result of the server-side action from the answer DATA/NEW and continues running as in the original action.

Calling Actions from Event Handlers Attached to User Interface Elements

Custom event handlers attached to user interface elements cannot directly call server-side functions. You must store the server-side function in a server-side action and call it through the runAction() function from the custom scripts. Custom scripts must use questions and answers to share information because the scratchpad variable is not available for them. In the rule of the server-side action, you must enter X(*/*) — the always false operator —because the action is not activated by answers selected by users on the interface.

The following example shows how to implement runAction() in an event handler attached to a user interface element.

Original Custom Script

New Implementation

                      //Custom script
//A. Adds an onclick event handler to a user interface button
jQuery('#my-button').click(function() {
    var currentCustomer = getValue('NS', 'ENTITYID');
    //B. Obtains the customer name
    getData({
        type: 'customer',
        filter: ['internalid', 'is', currentCustomer],
        fields: ['companyname']
    }).done(function(data) {
        var customer = data[0];
        //C. Displays the customer name on the user interface (if users click the button)
        showMessage(customer.companyname);
    });
}); 

                    

Updated Custom Script

                      //Custom script
//A. Adds an onclick event handler to a user interface button
jQuery('#my-button').click(function() {
    //Calls the server-side action
    runAction('LOAD_DATA').done(function() {
        var companyname = getValue('DATA', 'CUSTOMER');
        //C. Displays the customer name on the user interface (if users click the button)
        showMessage(companyname);
    });
}); 

                    

Server-Side Action

                      //Server-side action
//Check the Run on server box
//B. Obtains customer data
var currentCustomer = getValue('NS', 'ENTITYID');
getData({
    type: 'customer',
    filter: ['internalid', 'is', currentCustomer],
    fields: ['companyname']
}).done(function(data) {
    var customer = data[0];
    //Stores customer data in an answer
    setValue('DATA', 'CUSTOMER', customer.companyname);
}); 

                    

The original custom script adds an event handler to a user interface button. The custom script retrieves customer data through getData()—a server-side function. When users click the button, the customer name is displayed in a popup window through showMessage()—a client-side function.

The new custom script still adds the event handler and calls the showMessage() function to display the information. However, the new version retrieves the customer information by calling a server-side action through runAction(). The server-side action B loads the customer data and stores it in an answer to make it available on client.

Calling Actions from CPQ Modules

As custom event handlers, CPQ modules are client scripts that cannot directly call server-side functions. You must store server-side functions in a server-side action. Then, the modules must call the server-side actions through the runAction() function. To share information between modules and server-side actions, you must use questions and answers. Modules cannot access the scratchpad variable. In the rule of the server-side action, you must enter X(*/*) — the always false operator —because the action is not activated by answers selected by users on the interface.

The following example shows how to implement runAction() in a module.

Original Module

New Implementation

                      <script script-type="module" type="text/javascript">
  var app = angular.module('formApp');
  app.modController('modctrl', [function () {
    this.getCost = function() {
      var sku = getValue('ITEMS','SKU');
      if (sku) {
//Loads the item cost
        getData({
          type: 'item',
          filter: ['itemid','is', sku],
          fields: ['cost']
        }).done(function(data) {
          var cost = data[0].cost;
          showMessage(sku+' cost is '+cost);
        });
      } else {
        alert('Please enter the item SKU');
      }
    };
  }]);
</script>
<div ng-controller="modctrl as mc">
   <div style="margin:10px;">
      <div>Load item cost</div>
      <button style="margin:10px;padding:5px 15px;" type="button" ng-click="mc.getCost();">Show cost</button>
   </div>
</div> 

                    

Updated Module

                      <script script-type="module" type="text/javascript">
  var app = angular.module('formApp');
  app.modController('modctrl', [function () {
    this.getCost = function() {
      var sku = getValue('ITEMS','SKU');
      if (sku) {
        runAction('ITEM_COST').done(function(data) {
          var cost = getValue('MISC','COST');
          showMessage(sku+' cost is '+cost);
        });
      } else {
        alert('Please enter the item SKU');
      }
    };
  }]);
</script>
<div ng-controller="modctrl as mc">
    <div style="margin:10px;">
        <div>Load item cost</div>
        <button style="margin:10px;padding:5px 15px;" type="button" ng-click="mc.getCost();">Show cost</button>
    </div>
</div> 

                    

Server-Side Action

                      //Server-side action
//Check the Run on server box
var sku = getValue('ITEMS', 'SKU');
getData({
    type: 'item',
    filter: ['itemid', 'is', sku],
    fields: ['cost']
}).done(function(data) {
    setValue('MISC', 'COST', data[0].cost);
}); 

                    

When users click the button on the user interface, the original module retrieves the item SKU from the answer ITEMS/SKU. Then, the module searches the item cost for that item by directly calling the getData() function—a server-side function. Finally, the item cost is displayed in a popup window on the user interface through the showMessage() function—a client-side function.

In the new implementation, a server-side action has been created to store the getData() function. The updated module calls the server-side action through the runAction() function and shares the item SKU through the answer ITEMS/SKU. In the server-side action, the getData() function obtains the item SKU from the answer ITEMS/SKU, searches for the item cost, and saves it to the answer MISC/COST to make it available for the module. Then, the module retrieves the item cost from the answer.

Related Topics

  • Placeholder

General Notices