Expand my Community achievements bar.

Announcing the launch of new sub-community for Campaign Web UI to cater specifically to the needs of Campaign Web UI users!

AC Tips & Tricks: datatables jQuery plugin+ single page webapp [PART 1]

Avatar

Community Advisor

1/9/23

Introduction

Ever wanted to create a custom webapp which allows recipient data editing without the hussle of coding it from the ground up? look no further than datatables;

DataTables is a powerful JavaScript library for adding advanced interaction controls to HTML tables, enhancing the functionality of standard HTML tables with features such as pagination, searching, filtering, and sorting. (link: https://datatables.net/). Overall, DataTables is a powerful and flexible tool for adding advanced interaction controls to HTML tables, making it easy to work with large datasets and create user-friendly, feature-rich tables for data display and analysis.

David__Garcia_0-1673272806751.png

 

In this blog, we will develop a single page web application that provides you with recipient data and allows you to make modifications to this data. The ultimate goal of this web application is to store the modified recipient data in Adobe Campaign.

 

Sandbox

http://live.datatables.net/xecefabu/1/edit You can use this playground to make changes in your table development in realtime to be then promoted to adobe campaign.

Resources

Include the following files in your header.

 

<!-- CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.13.1/css/jquery.dataTables.css">
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/searchpanes/2.1.0/css/searchPanes.dataTables.min.css">
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/fixedcolumns/4.2.1/css/fixedColumns.dataTables.min.css">
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/select/1.5.0/css/select.dataTables.min.css">
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/buttons/2.3.2/css/buttons.dataTables.min.css">
<!-- JavaScript -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.1/jquery.js" integrity="sha512-CX7sDOp7UTAq+i1FYIlf9Uo27x4os+kGeoT7rgwvY+4dmjqV0IuE/Bl5hVsjnQPQiTOhAX1O2r2j5bjsFBvv/A==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4" crossorigin="anonymous"></script>
<script type="text/javascript" charset="utf8" src="https://cdn.datatables.net/1.13.1/js/jquery.dataTables.js"></script>
<script type="text/javascript" charset="utf8" src="https://cdn.datatables.net/searchpanes/2.1.0/js/dataTables.searchPanes.min.js"></script>
<script type="text/javascript" charset="utf8" src="https://cdn.datatables.net/fixedcolumns/4.2.1/js/dataTables.fixedColumns.min.js"></script>
<script type="text/javascript" charset="utf8" src="https://cdn.datatables.net/select/1.5.0/js/dataTables.select.min.js"></script>
<script type="text/javascript" charset="utf8" src="https://cdn.datatables.net/buttons/2.3.2/js/dataTables.buttons.min.js"></script>  

 

Extensions description. (https://datatables.net/extensions/)

  1. Buttons: Provides an API framework which performs unique actions to your applications.
  2. Select: Select adds item selection capabilities to a DataTable. Items can be rows, columns or cells, which can be selected independently, or together.
  3. Fixed Columns: Allows to fix/sticky left or right columns in place.
  4. Search Panes: Provides accessible, intuitive and interactive search filters with advanced custom search capabilities.

Data Sources:

DataTables can obtain data from four different fundamental sources:

  • HTML document (DOM)
  • Javascript (array / objects)
  • Ajax sourced data with client-side processing
  • Ajax sourced data with server-side processing

Recipient Data

As the purpose of this blog is to develop a single page application, we will construct a query script that can be executed from the front end by posting the encoded query to endpoint: "/xtk/queryList.jssp" which returns response in javascript object.

example:

 

var recipientQuery = {
   "operation":"select", "schema":"nms:recipient",
   "startLine":0, "lineCount":999,
   "select":{
      "node":[
        {"expr":"@id"},
        {"expr":"@firstName+' '+@lastName","alias":"@name"},
        {"expr":"@email"},
        {"expr":"@phone"},
        {"expr":"@blackList"},
        {"expr":"@status"},  
      ],
   },
   "where":{
      "condition":[{"expr":"@id <> 0"}]
   },
   "orderBy":{
      "node":[{"expr":"@id"}]
   },   
};
$.post("/xtk/queryList.jssp", {queryDef:encodeURIComponent(JSON.stringify(recipientQuery))}, function(recipientResponse) {

 

The above script will return an array objects containing all key:data pairs and will be used as the source to initialize our datatables table.

David__Garcia_0-1673280325371.png

 

{
  "blackList": "0",
  "email": "500002@email.com",
  "id": "13218257",
  "name": "500002 - First Name Test Edit  500002 - Last Name",
  "phone": "12345",
  "status": "6",
  "_schema": "nms:recipient"
}

 

Complete JS script

Head over to https://datatables.net/examples/advanced_init/ to understand all datatables options used in this script.

 

<script type="text/javascript">// <![CDATA[
//function to add a loading spinner
$(window).on('load', function(){
    $('#cover').fadeOut(1000);
})

//highlight recipients who are blacklisted
function blacklistCheck(row) {
    if (row.blackList == 1) {
        return '<span class="recipient-blacklisted">' + row.name + '</span>'
    } else {
        return '<span class="recipient-notblacklisted">' + row.name + '</span>'
    }
}
//render integer status to string equivalent
function statusRender(i){
  switch(parseInt(i)) {
    case 1:
      return 'Subscriber';
      break;
    case 2:
      return 'Lead';
      break;
    case 3:
      return 'MQL';
      break;
    case 4:
      return 'SQL';
      break;
    case 5:
      return 'Opportunity';
      break;
    case 6:
      return 'Client';
      break;
    default:
      return '0';      
  }
}

jQuery( document ).ready(function() {     
//query recipient json script
var recipientQuery = {
   "operation":"select", "schema":"nms:recipient",
   "startLine":0, "lineCount":99999,
   "select":{
      "node":[
        {"expr":"@id"},
        {"expr":"@firstName+' '+@lastName","alias":"@name"},
        {"expr":"@email"},
        {"expr":"@phone"},
        {"expr":"@blackList"},
        {"expr":"@status"},  
      ],
   },
   "where":{
      "condition":[{"expr":"@id <> 0"}]
   },
   "orderBy":{
      "node":[{"expr":"@id"}]
   },   
};
//post to endpoint
$.post("/xtk/queryList.jssp", {queryDef:encodeURIComponent(JSON.stringify(recipientQuery))}, function(recipientResponse) {

    //define columns used in table
    var colsDef = [
        {data: null, defaultContent:'', orderable: false, className: 'select-checkbox',title:'<input type="checkbox" id="select_all" class="" title="Select All" />'},
        {data: null ,defaultContent:'',render: function (data, type, row, meta) {return meta.row;}},
        {data: 'id', title: 'id' },
        {data: 'name', title: 'Recipient',render: function (data, type, row, meta) {return blacklistCheck(row)}}, 
        {data: 'email', title: 'Email' },
        {data: 'phone', title: 'Phone' }, 
        {data: 'blackList', title: ' Blacklist'}, 
        {data: 'status', title: 'Status', render: function (data, type, row, meta) {return statusRender(data)}},                          
       ];   
  
/** datatables ini **/     
var table= $('#recipients').DataTable({   
        data:recipientResponse.data,     
        stateSave: false,  
        responsive: true,
        select: true,
        dom: 'PBfrtip', 
        deferRender: true,          
        paging: true,
        scrollY: 400,
        scrollX: true,
        scrollCollapse: true,        
        fixedColumns:{left: 2},        
        buttons: [{
          text: 'Submit',
          action: function(e, dt, type, indexes) {

                /****************doSomething ****************/
                var selectedRecipients   = [];
            
                table.rows({ selected: true } ).every( function ( rowIdx, tableLoop, rowLoop ) {
                  var data = this.data();
                  selectedRecipients.push({recipient:data.id})                                                                                          
                });  
                console.log(selectedRecipients)               
                /***************************************/            
          }
        }, ],          

        columns:colsDef,           
        language: {
          searchPanes: {
            count: '{total} records',
            countFiltered: '{shown} / {total}',
          }
        },
        searchPanes: {cascadePanes: true, viewTotal: true},                   
        columnDefs: [                                                                   
                { targets: [1], visible:false},
                //{ searchPanes: {show: true, initCollapsed: true},targets: [1,2 },              
                //{ searchPanes: {show: false}, targets: [1,2] }                                                                                                                                       
              ],                             
        select: {style:'multi', selector: 'td:first-child'}, order: [[ 1, 'asc' ]],                               
          
    });//table ini
    
});// recipientResponse   
    
    /**JS: Select All ***/    
    $('#select_all').on('click', function() {
      if ($('#select_all:checked').val() === 'on') {
        table.rows().select();
      } else {
        table.rows().deselect();
      }
    });

    //$('#recipients').DataTable().state.clear();  
});

// ]]></script>

 

End product

WebApp backend

David__Garcia_0-1673284205421.png

 

WebApp Frontend

 

GIF 09-01-2023 17-03-39.gif

Full page download ( acc-spa-webapp-code.docx)

 

AC Tips & Tricks: datatables jQuery plugin+ single page webapp  [PART 2](TBC)

Part 2 will look at how to use front end inline editing to modify recipient data.