2013-02-17 5 views
3

Я пытаюсь использовать DataTables (через mrt add datatables) с помощью Meteor. Я по-разному попытался добавить к обратному сообщению Meteor.subscribe, Meteor.autorun, Meteor.startup и Template.mytemplate.rendered - все это приводит к следующему исключению и сообщению No data available in table.Meteor with DataTables: Meteor._atFlush TypeError

Любые указатели?

Exception from Meteor._atFlush: TypeError: Cannot call method 'insertBefore' of null 
     at http://localhost:3000/packages/liverange/liverange.js?bc1d62454d1fefbec95201344b27a7a5a7356293:405:27 
     at LiveRange.operate (http://localhost:3000/packages/liverange/liverange.js?bc1d62454d1fefbec95201344b27a7a5a7356293:459:11) 
     at LiveRange.replaceContents (http://localhost:3000/packages/liverange/liverange.js?bc1d62454d1fefbec95201344b27a7a5a7356293:403:17) 
     at http://localhost:3000/packages/spark/spark.js?c202b31550c71828e583606c7a5e233ae9ca50e9:996:37 
     at withEventGuard (http://localhost:3000/packages/spark/spark.js?c202b31550c71828e583606c7a5e233ae9ca50e9:105:16) 
     at http://localhost:3000/packages/spark/spark.js?c202b31550c71828e583606c7a5e233ae9ca50e9:981:9 
     at http://localhost:3000/packages/deps/deps-utils.js?f3fceedcb1921afe2b17e4dbd9d4c007f409eebb:106:13 
     at http://localhost:3000/packages/deps/deps.js?1df0a05d3ec8fd21f591cfc485e7b03d2e2b6a01:71:15 
     at Array.forEach (native) 
     at Function._.each._.forEach (http://localhost:3000/packages/underscore/underscore.js?47479149fe12fc56685a9de90c5a9903390cb451:79:11) 

Update: Потенциально связанные с this issue, для которых лучшее решение найдено было назвать DataTable() для каждой строки - не идеал в этом случае, и потенциально катастрофическое в шахте, учитывая очень большое количество строк.

ответ

4

Ответ доктора является правильным началом. Вот лучшая практика, как я вижу это в настоящее время:

HTML

<template name="data_table"> 
    {{#constant}} 
     <table class="table table-striped" id="tblData"> 
     </table> 
    {{/constant}} 
</template> 

JS:

Template.data_table.created = function() { 
    var _watch = Collection.find({}); 
    var handle = _watch.observe({ 
     addedAt: function (doc, atIndex, beforeId) { 
      $('#tblData').is(":visible") && $('#tblData').dataTable().fnAddData(doc); 
     } 
     , changedAt: function(newDoc, oldDoc, atIndex) { 
      $('#tblData').is(":visible") && $('#tblData').dataTable().fnUpdate(newDoc, atIndex); 
     } 
     , removedAt: function(oldDoc, atIndex) { 
      $('#tblData').is(":visible") && $('#tblData').dataTable().fnRemove(atIndex); 
     } 
    }); 
}; 

Template.data_table.rendered = function() { 

    if (!($("#tblData").hasClass("dataTable"))) { 
     $('#tblStudents').dataTable({ 
      "aaSorting": [] 
      , "sDom": "<'row-fluid'<'span6'l><'span6'f>r>t<'row-fluid'<'span6'i><'span6'p>>" 
      , "sPaginationType": "bootstrap" 
      , "oLanguage": { 
       "sLengthMenu": "_MENU_ records per page" 
      } 
      , "aoColumns": [ 
       { "sTitle": "First Data", "mData": function (data) { return data.firstData }, 
      ] 
     }); 

     $('#tblData').dataTable().fnClearTable(); 
     $('#tblData').dataTable().fnAddData(Collection.find().fetch()); 
    } 
}; 
+0

Интересно. Позвольте мне сделать это. Я немного подслушиваю, что нет более простого способа сделать это. – mukmuk

+0

Как насчет этого. Это работает – mukmuk

+0

Я бы заметил, что это больно медленно на большом наборе данных. – mukmuk

3

Поскольку Meteor реагирует, вам нужно сначала создать пустую таблицу, а затем добавить строки.

Создать таблицу:

$('#myTable').dataTable({ 
    "aoColumns": cols, //the column titles 
    "sDom": gridDom 
}); 

Добавить строки должны выглядеть примерно так:

var myCursor = myCollection.find({}); 
var handle = myCursor.observe({ 
    added: function (row) { 
    //Add in here the data to the table 
    }, 

});

+0

сэр вы можете обновить полный пример, пожалуйста. –

0

Вот моя реализация DataTables в Метеор, используя CoffeeScript и HTML. Он работает, и он проще, но может быть менее эффективным, чем существующие ответы для больших таблиц (это быстро в моем случае).

Шаблон Функция

Template.dashboard.rendered = -> 

    # Tear down and rebuild datatable 
    $('table:first').dataTable 
    "sPaginationType": "full_numbers" 
    "bDestroy": true 

HTML

<template name="dashboard"> 
    <table class="table table-bordered" id="datatable_3" style="min-width:1020px"> 
    <thead> 
     <!-- code removed to save space --> 
    </thead> 
    <tbody id="previous-jobs-list"> 
     {{#each jobs}} 
     {{> jobRow}} 
     {{/each}} 
    </tbody> 
    </table> 
</template> 

<template name="jobRow"> 
    <tr> 
    <td><a href="/jobs/{{number}}">{{number}}</a></td> 
    <td>{{normalTime date}}</td> 
    <!-- more code removed to save space --> 
    </tr> 
</template> 

Где dashboard.jobs простой .find (...) на коллекции.

+0

Это может быть использовано тогда, но на данный момент оно работает с проблемами. При первом рендеринге, так как нет содержимого, в таблице отображается сообщение, в котором не найдены данные, когда, когда он продолжает отображаться, вы также видите, что содержимое и сообщение «нет данных» не удаляются позже. – radalin

3

Ответный подход все еще стоит, но требует изменений после двух лет.

  1. Нет такой вещи, как постоянная.
  2. Вместо пустого стола положите thead, но не телом. Таким образом, столбцы определяются правильно.
  3. Поместите наблюдателя в onRendered (не отображается больше) и НЕ на onCreated (больше не созданный). В противном случае таблица заполняется только при первом создании, а не когда вы вернетесь.
  4. Очистить и заполнить методы onRendered не требуется.
  5. В методе наблюдения убедитесь, что вы добавляете массив, а не объект.В противном случае fnAdd не может отобразить содержимое
  6. fnRemove больше не существует. Вместо этого используйте fnDeleteRow
  7. Я не уверен, требуется ли «видимая проверка» или нет. Кажется, что проблема не возникает, когда вы ее удаляете, поэтому я удалил ее.

С учетом указанных выше замечаний, вот код:

Template.creamDealsList.onRendered(function() { 
    if (!($("#tblData").hasClass("dataTable"))) { 
     $('#tblStudents').dataTable({ 
     // Those configuration are not really important, use it as they are convenient to you 
     "aaSorting": [] 
     , "sDom": "<'row-fluid'<'span6'l><'span6'f>r>t<'row-fluid'<'span6'i><'span6'p>>" 
     , "sPaginationType": "bootstrap" 
     , "oLanguage": { 
      "sLengthMenu": "_MENU_ records per page" 
     } 
     , "aoColumns": [ 
      { "sTitle": "First Data", "mData": function (data) { return data.firstData }, 
     ] 
    }); 
    } 
    var _watch = Collection.find({}); 
    var convertDocToArray = function (doc) {return [doc._id, doc.name]} 
    var handle = _watch.observe({ 
    addedAt: function (doc, atIndex, beforeId) { 
     $('#tblData').dataTable().fnAddData(convertDocToArray(doc)); 
    } 
    , changedAt: function(newDoc, oldDoc, atIndex) { 
     $('#tblData').dataTable().fnUpdate(convertDocToArray(newDoc), atIndex); 
    } 
    , removedAt: function(oldDoc, atIndex) { 
     $('#tblData').dataTable().fnDeleteRow(atIndex); 
    } 
    }); 
}) 

И простой HTML будет, как:

<template name="data_table"> 
    <table class="table table-striped" id="tblData"> 
     <thead> 
      <th>Id</th> 
      <th>Name</th> 
     </thead> 
    </table> 
</template> 

Это работало, по крайней мере для меня. Я больше не вижу ошибок при флеше. А также, когда вы оказываете позже, иногда, отсутствовало сообщение с данными, доступное в datatable и которое также исчезло.