DOM as source: No data available in table


#1

Hi all,

I’ve been trying to implement DataTables (without any package - aldeed:tabular gets stuck on processing and crashes the browser) and using DOM as the source of data. However, I get “No data available in the table”. Is there any obvious reason why it can’t pick the DOM data?

I have this on my HTML file:

<head>
<title>Logins</title>
</head>
<body>
    <h1>Logins</h1>
{{> loginButtons}}
{{> loginstemplate}}
</body>

 <template name="loginstemplate">
{{#if ready}}
 <h1>External users logged in: {{countusers}}; Active: {{countactiveusers}}</h1>
<table id="example" class="display" width="70%">
<thead>
<tr>
 <th>Username</th>
<th>Logged in?</th>
<th>Name</th>
 <th>Firm</th>
 <th>Region</th>
 <th>Login time</th>
 <th>Record type</th>
 </tr>
 </thead>
 <tbody>         
   {{#each getlogin}}
    <tr>
<td>{{Username}}</td> 
<td>{{#if registeredatcheck}} Y {{/if}}</td>
<td>{{Name}}</td>
<td>{{Firm}}</td>
<td>{{Region}}</td>
<td>{{formatDate RegisteredAt}}</td>
<td>{{Recordtype}}</td>
</tr>
{{/each}}       
</tbody>
</table>
{{/if}}
</template>

And my JS file:

import { Template } from 'meteor/templating';

Logins = new Mongo.Collection('logins');

if(Meteor.isClient){
Meteor.subscribe('getlogins');
var $       = require( 'jquery' );
var dt      = require( 'datatables.net' )( window, $ );

Template.loginstemplate.helpers({
	'ready': function () {
		return Template.instance().subscriptionsReady();
		// $('#example').DataTable();
	},
	'getlogin': function(){
		return Logins.find({});
	},
	'countusers': function(){
		return Logins.find({"RegisteredAt":{$ne:'N/A'}}).count();
	},
	'countactiveusers': function(){
		return Logins.find().count();
	},
	'registeredatcheck': function(){
		return this.RegisteredAt instanceof Date;
	}

});


$(document).ready(function() {
    $('#example').DataTable();
} );

Template.registerHelper('formatDate', function(date) {
	if (this.RegisteredAt instanceof Date){
		return moment.utc(date).format('D MMM YYYY h:mm A');
	}
});

}


#2

this won’t work, because of multiple reasons.

For once, datatable() is initialized when the table is still empty. It is not built for reactive-templates like blaze. It can’t reflect changes in your dom. I would rather stick with something that is created for meteor/blaze to begin with. E.g. aldeed:datatable usually works. Try to find out, why it did not work properly.

Also, you have some flaws in your code, i hope you don’t mind if I mention some of them:

1.) do not use $(document).ready() with meteor. use Template.loginstemplate.onRendered(function() { …})
2.) do not reference things with jquery by id (or with javascript in general). Ids need to be unique and can lead to hard-to-track bugs, if they occure multiple times. Meteor/Blaze provides a template-scoped jquery (this.$). Use that to find dom-elements (e.g. by classname) in your template:

Template.loginstemplate.onRendered(function() {
   this.$(".datatable").DataTable();
});

3.) your global helper formatDate looks a bit odd. You pass a date, but you reference this.RegisteredAt in it.
4.) Try to avoid “magic-strings” like ‘N/A’ in a field that is usually a date. it should be either a date or not set at all (or null)
5.) Try use ES2015. Use const instead of var, use object-shortnotations like ready() { …} instead of read: function() { …}


#3

Thanks @macrozone, this is very helpful advice. I will take this route.