Tabulator: Secondary Table in Modal

Created on 12 Apr 2018  路  6Comments  路  Source: olifolkerd/tabulator

Hi Oli,

Programming newbie here... :)

I am currently updating a tracking application for projects with multiple requirements each. this involves a considerable amount of database records that are queried separately - one JSON file to output the projects from a department and another to output the requirements for each project.

The output in the browser should be is a table with all the projects of the department, with a drop-down table from each row, containing a table with the respective project requirements.

However, the nested tables example you provide in your 3.5 beta documentation (reply to issue #775), does not seem to be feasible as it would require a massive amount of data output form the database and would most certainly crash the server.

Alternatively though, I am now exploring the possibility of showing the requirements for each project through a model rather than a drop-down table from the row.

My current code uses the following:

// Variables to get the data from the json file
//----------------------------------------------------------------------
let  serviceTowerID = $("#tower-id").text(),
    jsonURL = "php/json/json-tracker-projects.php?t=" + serviceTowerID;
    jsonURL1 = "php/json/json-tracker-projects.php?t=" + serviceTowerID;
//----------------------------------------------------------------------

// TRACKER TABLE - Projects List
//===================================================================================================================================================================
$("#tracker").tabulator({
    height:740, // set height of table (in CSS or here), this enables the Virtual DOM and improves render speed dramatically (can be any valid css height value)
    responsiveLayout:true, // this option takes a boolean value (default = false)
    movableColumns: true, //enable user movable columns
    layout:"fitColumns", //fit columns to width of table (optional)
    pagination:"local",
    paginationSize:12,
    initialSort:[
        {column:"ClientName", dir:"asc"}, //sort by this first
    ],
    columns:[ //Define Table Columns for the project rows
        {title:"Project", field:"Name"},
        {title:"Type", field:"ProjectType"},
        {title:"Client", field:"ClientName"},
        {title:"Status", field:"ProjectStatus"},
        {title:"Go-live Date", field:"GoLiveDate"},
        {title:"Project Manager", field:"ProjectManagerName"},
        {title:"Progress", field:"AvgPercentComplete", formatter:"progress", formatterParams:{color:['#991F3D', '#E31937', '#FF6A00', '#F2A200', '#A5ACB0', '#A1C4D0','#008080']}, align:"left"},
        {title:"Last Update", field:"Notes", formatter:"", width:"25%"},
    ],

    footerElement:$("<div class='tabulator-footer'><button class='btn btn-outline-secondary btn-sm' name='download' style='float:left' id='download-csv'><i class='fa fa-download'></i> Download as CSV</button></div>"), //set custom table footer with custom button   

    rowClick:function(e, row){ //trigger a modal window when a row is clicked
        $('#req-modal').modal('show');
        $("#req-modal").tabulator("setData", jsonURL1);

        //console.log ("its working");
    },     
    rowFormatter:function(row){
        if(row.getData().AvgPercentComplete < 20){
            row.getElement().addClass("error"); //mark rows with age less than 18 with a warning state;
        };
        if(row.getData().AvgPercentComplete > 75){
            row.getElement().addClass("positive"); //mark rows with age less than 18 with a warning state;
        }
    },
});

//Load data into the table
$("#tracker").tabulator("setData", jsonURL);

//===================================================================================================================================================================


// Requirements Table
//===================================================================================================================================================================
$("#req-table").tabulator({
    height:740, // set height of table (in CSS or here), this enables the Virtual DOM and improves render speed dramatically (can be any valid css height value)
    //responsiveLayout:true, // this option takes a boolean value (default = false)
    movableColumns: true, //enable user movable columns
    //layout:"fitColumns", //fit columns to width of table (optional)
    //pagination:"local",
    //paginationSize:12,
    initialSort:[
        {column:"ClientName", dir:"asc"}, //sort by this first
    ],
    columns:[ //Define Table Columns for the project rows
        {title:"Project", field:"Name"},
        {title:"Type", field:"ProjectType"},
        {title:"Client", field:"ClientName"},
        {title:"Status", field:"ProjectStatus"},
        {title:"Go-live Date", field:"GoLiveDate"},
        {title:"Project Manager", field:"ProjectManagerName"},
        {title:"Progress", field:"AvgPercentComplete", formatter:"progress", formatterParams:{color:['#991F3D', '#E31937', '#FF6A00', '#F2A200', '#A5ACB0', '#A1C4D0','#008080']}, align:"left"},
        {title:"Last Update", field:"Notes", formatter:"", width:"25%"},
    ],


    //footerElement:$("<div class='tabulator-footer'><button class='btn btn-outline-secondary btn-sm' name='download' style='float:left' id='download-csv'><i class='fa fa-download'></i> Download as CSV</button></div>"), //set custom table footer with custom button   

    rowFormatter:function(row){
        if(row.getData().AvgPercentComplete < 20){
            row.getElement().addClass("error"); //mark rows with age less than 18 with a warning state;
        };
        if(row.getData().AvgPercentComplete > 75){
            row.getElement().addClass("positive"); //mark rows with age less than 18 with a warning state;
        }
    },
});

Note: I am using the same JSON file for both tables only for testing purposes.

While i can get the modal to show the table headers (see below), i am not sure why they are not filling the whole width of the table, nor why no data is currently loading. Can you please advise if it is possible to implement this? and if so, why is it not working so far?

image

Question - Ask On Stack Overflow

All 6 comments

Hey @LMJS1974

With a few tweaks to the nested table example we can get the functionality you are after. so the steps would be:

  • use a rowFormatter to add an element that will later be turned into the sub table
  • use a custom formatter to add add a column to the table that allows toggling of the table and then creeates a new tabulator instance that makes a separate ajax request for its data.

Here is a rough example (can't guarantee it will work straight of, just blind coding the example), in this i am assuming that each row data has an id property that is used in the query for the sub table:

//toggle for table formatter
var tableToggleFormatter function(cell, formatterParams){
    var self = this,
    el = $("<div class='tabulator-responsive-collapse-toggle'><span class='tabulator-responsive-collapse-toggle-open'>+</span><span class='tabulator-responsive-collapse-toggle-close'>-</span></div>");

    cell.getElement().addClass("tabulator-row-handle");

    //toggle table on click

    el.click(function(){
        var subTable = $(this).closest(".tabulator-row").find(".subtable-holder");

        $(this).toggleClass("open");

        if(subTable.hasClass("tabulator")){
            //remove table if it currently exists
            subTable.tabulator("destroy");
        }else{
            //create table if not present
            tableEl.tabulator({
                layout:"fitColumns",
                ajaxURL:"/getdatafromhere.com?id=" + cell.getData().id,
                columns:[
                    {title:"Date", field:"date", sorter:"date"},
                    {title:"Engineer", field:"engineer"},
                    {title:"Action", field:"actions"},
                ]
            })
        }
    });

    return el;
}

//table definition
$("#example-table").tabulator({
    height:"311px",
    layout:"fitColumns",
    resizableColumns:false,
    data:nestedData,
    columns:[
        {formatter:tableToggleFormatter, width:30, minWidth:30, align:"center", resizable:false, headerSort:false}, //toggle formatter
        {title:"Make", field:"make"},
        {title:"Model", field:"model"},
        {title:"Registration", field:"reg"},
        {title:"Color", field:"color"},
    ],
    rowFormatter:function(row){
        //create holder element for table
        row.getElement().append("<div class='subtable-holder'></div>");
    },
})

Let me know if that helps.

Cheers

Oli :)

HI Oli,

Thank you very much for your reply. Apologies for the late reply but haven't had the opportunity to work on this project over the last week and try your code example yet.

Still, can you please clarify if the example provided is for the nested table or for the modal?

As per my post above, I have now looking to show the requirements table for each project through a model rather than a drop-down table from the row.

Once again, thank you for the fantastic support to an already fantastic plugin.

Cheers,

Luis

Hey Luis,

That example is for a nested table.

Tabulator does not provide modals itself, as it is a table library not a UI framework, but you could easily use the rowClick callback to trigger a modal load or database lookup when the user clicks on a row.

There are a whole host of modal options out there, you could either craft your own or use the jQuery or Bootstrap modals as a starting point.

I hope that helps.

Cheers

Oli :)

HI Oli,

Thanks for the example mentioned above for sub-table . I am using it , but currently facing one issue .
on clicking toggle button subtable is created using tabulator but after that all formatters re-run for the main table , whic reset everything.
So basically i am not able to see the subtable view.
It goes like this:

  1. click toggle button
  2. subtable created base on click.
  3. again all formatters run for main table which reset tabulator set in a particular row.
  4. View is not updated with sub table.

Could you please help me in this regard.

Hey @bajpad

What do you mean by point 3? what is triggering the formatters to run again?

Cheers

Oli

I have tried this example. Seems there is typo:

row.getElement().append("<div class='subtable-holder'></div>");

should be appendChild. If someone looking for working example. better look into Nested table

Here you can put inside hoderEl anything that should appear inside. even, with some hack, the modal window ;)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

mindcreations picture mindcreations  路  3Comments

cemmons picture cemmons  路  3Comments

Manbec picture Manbec  路  3Comments

sphynx79 picture sphynx79  路  3Comments

yaxino picture yaxino  路  3Comments