How do I properly use datatables in Flask with using templates - html

I am trying to form a template using datatables. For some reason my datatables is not working properly.
This is my base.html, I put the Jquery at the bottom of the page so that I can reuse the query every single time.
'''
<head>
</head>
<body>
{% block content %} {% endblock %}
<script src="static/plugins/datatables-bs4/js/dataTables.bootstrap4.js"></script>
<script>
$(function () {
$('#table1').DataTable({
"paging": true,
"lengthChange": false,
"searching": false,
"ordering": true,
"info": true,
"autoWidth": false,
});
});
</script>
</body>
'''
This is where I am planning to use it. for some reason the thead does not output the table as expected.
'''
{% extends "base.html" %} {% block content %}
<table id="table1">
<thead>
<tr>Company Name</tr>
<tr>Pre Money Value</tr>
<tr>Post Money Value</tr>
<tr>Round Size </tr>
<tr>Investment Cost </tr>
<tr>Status </tr>
</thead>
</table>
{% endblock %}
'''
Any help will be fully appreciated

DataTables expects a fully-formed HTML table, which you're missing.
From DataTables site:
In order for DataTables to be able to function correctly, the HTML for the target table must be laid out in a well formed manner with the 'thead' and 'tbody' sections declared.
For example:
<table id="table_id">
<thead>
<tr>
<th>Column 1</th>
<th>Column 2</th>
<th>etc</th>
</tr>
</thead>
<tbody>
<tr>
<td>Row 1 Data 1</td>
<td>Row 1 Data 2</td>
<td>etc</td>
</tr>
<tr>
<td>Row 2 Data 1</td>
<td>Row 2 Data 2</td>
<td>etc</td>
</tr>
</tbody>
</table>
Notably, your table is missing <tbody>. It's not clear from your code what you actually intend to have in the body of the table, but you'll also need to ensure your data conforms to the appropriate rows/columns.
I would also suggest using $(document).ready();, unless you're tying your function to a button press or something.
Also from the DataTables site:
$(document).ready( function () {
$('#myTable').DataTable();
} );

I tried that,
for some reason the thead is not showing
The console has errors but I don't know how to fix it
jquery.min.js:2 Uncaught TypeError: Cannot read property 'aDataSort' of undefined
at _fnSortFlatten (jquery.dataTables.js:5889)
at _fnSortingClasses (jquery.dataTables.js:6227)
at loadedInit (jquery.dataTables.js:1208)
at HTMLTableElement.<anonymous> (jquery.dataTables.js:1306)
at Function.each (jquery.min.js:2)
at k.fn.init.each (jquery.min.js:2)
at k.fn.init.DataTable [as dataTable] (jquery.dataTables.js:869)
at k.fn.init.$.fn.DataTable (jquery.dataTables.js:15161)
at HTMLDocument.<anonymous> (test:318)
at e (jquery.min.js:2)

Here is a very good article about datatables.net in Flask : her POC works very well. :)
Alta Fang, June 1st, 2019:
Making a web app that updates a database based on table row selections

Related

Save to Database when someone updates notes field in html table (django)

I have found many answers to this on SO but my understanding of all of this is still too new to be able to understand how to implement so just posting my exact question:
I have a table which is a filtered view of my database that shows up on one page of my app. It has a notes column where each cell uses content-id-editable. I want to add a save button and when someone wishes to save that particular notes section cell I want them to be able to press "save" and have the updated cell post to the database.
UPDATED QUESTION:
I have made an attempt at using AJAX to push the data to the database (based on #rastawolf's answer) but I haven't made much progress and everything online seems to be geared toward inputting an entire form instead of one column of a table. Here's where I'm at so far:
notes.js:
function saveNoteAjax() {
return $.ajax({
type: 'POST',
url: '/Users/justinbenfit/territorymanagerpython/homepage/views.py/notes',
data: {note: document.getElementById('notes').value,}
})
}
async function SaveLoadNote(){
await saveNoteAjax()
return $.ajax({
type: 'GET',
url: '/Users/justinbenfit/territorymanagerpython/homepage/views.py/notes',
data: {note: document.getElementById('notes').value}
})
let location = "/Users/justinbenfit/territorymanagerpython/homepage/", """I don't have any idea how to make the page refresh"""
location.reload()
}
detail.hmtl:
<table class= "content-table">
<thead>
<tr>
<th>Name</th>
<th>Distributor</th>
<th>State</th>
<th>Brand</th>
<th>Cell</th>
<th>Email</th>
<th>Notes</th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
{% for tm in territory_manager %}
<td style="white-space:nowrap;">{{ tm.Name }}</td>
<td style="white-space:nowrap;">{{ tm.Distributor }}</td>
<td style="white-space:nowrap;">{{ tm.State }}</td>
<td style="white-space:nowrap;">{{ tm.Brand }}</td>
<td style="white-space:nowrap;">{{ tm.Cell }}</td>
<td style="white-space:nowrap;">{{ tm.Email }}</td>
<td id='notes' contenteditable="True">{{ tm.Notes }}</td>
<td><input type='submit', align="right" value='Update' class='btn btn-primary'></td>
</tr>
{% endfor %}
</tr>
{% else %}
<h2>No Results for: {{ state }} </h2>
{% endif %}
</tbody>
</table>
<!-- Scripts -->
<script src="assets/js/notes.js"></script>
</body>
</html>
views.py:
def notes(request):
if request.is_ajax():
note = request.POST['note']
updatedNote = TM.objects.update(note) #how is the database supposed to know which tm's notes field to update? How do I pass that information in here?
return render(request, 'homepage/detail.html', {"note": updatedNote})
I wouldn't recommend setting it up this way as the page will refresh every time someone saves a note...
Why don't you instead send the POST data via AJAX?
You will need to write a JavaScript function that you can call when your button is clicked.
You can do something simple like...
Notes.js
function saveNoteAjax() {
return $.ajax({
type: 'POST',
url: 'your route to the function notes function in views.py',
data: {note: document.getElementById('yourNotesInput_ID').value}
})
}
async function SaveLoadNote(){
await saveNoteAjax()
*use another Ajax call to get the new notes from the DB*
*insert some function to refresh the notes on-screen*
}
views.py
def notes(request):
if request.is_ajax():
note = request.POST['note']
*insert your code for updating your DB table*
return HttpResponse('')
If you don't want AJAX, you could make your entire table into a Django model formset. Each notes field would be an input element. To get started, {{form.notes}}. Once it's working you can change your html to render the and style the form field any way you want). The other non-editable fields would be accessed with {{form.instance.fieldname}}
The differemce would be that the user would need to explicitly update after making changes, i.e. you need an Update button to submit the change(s)
Formsets and model formsets look complicated to start with, but they aren't really once you have done a few on them!

How To Transclude Table Row Into AngularJs Component

Iv been trying to create an angularJS component for constructing a dynamic html table from a provided array.
The components template includes some ng-transclude directives as 'placeholders'/slots for templates provided by the component consumer.
Is it possible to transclude a <tr> template (with nested <th>), to be used inside the table <thead>?
I have tried using all variations for transclution:
transclude: true, transclude: 'element'
and transclude: { header: 'header'}
(the third option seems as the most suitable, as I will eventually required multiple elements to be transcluded).
Component:
app.component("virtualTable", {
bindings: {
someArray: "<"
},
transclude: {
header: "header"
},
templateUrl: () => {
return "/app/components/virtual-table.component.html";
});
Component Template:
<div>
<table>
<thead>
<tr ng-transclude="header"></tr>
</thead>
<tbody>
<tr ng-repeat="item in vt.someArray">
...another place for transclution...
</tr>
</tbody>
</table>
</div>
Consuming HTML (component declaration):
<virtual-table some-array="vm.personList">
<header>
<th>First Column</th>
<th>Second Column<th>
</header>
</virtual-table>
I excpect the compiled DOM to look like this:
<table>
<thead>
<tr>
<th>First Column</th>
<th>Second Column</th>
</tr>
</thead>
...
But instead I get the innerHTML of the transcluded element (header) as Text:
<table>
<thead>
<tr ng-transclude="header">
<header class="ng-scope">
First Column
Second Column
</tr>
</header>
...
I Suspect the browser (chrome 76) to somehow strip the <tr> tags from the transcluded element before it is being provided to the component (as it illegal us to use <tr> outside of a <table>).
I would like to maintain an html table structure.
Is The Any Way to Solve This?

Get the width of parent <td> from angularjs directive template

Im trying to figure out if its possible to get the width of the parent my directive is going to be placed in.
Keeping it simple I have some directive my-directive which Im placing inside of a table:
<table>
<tr>
<td><my-directive ..../></td>
<td><my-directive ..../></td>
<td><my-directive ..../></td>
<td><my-directive ..../></td>
</tr>
</table>
And inside my-directive Iwant to know the width of my parent <td> so I could display my content properly - with more or less data according to the width
Can it be done?
Update:
My HTML code:
<table class="table">
<thead>
<tr>
<td width="5%"></td>
<td width="5%"></td>
<td width="85%"></td>
</tr>
<tr>
<th>Col 5</th>
<th>Col 5</th>
<th>Col C 85</th>
</tr>
</thead>
<tbody>
<tr>
<td><trim value="Some value a"></trim></td>
<td>Some value b</td>
<td>Some value c</td>
</tr>
</tbody>
</table>
My directive:
angular.module('ui.directives', []).directive('trim', function() {
return {
restrict: 'E',
scope: {
value: '#'
},
template: "{{value | limitTo:6}}"
};
}
);
From within the template I can limit by a constant I define (or pass by, from outside. But I want to change that, to know myself, from within that directive if I should trim the text or not
Yes you can get the parent element using angular's jqlite, a subset of jquery in the link function. The link function is to provide the behavior to your directive, in this function you can get the directive element and modify it at run time according to your need.
angular.directive('myDirective', [function($document) {
return {
restrict:'E',
link: function(scope, element, attribute) {
var parent = element.parent();// will give an array
var parentWidth = parent[0].offsetWidth;
//modify/truncate your attribute.value depending upon the parentWidth.
}
}
}]);

How to print html table with default header in each page

I am creating a print option on a html table.
this table has hundreds of rows. Data are fetching from php and AJAX.
After getting this data i am creating a print option like below.
function PrintElem(elem){
Popup($(elem).html());
}//
function Popup(data)
{
var mywindow = window.open('', 'my div', 'width=100%');
mywindow.document.write('<html><head><title></title>');
mywindow.document.write('<link rel="stylesheet" href="<?php echo base_url(); ?>/resources/css/bootstrap.css" />');
mywindow.document.write('</head><body >');
mywindow.document.write(data);
mywindow.document.write('</body></html>');
mywindow.document.close(); mywindow.focus(); //newwindow.focus();
mywindow.print(); mywindow.close();
return true;
}//
<span class="trial_balance_ajax" id="print_section">
<!---- Ajax table data loads here----->
</span>
Now I am trying to print table header column in each page of printed document.
But In this case Data header only shows in first page then data overflows in others page...
I want a Default Column header in Each page
please help
What does your generated table look like? My testing indicates that if you create a table with explicit <thead> and <tbody> the header is automatically set for you:
<table>
<thead>
<tr>
<th>Foo</th>
<th>Bar</th>
<th>Baz</th>
</tr>
</thead>
<tbody>
<tr>
<td>!!!</td>
<td>!!!</td>
<td>!!!</td>
</tr>
<!-- Many rows... -->
<tr>
<td>!!!</td>
<td>!!!</td>
<td>!!!</td>
</tr>
</tbody>
</table>
In other words, the above seems to work as requested.
Edit: The requested behaviour seems to occur automatically in Firefox, but is sadly not possible to achieve without compromises in other browsers. See this related question for suggestions.
Why dont you divide rows so you can create another table having header in it.

Printing a html table

I have the following table for example, how do i add print functionality just to the table? And a button that when clicked, the following table is printed via printer
<table border="1">
<tr>
<th>Header 1</th>
<th>Header 2</th>
</tr>
<tr>
<td>row 1, cell 1</td>
<td>row 1, cell 2</td>
</tr>
<tr>
<td>row 2, cell 1</td>
<td>row 2, cell 2</td>
</tr>
</table>
You require to create new style sheet print.css and set CSS media=print
for example :
<style media="screen">
.noPrint{ display: block; }
.yesPrint{ display: block !important; }
</style>
<style media="print">
.noPrint{ display: none; }
.yesPrint{ display: block !important; }
</style>
and add class to "yesPrint" to the sections you want to print
<div class= "yesPrint">
<table border="1">
<tr>
<th>Header 1</th>
<th>Header 2</th>
</tr>
<tr>
<td>row 1, cell 1</td>
<td>row 1, cell 2</td>
</tr>
<tr>
<td>row 2, cell 1</td>
<td>row 2, cell 2</td>
</tr>
</table>
</div>
Now add a button
<input TYPE="button" onClick="window.print()">
for more detatil : http://www.codeproject.com/KB/HTML/Printing_with_CSS.aspx
I use this function:
<script type="text/javascript">
function PrintElem(elem)
{
Popup($(elem).html());
}
function Popup(data)
{
var mywindow = window.open('', 'my div', 'height=400,width=600');
mywindow.document.write('<html><head><title></title>');
/*optional stylesheet*/ //mywindow.document.write('<link rel="stylesheet" href="main.css" type="text/css" />');
mywindow.document.write('</head><body style="direction:rtl;"><pre>');
mywindow.document.write(data);
mywindow.document.write('</pre></body></html>');
mywindow.document.close();
mywindow.print();
return true;
}
</script>
You can modify it to your needs.
In fact it opens a new window containing this element and prints it.
One approach is to open the table in a new page. You can do this with a javascript submit of a form to the new page, passing along all the variables you will need to build your table.
<form name = "theform" .... >
<input type = "hidden" name = "something" value = "importantdata">
... stuff
</form>
<script type = "text/javascript">
submit('theform')
</script>
Then put the code to generate the table on the new page along with your button. If you don't want a button, you can still invoke the print function by simply referring to your javascript function within your html code:
<script type = "text/javascript">
printit()
</script>
You can also open your table in a new page using the javascript window.open() method. This is a good approach if you don't have too many variables to pass to the new window. You can pass a few small things via url variables, which you can set up in your javascript function.
I have also used an approach where I stay on the same page and the user can click on something to remove the display of everything but the table. This is done by wrapping the removable stuff in a div
<div id= "remove">
stuff
</div>
When the user does a click, the javascript function that is fired sets the display for that id to "none".
document.getElementById('remove').style.display = 'none';
A second click restores the display. The click doesn't have to be on a button. I have used it on a report heading, so that everything would disappear except the report itself. You could put it on one of your table cells.
In any case, the window.print() method will only open a window for the printer; the user can then set up the print job as he/she wishes, make sure the printer is on, etc.
js way : ( you cant print only the table)
<FORM>
<INPUT TYPE="button" onClick="window.print()">
</FORM>
c# way :
you should open a new page or container, with styles or crystal reports - and print using c# commands.
Actually you can print only the table. It requires some JavaScript magic (inspired by this page). The idea is that we open a new page (JS-window element), insert the table into that page and prints it. There are probably some portability issues with different browsers. Also, some browsers will probably complain about popups but yeah.. in theory it should work. :-)
The code could look something like this;
<script type="text/javascript">
var win = window.open(); // We create the window
win.document.open(); // We open the window (popup-warning!)
win.document.write("<h1>Hello world</h1>"); // Insert table here <--
win.print(); // Print the content
win.close(); // Close down the page
</script>