使用 Meteor 和 blaze 在掌上电脑上正确加载数据

Posted

技术标签:

【中文标题】使用 Meteor 和 blaze 在掌上电脑上正确加载数据【英文标题】:Loading data correctly on handsontable with Meteor and blaze 【发布时间】:2017-01-03 10:00:09 【问题描述】:

我通过插件 awsp:handsontable@0.16.1 在 Meteor 1.4.1 上使用 handsontable

我遇到的问题是每次更改值时都会重新渲染矩阵,这会产生两个问题。首先是编辑单元格的焦点丢失,滚动回到顶部。第二个是有时值没有保存,因为每次更改都会重新加载矩阵的数据。

我订阅数据和渲染表格的方式如下:

Template.connectivityMatrix.onCreated(function () 
  this.activeScenario = () => Session.get('active_scenario');

  this.autorun(() => 
    this.subscribe('connectivityMatrixUser', this.activeScenario());
  );
);

Template.connectivityMatrix.onRendered(function () 
  this.autorun(() => 
    if (this.subscriptionsReady()) 
      const activeScenario = Session.get('active_scenario');
      const currentScenario = Scenarios.findOne(_id: activeScenario);
      const currentTurn = currentScenario.turn;
      const numObj = ConnectivityMatrix.find(scenario_id: activeScenario, user_id: Meteor.userId(), turn: currentTurn).count();

      var myData = [];  // Need this to create instance
      var container = document.getElementById('connectivity-matrix');

      var hot = new Handsontable(container,  // Create Handsontable instance
        data: myData,
        startRows: numObj,
        startCols: numObj,
        afterChange: function (change, source)   // 'change' is an array of arrays.
          if (source !== 'loadData')   // Don't need to run this when data is loaded
            for (i = 0; i < change.length; i++)    // For each change, get the change info and update the record
              var rowNum = change[i][0]; // Which row it appears on Handsontable
              var row = myData[rowNum];  // Now we have the whole row of data, including _id
              var key = change[i][1];  // Handsontable docs calls this 'prop'
              var oldVal = change[i][2];
              var newVal = change[i][3];
              var setModifier = $set: ;   // Need to build $set object
              setModifier.$set[key] = newVal; // So that we can assign 'key' dynamically using bracket notation of javascript object
              ConnectivityMatrix.update(row._id, setModifier);
            
          
        
      );

      myData = ConnectivityMatrix.find(scenario_id: activeScenario, turn: currentTurn, user_id: Meteor.userId(), sort: created_at: 1).fetch();  // Tie in our data
      hot.loadData(myData);
    
  );
);

我想要实现的是只创建一次矩阵,而不是在每次数据更改时重新创建它,以便保持焦点并始终保存数据。 因此,我尝试按照 question 中的建议仅在 this.autorun() 的块中保留最后两行@

Template.connectivityMatrix.onRendered(function () 
  const activeScenario = Session.get('active_scenario');
  const currentScenario = Scenarios.findOne(_id: activeScenario);
  const currentTurn = currentScenario.turn;
  const numObj = ConnectivityMatrix.find(scenario_id: activeScenario, user_id: Meteor.userId(), turn: currentTurn).count();

  var hot = new Handsontable(container,  // Create Handsontable instance
    ...
  );

  this.autorun(() => 
    if (this.subscriptionsReady()) 
      myData = ConnectivityMatrix.find(scenario_id: activeScenario, turn: currentTurn, user_id: Meteor.userId(), sort: created_at: 1).fetch();  // Tie in our data
      hot.loadData(myData);
    
  );
);

但是当我第一次加载页面时,数据不可用所以我收到错误

无法读取未定义的属性“转”

因此,如何正确获取创建表格所需的所有数据,而无需在单元格值更改时重新渲染它?

提前感谢您的帮助。

【问题讨论】:

【参考方案1】:

您正在尝试在 Scenarios 和 ConnectivityMatrix 集合准备好之前对其进行查询。将所有 mongo 查询移到 this.subscriptionsReady() 条件块中。

【讨论】:

嗨@cstricklan,如果我这样做了,那么 const numObj 不能用于初始化新 Handsontable 对象的属性 startRowsstartCols。还有其他建议吗? 将热点的创建也移动到 subscriptionsReady 块中。您需要使用 if 语句仅在热尚不存在时才创建它。【参考方案2】:

我设法做我需要的方法是在矩阵被渲染后停止计算。代码如下:

Template.connectivityMatrix.onRendered(function ()     
  this.autorun((computation) => 
    if (this.subscriptionsReady())     
      const currentScenario = Scenarios.findOne(_id: activeScenario);
      const currentTurn = currentScenario.turn;
      const numObj = ConnectivityMatrix.find(scenario_id: activeScenario, user_id: Meteor.userId(), turn: currentTurn).count();

      var myData = [];  // Need this to create instance
      var container = document.getElementById('connectivity-matrix');

      var hot = new Handsontable(container,  // Create Handsontable instance
        data: myData,
        colHeaders: arrayRowsCols,
        rowHeaders: arrayRowsCols,
        height: '450',
        maxRows: numObj,
        maxCols: numObj,
        columns: columns,
        afterChange: function (change, source)   // 'change' is an array of arrays.
          if (source !== 'loadData')   // Don't need to run this when data is loaded
            for (i = 0; i < change.length; i++)    // For each change, get the change info and update the record
              var rowNum = change[i][0]; // Which row it appears on Handsontable
              var row = myData[rowNum];  // Now we have the whole row of data, including _id
              var key = change[i][1];  // Handsontable docs calls this 'prop'
              var oldVal = change[i][2];
              var newVal = change[i][3];
              var setModifier = $set: ;   // Need to build $set object
              setModifier.$set[key] = newVal; // So that we can assign 'key' dynamically using bracket notation of JavaScript object
              ConnectivityMatrix.update(row._id, setModifier);
            
          
        
      );

      myData = ConnectivityMatrix.find(scenario_id: activeScenario, turn: currentTurn, user_id: Meteor.userId(), sort: created_at: 1).fetch();  // Tie in our data
      hot.loadData(myData);
      computation.stop();
    
  );
);

【讨论】:

以上是关于使用 Meteor 和 blaze 在掌上电脑上正确加载数据的主要内容,如果未能解决你的问题,请参考以下文章

Meteor + Blaze - If else 语句

Angular、React 和 Blaze(客户端 Meteor)之间的主要设计差异? [关闭]

使用 blaze (meteor) 模板引擎在 Iron-icons 中设置的 Polymer 1.0 默认图标不工作

带有 Meteor 的 Blaze-Apollo,观察者不会触发变量更改的订阅

Meteor/Blaze - 参数中的简单字符串连接

Meteor Blaze 访问 Template.onCreated 内的 Template.contentBlock