Datatables 带有数据表的Meteor:Meteor.\u atFlush TypeError

Datatables 带有数据表的Meteor:Meteor.\u atFlush TypeError,datatables,meteor,Datatables,Meteor,我正在尝试使用Meteor的DataTables(通过mrt添加DataTables)。我尝试过将$(“#mytableid').dataTable()添加到Meteor.subscribe回调、Meteor.autorun、Meteor.startup、和Template.mytemplate.rendered——所有这些都会导致以下异常和表中没有可用数据 有什么建议吗 Exception from Meteor._atFlush: TypeError: Cannot call met

我正在尝试使用Meteor的DataTables(通过
mrt添加DataTables
)。我尝试过将
$(“#mytableid').dataTable()
添加到
Meteor.subscribe
回调、
Meteor.autorun
Meteor.startup
、和
Template.mytemplate.rendered
——所有这些都会导致以下异常和
表中没有可用数据

有什么建议吗

    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)

更新:可能与相关,找到的最佳解决方案是为每一行调用dataTable()——在这种情况下并不理想,而且在我的情况下,由于行数非常多,因此可能会带来灾难性后果。

由于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
  },

}))

Dror的答案肯定是正确的开始。以下是我目前的最佳实践:

HTML


{{{#常数}}
{{/常数}
JS:

Template.data\u table.created=function(){
var_watch=Collection.find({});
变量句柄=_watch.observe({
addedAt:函数(doc、atidex、beforeId){
$('tblData').is(“:visible”)&&$('tblData').dataTable().fnAddData(doc);
}
,changedAt:函数(newDoc、oldDoc、atidex){
$('tblData').is(“:visible”)&&$('tblData').dataTable().fnUpdate(newDoc,atIndex);
}
,removedAt:函数(oldDoc,atIndex){
$('tblData').is(“:visible”)&&$('tblData').dataTable().fnRemove(atIndex);
}
});
};
Template.data\u table.rendered=函数(){
if(!($(“#tblData”).hasClass(“数据表”)){
$('tblStudents')。数据表({
“aaSorting”:[]
,“sDom”:“t”
,“sPaginationType”:“引导”
,“语言”:{
“sLengthMenu”:“\u MENU\u每页记录”
}
,“AO列”:[
{“sTitle”:“First Data”,“mData”:函数(Data){return Data.firstData},
]
});
$('#tblData').dataTable().fnClearTable();
$('#tblData').dataTable().fnAddData(Collection.find().fetch());
}
};

以下是我在Meteor中使用CoffeeScript和HTML实现的dataTables。它可以工作,而且更简单,但效率可能低于现有的大型表解决方案(不过在我的例子中,它很快)

模板功能

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>

{{{#每个工作}
{{>jobRow}
{{/每个}}
{{normalTime date}}

其中dashboard.jobs是一个简单的.find(…)集合。

答案仍然有效,但两年后需要进行一些更改

  • 再也没有常数了
  • 不是空表,而是放置thead而不是tbody。这样可以正确定义列
  • 将观察者放在onRendered(不再渲染)和onCreated(不再创建)中。否则,表仅在第一次创建时填充,而不会在返回时填充
  • onRendered上的clear和fill方法不是必需的
  • 在observe方法中,确保添加的是数组而不是对象。否则fnAdd无法呈现内容
  • fnRemove已不存在。请改用fnDeleteRow
  • 我不确定是否需要“是否可见检查”。当您也删除它时,似乎没有问题,所以我删除了它
  • 根据上述说明,代码如下:

    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);
        }
      });
    })
    
    Template.creamDealsList.onRendered(函数(){
    if(!($(“#tblData”).hasClass(“数据表”)){
    $('tblStudents')。数据表({
    //这些配置并不十分重要,请使用它们,因为它们对您很方便
    “aaSorting”:[]
    ,“sDom”:“t”
    ,“sPaginationType”:“引导”
    ,“语言”:{
    “sLengthMenu”:“\u MENU\u每页记录”
    }
    ,“AO列”:[
    {“sTitle”:“First Data”,“mData”:函数(Data){return Data.firstData},
    ]
    });
    }
    var_watch=Collection.find({});
    var convertdoctoraray=函数(doc){return[doc.\u id,doc.name]}
    变量句柄=_watch.observe({
    addedAt:函数(doc、atidex、beforeId){
    $('#tblData').dataTable().fnAddData(convertdoctoraray(doc));
    }
    ,changedAt:函数(newDoc、oldDoc、atidex){
    $('#tblData').dataTable().fnUpdate(convertdoctoraray(newDoc),atIndex);
    }
    ,removedAt:函数(oldDoc,atIndex){
    $('#tblData').dataTable().fnleteRow(atIndex);
    }
    });
    })
    
    简单的HTML如下所示:

    <template name="data_table">
        <table class="table table-striped" id="tblData">
            <thead>
                <th>Id</th>
                <th>Name</th>
            </thead>
        </table>
    </template>
    
    
    身份证件
    名称
    

    这至少对我来说是有效的。我不再看到刷新错误。而且,当你以后渲染时,有时,数据表中有一条“无数据可用”的消息,这条消息也消失了。

    很有趣。让我来试一试。我有点不安,没有更直接的方法可以做到这一点。我会注意到,这很痛苦在大数据集上速度较慢。这种方法似乎一般有效,但有一些变化,请参阅下面的答案。这可能在当时使用,但现在它可以解决问题。在第一次呈现时,由于没有内容,表显示一条未找到数据的消息,当它不断呈现时,您还可以看到内容和“无数据”消息以后不会被删除。
    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);
        }
      });
    })
    
    <template name="data_table">
        <table class="table table-striped" id="tblData">
            <thead>
                <th>Id</th>
                <th>Name</th>
            </thead>
        </table>
    </template>