Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bootstrap & DataTables: Table is rendered twice

Please read below "Update: 2017-Aug-23 (20Hs)", I discovered this effect experimenting with Flask but it seems to be related only between DataTables and Bootstrap.

Implementing a Flask application I have rendered a table reading data by means of Pandas directly from a CSV file, that was no problem.

Then I decided to use DataTables in order to make of some features like scroll-bar/search/ordering first and later other more advanced features when implementing a database.

# file structure
#
# /testapp
#   +--- /app
#   |     +------ /templates
#   |     |           +------ events.html
#   |     +------ __init__.py
#   |     |
#   |     +------ events.csv
#   |     
#   +---- run.py
#

My __ init __ .py (where I render my events table) looks like:

# file: __init__.py 
import pandas as pd

from flask import Flask, render_template
from flask_bootstrap import Bootstrap

app = Flask(__name__, static_path = '/static', static_url_path = '/static')

bootstrap = Bootstrap(app)

@app.route('/')
@app.route('/events')
def events():
    return render_template('events.html', page='events')

and my events.html template looks like:

{% extends "bootstrap/base.html" %}
{% block content %}

{% block scripts %}
    {{ super() }}
    <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/v/bs/dt-1.10.15/datatables.min.css"/>
    <script type="text/javascript" src="https://cdn.datatables.net/v/bs/dt-1.10.15/datatables.min.js"></script>

    <script>
        $(document).ready(function(){
            if ( !$.fn.dataTable.isDataTable( '#myTable' ) ) {
                $('#myTable').DataTable( {
                    scrollY: 270,
                    paging: false
                } );
            }
        });
    </script>
{% endblock scripts %}

<div class="bootstrap-iso">
    <div class="container-fluid">      
      <table border="1" class="dataframe " id="myTable">
      <thead>
        <tr style="text-align: right;">
          <th></th>
          <th>Event</th>
          <th>Next Shutdown</th>
          <th>Next Startup</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <th>1</th>
          <td>2017-08-20 15:06:18</td>
          <td>2017-08-20 16:06:00</td>
          <td>2017-08-21 07:30:00</td>
        </tr>
        <tr>
          <th>2</th>
          <td>2017-08-20 12:26:26</td>
          <td>2017-08-20 13:26:00</td>
          <td>2017-08-21 07:30:00</td>
        </tr>
      </tbody>
    </table>
    </div>
</div>

{% endblock %}

run.py file looks like:

from app import app
app.run(host='0.0.0.0', debug=False)

Now when rendering the events page I see shortly the original table (without DataTable) and one second later I see the table rendered again but in DataTable format.

Could anyone explain me what I am doing wrong here?

Should I use JavaScript sourced data like proposed here by DataTable?

I am using Flask and Bootstrap from Flask which uses jQuery version v1.12.4.

Thank you very much in advance for helping!

==============================

Update: 2017-Aug-22

This effect occurs when using Bootstrap. When no Bootstrap is used (means: no "extends "bootstrap/base.html"" in events.html and set the corresponding Datatables with no bootstrap) then the page is updated only once and Datatables is rendered correctly.

I saw other link like this (Bootstrap Issue) where a JS popover's function is called twice and I'm questioning if this is a similar problem...

I have also updated the files (see above init.py and events.html) with a minimum of code which reproduces the effect.

I have posted a question in DataTables discussion forum too (Link)

==============================

Update: 2017-Aug-23 (20Hs)

Thanks to people in DataTables forum the effect can be reproduced without any flask or python files by means of live datatables (link) !

Go to this link and add following line (from Bootstrap CDN)

into the HTML head:

<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">

Now when you run the example by clicking on "Run with JS" button you will see first the HTML table and then the DataTable,

Im using DataTable 1.10.15, Bootstrap 3.3.7 and JQuery 1.12.4

This effect does not happens if the Bootstrap is not used.

==============================

Update: 2017-Sep-10

For me is the issued closed by using a new approach. Read my post at 2017-Sep-10 below.

like image 429
rsp Avatar asked Jun 29 '26 10:06

rsp


1 Answers

Now when rendering the events page I see shortly the original table (without use of DataTable script) and then the DataTable is correctly rendered.

I misread that when I commented above. This doesn't appear to be either a pandas of Flask issue.

I threw together a test case to poke at a theory that something was stalling jQuery from thinking the page was ready, thus delaying the invocation of .DataFrame() until after the page had rendered. That would case the effect you're seeing. (I assume you're pulling in jQuery from the page you're overriding.)

You don't show the fragement that pulls in jQuery, and it looks like you're using Bootstrap. Are you pulling in other JS? Can you post that bit of code?

Looking at the DataTable docs, the only thing that jumped out is that the paths they recommend are different from the ones you're using (the doc I'm looking at doesn't have the v/bs/dt- part). I get a slightly different result switching between the two.

like image 67
Dave W. Smith Avatar answered Jul 02 '26 10:07

Dave W. Smith