【问题标题】:How could I make this Meteor code reactive?我怎样才能让这个 Meteor 代码反应?
【发布时间】:2016-08-22 04:05:27
【问题描述】:

我有许多“多个”选择器,但为了这个示例,假设我有两个。

<form class="input-field col s10">
  <select multiple id="jans-room21">
    <option value="" disabled selected>Add Names</option>
    {{#each Jans21}}
        <option value= '{{FullName}}' selected = {{formatSelectedNames21 RoomJans}} >{{FullName}}</option>
    {{/each}}
  </select>
</form>

<form class="input-field col s10">
  <select multiple id="jans-room22">
    <option value="" disabled selected>Add Names</option>
    {{#each Jans22}}
      <option value='{{FullName}}' selected = {{formatSelectedNames22 RoomJans}}>{{FullName}}</option>
    {{/each}}
  </select>
</form>

Jans21 和 Jans22 正在从数据库返回一些文档。它们将显示该房间的选定名称,或者那些没有“RoomJans”属性或“RoomJans”等于“”的名称。它们将排除在另一个选择器中选择的那些名称。

Template.jansNameSelect.helpers({ 
  Jans21: function () { 
    return Programs.find({ $and: [{ CampYear: Session.get('GlobalCurrentCampYear') }, { $or: [{ RoomJans: '' }, { RoomJans: { $exists: 0 }}, { RoomJans: { $in: ['21A', '21B'] }}]}]}, { sort: { FullName: 1 }}).fetch();
  },

  Jans22: function () {
    return Programs.find({ $and: [{ CampYear: Session.get('GlobalCurrentCampYear') }, { $or: [{ RoomJans: '' }, { RoomJans: { $exists: 0 }}, { RoomJans: { $in: ['22A', '22B'] }}]}]}, { sort: { FullName: 1 }}).fetch();
  }
});

单击按钮时,会调用一个方法来更新数据库并存储这些名称。

// ...
$('#room_21_jans_button').on('click', function() {
var roomValue = $('input[name="room_select_21_jans"]:checked').val();
if (roomValue) {
  var selectedValues = [];
  $r21jans.find("option:selected").each(function () {
    selectedValues.push($(this).val());
  });
  selectedValues.splice(0, 1);
  var unselectedValues = [];
  $r21jans.find("option:not(:selected)").each(function () {
    unselectedValues.push($(this).val());
  });
  Meteor.call('roomUpdateSN',
    selectedValues,
    unselectedValues,
    roomValue,
    Session.get('GlobalCurrentCampYear')
  );
//...

我所追求的是,​​当在第一个选择器中选择名称并随后保存到数据库时,第二个选择器将更新其名称列表以删除从第一个选择器中选择的名称。我原以为这将是反应性的,因为我正在执行数据库操作,因此如果从第一个选择器中选择名称并将其保存到数据库,则“Jans22”函数将再次触发。但事实并非如此。但是,它会在刷新时加载正确的名称。有没有办法让它变得被动?

【问题讨论】:

  • 您的代码乍一看应该是反应式的。您是否使用在呈现后操纵选择的 UI 组件?如果是这样,在选项更新后可能需要刷新。
  • 想一想,我正在使用 Materialize 选择器。我想知道这些选择器是否不会响应 Meteor 的反应?

标签: meteor meteor-blaze


【解决方案1】:

在 Meteor 模板之上使用 UI 组件框架时,您需要告诉框架它下面的模板何时发生变化。这是因为框架(在本例中为具体化)使用模板呈现的&lt;select&gt; 作为输入,然后创建一组新的 DOM 元素来呈现所需的 UI 外观。如果&lt;option&gt;的变化,你需要告诉框架重新运行这个过程。

在这种情况下你需要重新运行

$('select').material_select();

每次都有变化。在我看来,最简单的方法是使用辅助函数本身的延迟函数:

Template.jansNameSelect.helpers({ 
  Jans21: function () { 
    Meteor.defer( function() { $('select#jans-room21').material_select(); } );
    return Programs.find({ $and: [{ CampYear: Session.get('GlobalCurrentCampYear') }, { $or: [{ RoomJans: '' }, { RoomJans: { $exists: 0 }}, { RoomJans: { $in: ['21A', '21B'] }}]}]}, { sort: { FullName: 1 }}).fetch();
  },

  Jans22: function () {
    Meteor.defer( function() { $('select#jans-room22').material_select(); } );
    return Programs.find({ $and: [{ CampYear: Session.get('GlobalCurrentCampYear') }, { $or: [{ RoomJans: '' }, { RoomJans: { $exists: 0 }}, { RoomJans: { $in: ['22A', '22B'] }}]}]}, { sort: { FullName: 1 }}).fetch();
  }
});

【讨论】:

  • 哇,你说得对。我只在渲染模板时初始化了一次选择器。不过,UI 的重新运行似乎需要在返回 Programs.find() 之后进行,因为返回后的代码不会运行,所以这不起作用。在 Jans21 函数返回后 Meteor.defer 是否等待运行?
  • 没错。它将在所有当前计划的事件(包括模板重新渲染)完成后运行。
  • 在defer方法里面运行$('select#jans-room21').material_select(),而不仅仅是$('select').material_select()有什么好处吗?两者似乎都能胜任。
  • 后者将命中所有选择,即使没有必要也会更新它们,让您损失几毫秒:-)
  • 但是点击模板中的所有选择器正是我需要发生的事情。因此,将一个 $('select').material_select() 放在 10 个辅助函数(我有 10 个选择器)中的任何一个中可能是有意义的,比如 'Jans22' 函数。除非说 $('select').material_select() 会更新应用程序中的所有选择器,这是我不想要的。
猜你喜欢
  • 2012-10-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-19
  • 1970-01-01
  • 1970-01-01
  • 2021-02-26
  • 2012-09-02
相关资源
最近更新 更多