Skip to main content
Kinetic Community

Putting Answers into DataTables (CE)

The service item described in this article illustrates (also attached) a simple usage of using a customer's answers to build up a table in Kinetic Request.  This gives the customer to request multiple items (ex. Port details for a Server Add Request) without having to have multiple instances of the same field (ex. Port Type and IP Address) on the service item. The attached example is a very simple application of a clothing order.

Usage

The Description section below explains the service item implementation.  To try the service item that is being described, download the attached service item (in .json format) and use the Author => Forms section of your Kapp to import the service item into your environment.  

Description

This example utilizes the DataTable plugin for JQuery to automatically build the table from the answers.

For more information about DataTable, see this site. For more information about JQuery, see this site. There is also helpful information here.

Sample Table 

Answers2Table.jpg

 

This example displays a table of records obtained by the customer entering answers and submitting them as a row to the table (in all base package default styling). There are four steps necessary to configure a Kinetic Request service item to display a table of user answers:

  1. Require the javascript and css files necessary for DataTables (if not already included in your bundle)
  2. Create the questions that have answers entered into the table and the table div
  3. Build the functions to process the tables
  4. Create the buttons for adding rows (note that delete is processed from within the table) and the events to support table build and review

1. Require the javascript and css files necessary for DataTables

DataTables may very well already be included in your bundle. If you find it is not, the following code was inserted into the customer header content for this service item to load the javascript and css files necessary for datatables. Note that these are not local calls. To do this long term on your system, you would want to download these locally and reference them from the local source.


<meta name="viewport" content = "width = device-width, initial-scale = 1.0, minimum-scale = 1.0, maximum-scale = 1.0, user-scalable = no" />
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.12/css/jquery.dataTables.min.css"/>

<!-- Font-Awesome -->
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css">

<script type="text/javascript" src="https://code.jquery.com/jquery-2.2.3.min.js"></script>
<script type="text/javascript" src="https://cdn.datatables.net/1.10.12/js/jquery.dataTables.min.js"></script>
 
2. Create the questions that have answers entered into the table and the table div
 
The questions created depend entirely on what you data you need to collect. Any type of question can be used.
 
3. Build the functions to process the tables
 
Note that since there are click actions on the table, there is a table build function for review request that doesn't contain the actionable items. This content is placed in the Custom Head Content for the service item.
 
<script>

//define table variable
var tableItems;

//Build the table for display on page load
function buildTables() {
    //Build the items table from the indicated stored JSON
    buildItemTable('itemsTableJSON', 'itemsTable');
}
function buildTablesReview() {
    //Build the items table from the indicated stored JSON without click actions
    buildItemTableReview('itemsTableJSON', 'itemsTable');
}

//Build the item table from the provided JSON string and display in provided
//div tag
function buildItemTable(jsonDataQuestion, divTag) {
    //Set up table
    tableItems = $('<table  id="'+divTag+'" >').replaceAll($('#'+divTag));
    
     // create table
    tableItems =  $('#'+divTag).DataTable( {
    //allows you to recreate the table each time they click search/add row
     "destroy": true,
     responsive: true,
     //creates the columns for the table
    columns: [
                
                { data: 'Item', "title":"Item" },
                { data: 'Size', "title":"Size" },
                { data: 'Color', "title":"Color" },
                { data: 'Quantity', "title":"Quantity" },
                { data: 'Comment', "title":"Comment" },
                { data: 'delete', "title":"DELETE",    orderable: false, width: 60,            className: "delete " }
            ]
    });
    
    //get data and parse JSON
    var oTxt = K('field['+jsonDataQuestion+']').value();
    var json = "[]";
    var dataArray = [];
        if (oTxt != null && oTxt != "") {
        //append the table body to the existing header
        var thisRow = {};
        json = $.parseJSON(oTxt);
        //create body and append body to the table by looping through the JSON
        for(var i=0; i < json.length; i++){

            // add row
            thisRow = { 
            "delete": "<i class='fa fa-times'></i>",
           "Item": json[i].Item,
            "Size": json[i].Size,
           "Color": json[i].Color,
            "Quantity": json[i].Quantity,
            "Comment": json[i].Comment    };
            dataArray.push(thisRow);
    
        }
        
    }
     //clear any existing data from the table, add the built rows and draw the table
    tableItems.clear().rows.add(dataArray).draw();
    
    //set up delete on click
    $('#'+divTag).on( 'click', 'td', function () {
       var cell = tableItems.cell(this);
       //if they clicked on the delete cell
       if (cell.data() == "<i class='fa fa-times'></i>") {
          //remove the seleted row
            tableItems.row(this.parentNode).remove().draw();
            buildTableJSON(tableItems);
    
        }
    } );
}
//Build the item table from the provided JSON string and display in provided
//div tag
function buildItemTableReview(jsonDataQuestion, divTag) {
    //Set up table
    tableItems = $('<table  id="'+divTag+'" >').replaceAll($('#'+divTag));
    
     // create table
    tableItems =  $('#'+divTag).DataTable( {
    //allows you to recreate the table each time they click search
     "destroy": true,
     responsive: true,
     //creates the columns for the table
    columns: [
                
                { data: 'Item', "title":"Item" },
                { data: 'Size', "title":"Size" },
                { data: 'Color', "title":"Color" },
                { data: 'Quantity', "title":"Quantity" },
                { data: 'Comment', "title":"Comment" }
                
            ]
    });
    
    //get data and parse JSON
    var oTxt = K('field['+jsonDataQuestion+']').value();
    var json = "[]";
    var dataArray = [];
        if (oTxt != null && oTxt != "") {
        //append the table body to the existing header
        var thisRow = {};
        json = $.parseJSON(oTxt);
        //create body and append body to the table by looping through the JSON
        for(var i=0; i < json.length; i++){

            // add row
            thisRow = { 
           "Item": json[i].Item,
            "Size": json[i].Size,
           "Color": json[i].Color,
            "Quantity": json[i].Quantity,
            "Comment": json[i].Comment    };
            dataArray.push(thisRow);
    
        }
        
    }
     //clear any existing data from the table, add the built rows and draw the table
    tableItems.clear().rows.add(dataArray).draw();
    
}

//Add a row to the table
function addItemRowJson() {
    
    var txtId = K('field[Item]').value();
    var txtSize = K('field[Size]').value();
    var txtColor = K('field[Color]').value();
    var txtQuantity = K('field[Quantity]').value();
    //Check that all required items are entered before allowing the row add
    //In this example, all columns are required except the comment
    if (txtId == '' || txtSize == '' || txtColor == '' || txtQuantity == '') {
        alert('Please fill in Item, Size, Color and Quantity before clicking add');
        return;
    }
        
    //Get existing table values
    var existingTableJson =  K('field[itemsTableJSON]').value();
    if (existingTableJson == "" || existingTableJson == null) {
        //The table is currently blank/empty. Create an empty json string to work with
        existingTableJson = "[]";
    } else {
        //entries already exist, so check that this isn't a duplicate.
        var duplicatesCheckReturn = true;
        $(jQuery.parseJSON(existingTableJson)).each(function() {  
             if (this.Item == txtId && this.Size == txtSize && this.Color == txtColor) {
                alert("You have already ordered "+txtColor+", "+txtSize+" "+txtId);
                duplicatesCheckReturn = false;
            }
        });
        if (duplicatesCheckReturn == false) { return; }
    }
        
    //the size of the full answer field is 4000. We need to make sure 
    //the table saved as a JSON string fits into the available space.
    
        
        //Add the row to the visible table
        tableItems.row.add({ 
            "delete": "<i class='fa fa-times'></i>",
            "Item": txtId,
            "Size": txtSize,
            "Color": txtColor,
            "Quantity": txtQuantity,
            "Comment": K('field[Comment]').value()    }).draw();
    
    buildTableJSON(tableItems);
    
    //Clear the previously selected options/reset defaults
    K('field[Item]').value('');
    K('field[Size]').value('');
    K('field[Color]').value('');
    K('field[Quantity]').value('1');
    K('field[Comment]').value('');

 
}    

function buildTableJSON(table){
    var newTableJson = JSON.stringify(table.rows().data().toArray());
    K('field[itemsTableJSON]').value(newTableJson);
}

</script>
 
4. Create the buttons for adding/removing rows and the events to support table build and save
 
The "Initial Page" element for this service item specifies the "Build Table" custom on-load event which initiates the table.  To create your own table, create a new load event with a Custom action.
 
 
The button for adding rows to the table call the functions defined in the javascript referenced above. 
Answers2TableAddButton.jpg
Answers2TableAddButtonEvent.jpg
 
The questions and add button don't have a purpose in review and only clutter the page, so they are placed in a section with criteria that removes them in review:
 
Answers2TableReview.jpg