Blaze 模板遍历对象

Blaze template iterate over object

我正在尝试遍历 blaze 模板 (meteor) 中的一个对象,在控制台中我可以看到数据,但在 template.How 上什么也看不到,我可以让它工作吗? #each 不工作,arrayify 也没有工作。


从评论添加到这里:

{{#each contactList}} 
 <tr class="clickable" name="edit-contact" >
   <td>{{name}} </td>
   <td>{{email}} </td>
   <td>{{title}}</td>
   <td>{{phone1}}</td>
   <td>{{phone2}}</td>
   <td>{{phone3}}</td>
 </tr>
{{/each}}

JS:

contactList: function() { 
  $.ajax({ 
    url: Meteor.absoluteUrl()+'contacts/get_by_company/'+Session.get(‌​'company_id'),
    type: 'GET',
    error: function() { callback(); }, 
    success: function(res) { console.log(res); return res; }, 
  });
}

回答您的主要问题,您的模板没有迭代的原因是您的 contactList 函数根本没有 returning 任何东西。即使它做了 return 某些事情,由于您的方法,它仍然可能无法正常工作。不幸的是,解决这个问题的方法不仅仅是添加一个简单的 return 语句,而是改变你的整个方法。

首先,我会 高度 鼓励您阅读并遵循 Blaze Tutorial 从头到尾,然后再 return 回到您的项目. 根据您共享的示例代码,很明显您误解了 Meteor 的大部分基础知识(这很遗憾,因为 Meteor 是一个非常强大且令人愉快的框架)。希望我能帮助解决一些问题,但在尝试进入之前了解 Meteor 的工作原理绝对是必不可少的。

我在这里看到的最大问题是您正在定义 API 端点并从前端使用它们。虽然这在其他 frameworks/technologies 中是一种相当正常的方法,但服务器和客户端之间的关系在 Meteor 中是完全不同的。事实上如此不同,以至于只有一个例子才能证明这种差异。

根据您在问题中提供的内容,我重写了所有内容以解释如何在 Meteor 中处理此问题。

首先是模板定义(此处没有实际更改)。

<template name="manageContacts">
  <table>
    <thead>
      <tr>
        <th>Name</th>
        <th>Email</th>
        <th>Title</th>
        <th>Phone 1</th>
        <th>Phone 2</th>
        <th>Phone 3</th>
      </tr>
    </thead>
    <tbody>
      {{#each contact in contactList}} 
      <tr class="clickable" name="edit-contact" >
        <td>{{contact.name}}</td>
        <td>{{contact.email}}</td>
        <td>{{contact.title}}</td>
        <td>{{contact.phone1}}</td>
        <td>{{contact.phone2}}</td>
        <td>{{contact.phone3}}</td>
      </tr>
      {{/each}}
    </tbody>
  </table>
</template>

然而,接下来的部分却大不相同。请注意,我真的不建议在同一个文件中组合仅服务器和客户端代码,但我在这种情况下这样做是为了节省 space.

const Contacts = new Mongo.Collection('contacts');

if (Meteor.isServer) {
  Meteor.publish('contacts', function() {
    return Contacts.find();
  });
}

if (Meteor.isClient) {
  Template.manageContacts.onCreated(function() {
    Meteor.subscribe('contacts');
  });

  Template.manageContacts.helpers({
    contactList: function() {
      return Contacts.find({
        company_id: Session.get(‌​'company_id')
      });
    }  
  });
}

我们在这里要做的是创建一个联系人 mongo 集合,它将存储所有联系人数据。然后我们在服务器上定义一个发布函数,将所有联系人数据发布到客户端。我们从客户端(例如模板)订阅发布(这是模板获取其数据的方式)并向模板提供辅助函数(contactList),return 是 mongo光标。 Blaze 当然可以遍历光标,我们所有的联系人都将呈现在屏幕上。

您的 contactList 助手没有为您提供预期联系人列表的直接原因是您调用了一个 异步 函数 ($.ajax) 并且那个电话之后不要 return 任何东西。

How do I return the response from an asynchronous call?

Meteor 不知道您的异步调用何时完成,也不知道其结果。

如果你真的需要保持你的AJAX调用,你可以将结果存储在ReactiveVar and read it in your helper. Meteor knows that it should automatically re-run your helper中,只要反应源在该助手中更新功能。因此,您的模板将在结果到达时自动接收。

import { ReactiveVar } from 'meteor/reactive-var'

var contacts = new ReactiveVar();

Template.templateName.onCreated(function () {
    $.ajax({ 
        url: Meteor.absoluteUrl()+'contacts/get_by_company/'+Session.get(‌​'company_id'),
        type: 'GET',
        error: function() { callback(); }, 
        success: function (res) {
            console.log(res);
            contacts.set(res); // Update the reactive var.
            return res; // Useless.
        }
    });
});

Template.templateName.helpers({
    contactList: function () {
        return contacts.get(); // Will get updated later on and Meteor will automatically refresh the helper.
    }
});

也就是说,正如@jordanwillis 指出的那样,在 Meteor 中几乎不需要 REST 端点。如果您可以重构检索联系人列表的方式,您可以获得更像 Meteor 的结构,并具有其所有优点(实时更新、在客户端处理数据的灵活性等)