How to pull csv into DataTables

I have two questions to combine csv data with datatables and render this on a jekyll page:

  1. I’d like to be able to pull a CSV and then have it render as a datatable via JQuery

So a cross between this (which pulls a csv): https://jekyllrb.com/tutorials/csv-to-table/
And this (which makes a datatable with markdown): https://idratherbewriting.com/documentation-theme-jekyll/mydoc_tables.html

Is there a way this is possible?

  1. Then I would also like to set paging and search for DataTables on with this:

but I don’t know which file this should go in? the page itself? the template for the page? somewhere else?

Any help much appreciated! :slight_smile:

Yes you can use the CSV tutorial to get your table created as HTML.

And then according to the 2nd like you add display to the class of the table you rendered above. And also add dataTable: true to the frontmatter of that page.

Start with getting those to work directly on the page as everything’s in one place. If you need jquery script tag to be added you can put that on your page too.

And then if that all works well for one table on one page, then you can move something to a layout. Perhaps you have 10 pages which all have a table on them and data in their frontmatter and then you can write your HTML table / datatable template and generalize it for the others

You can also write your table as an includes file. Then you can use it on a page directly or in a layout using just one line.

I’d recommend going for the option of the datatable using HTM and not markdown. It says you just add a class as I covered above.

The reason being that rendering a table that ends up as a markdown down is tricky because you have to make that no extra lines appear between rows and that you don’t add a new line between values in a row or you’ll break the table.
Using an HTML table is more forgiving and allows you to use for and assign etc without worrying about the whitespace that a statement causes (since for and assign are not rendered literally)

Hi @MichaelCurrin ! Thanks so much! I added the display class and datatable:true and it works great!

However, where can I set the options for the datatable to make the paging/search/filter/sort/etc. appear on the table?

Those options get setup for you.

I made a codepen to demonstrate.

This is great… I just can’t work out how to add the javascript, this bit

$(document).ready(function () {
$("#my-table > table").DataTable();
});

i.e. where does this go / how do I reference it?

Add it at the bottom of the page.

<head>
external CSS and JS. add to layout for any page with a table.
</head>

## Heading 

<table>
</table>

<script>
$(document)...
</script>

The script can go below the table. The script is specific to the table. If you want multiple pages with tables on then you can create a layout which generated a table using data and adds the script tag below it.

Thanks for your help. However, feel like I am going a bit mad here as I can’t get the table to work as a datatable. This is what I have.

Default layout contains, in the following:

<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.21/css/jquery.dataTables.min.css" />
<script src="https://code.jquery.com/jquery-3.5.1.js"></script>
<script src="https://cdn.datatables.net/1.10.21/js/jquery.dataTables.min.js"></script>

My page itself has

dataTable: true

(tried with capital T and without)

and then pulls the csv into a table (this works) and sets the datatable script (doesn’t seem to do anything, no matter what options I set)

<table class="display" id="my-table">
  {% for row in site.data.mytabledata %}
    {% if forloop.first %}
    <tr>
      {% for pair in row %}
        <th>{{ pair[0] }}</th>
      {% endfor %}
    </tr>
    {% endif %}

    {% tablerow pair in row %}
      {{ pair[1] }}
    {% endtablerow %}
  {% endfor %}
</table>

<script>
$(document).ready(function () {
$("#my-table > table").DataTable();
});
</script>

So, the table of csv data appears fine, but I am sure it isn’t turning into a proper DataTables because no matter what I put in the for options etc. it does nothing… just looks like a normal html table with default css for jekyll.

Looks like your issue is using the DataTable script and not Jekyll. I would suggest broadening your search to Stackoverflow or the DataTables help channels to make sure you’re using it correct.

Have you tried getting it to work with a simple table in standard HTML? Once you get it to work there then I would carve it up into Jekyll/Liquid. That would at least tell you where your problem is.

Thank you, that’s a good point @mmistakes … I’ll go try that on a static html page/table. Currently feel like I am going a bit mad with it.

Also sorry I am not able to help with the jekyll docs theme approach which uses the class and might not even need the JS snippet.

I only tried the non Jekyll way as per the code pen.

Hi @MichaelCurrin and @mmistakes … I managed to very easily (instantly) setup a static html datatable by…

including this in index.html head

<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.21/css/jquery.dataTables.min.css" />
<script src="https://code.jquery.com/jquery-3.5.1.js"></script>
<script src="https://cdn.datatables.net/1.10.21/js/jquery.dataTables.min.js"></script>  

Using this table

<table class="display">
<colgroup>
<col width="30%" />
<col width="70%" />
</colgroup>
<thead>
<tr class="header">
<th>Field</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td markdown="span">First column **fields**</td>
<td markdown="span">Some descriptive text. This is a markdown link to [Google](http://google.com). Or see [some link][mydoc_tags].</td>
</tr>
<tr>
<td markdown="span">Second column **fields**</td>
<td markdown="span">Some more descriptive text.
</td>
</tr>
</tbody>
</table>

And then putting this beneath the table in the body

<script>
$('table.display').DataTable()
</script>

And it works… so what gives with Jekyll… where my table is just:

<table class="display">
  {% for row in site.data.datafile %}
    {% if forloop.first %}
    <tr>
      {% for pair in row %}
        <th>{{ pair[0] }}</th>
      {% endfor %}
    </tr>
    {% endif %}

    {% tablerow pair in row %}
      {{ pair[1] }}
    {% endtablerow %}
  {% endfor %}
</table>

If I follow the same steps, the table just renders as a normal table with Jekyll css, not a datatable (I also have datatable: true in header of file)

I cannot understand why this should be any different…

Not sure what datatable: true is for? Do you have Liquid logic that is tied to that?

What is the HTML of the table that is produced by the Liquid above that pulls from your _data file? How does it compare to the static HTML you tested without placing in Jekyll?

Seems to me something is off there or perhaps how jQuery DataTables is loading. Have you looked at the browser’s console to see if you have any script errors?

I would suggest putting all this in a public repo that others can test and look at your actual code.

@JohnS are you using the jekyll docs theme from the linked tutorial? The datatable setup is specific to that theme and not Jekyll.

If you can’t get that way to work you can always use the JS snippet way that is working for you and apply it to Jekyll. It is also reusable across projects regardless of theme

The difference is that your Liquid template for the DataTable does not resemble (let alone correlate) the static markup you tested with…

(Note that {% tablerow %} is not a flexible shortcut for every table out there…)

Getting the Liquid Template to render markup similar to your test static-markup is the key to solving this issue.

Right… yes, I didn’t realise this was specific to that documentation theme. I guess maybe this is going to be too complex for me!

My static html for the table that words if I write it myself is:

<table class="display">
<colgroup>
<col width="30%" />
<col width="70%" />
</colgroup>
<thead>
<tr class="header">
<th>Field</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td markdown="span">First column **fields**</td>
<td markdown="span">Some descriptive text. This is a markdown link to [Google](http://google.com). Or see [some link][mydoc_tags].</td>
</tr>
<tr>
<td markdown="span">Second column **fields**</td>
<td markdown="span">Some more descriptive text.
</td>
</tr>
</tbody>
</table>

The HTML generated in the example I am trying to make work, but doesn’t work, is as follows:

<table class="display">
    <tr>
        <th>Field</th>
        <th>Description</th>
    </tr>
    <tr class="row1">
<td class="col1">
      First column **fields**
    </td>
<td class="col2">
      Some descriptive text. This is a markdown link to [Google](http://google.com). Or see [some link][mydoc_tags].
    </td>
</tr>

    <tr class="row1">
<td class="col1">
      Second column **fields**
    </td>
<td class="col2">
      Some more descriptive text.
    </td>
</tr>
</table>

I am not a genius but I don’t really see why this should be dramatically different for the purpose of generating it as a datatable though… a lot of it does look the same?

I haven’t worked with jQuery Datatables so no idea on what HTML it is expecting. But if it’s expecting <thead> elements for the header it’s not getting that in your second example.

That’s the big difference I see. I suppose you need to consult the docs for jQuery Datatables where it explains how to work with it.

Solved! I needed to include elements around the header as suggested by @mmistakes i.e.

<table class="display">
  {% for row in site.data.csvfile %}
    {% if forloop.first %}
    <thead>
    <tr>
      {% for pair in row %}
        <th>{{ pair[0] }}</th>
      {% endfor %}
    </tr>
    </thead>
    {% endif %}

This solved the issue immediately! So the original CSV tutorial linked just needed to include the tags around the first row so that it was properly recognised for the datatables.

Thanks all!!

1 Like