0

I am having trouble making the jQueryUI selectmenu work in a Meteor app when the options are dynamic. 我在用:

  • 流星 1.4.1
  • jQuery 2.2.4
  • jQueryUI 1.11.4
  • lodash 4.15.0

physiocoder 在另一个问题上说: “Meteor 反应性迫使您选择负责 DOM 更新的人员。”。

我意识到这是我的问题的基础。因此,如果页面/模板可以让 Meteor 加载所有页面内容/数据,然后将 DOM 控制权交给 jQueryUI 的小部件,则没有问题。但是,我有一个案例,我想吃蛋糕也想吃——我想让 Meteor 响应式地提供 jQueryUI 小部件的选项(特别是目前的选择菜单),但仍然让 jQueryUI 处理样式/主题。

在模板 onRendered 函数中初始化 jQueryUI 小部件工作得很好,在必要时在模板 onDestroyed 函数中销毁 jQueryUI 小部件也是如此。当新选项可用时,调用selectmenu('refresh')选项模板的 onRendered 函数会刷新选择菜单。However, I cannot find anywhere I can effectively call refresh when options are reactively removed such that the selectmenu is refreshed to the new, correct UI state -- not at the end of the event which changes the Meteor data context, not on the option template's onDestroyed 函数,而不是绑定到适当数据源的 Tracker.autorun 函数。

HTML:

<head>
  <title>Proof of Concept</title>
</head>

<body>
  <div id="myApp">
    {{> myForm}}
  </div>
</body>

<template name="myForm">
  <div>
    <div id="selectedEntries">
      <h3>Selected Entries</h3>
      <ul class="display-list">
        {{#each entry in selectedEntries}}
          {{> myForm_entry entry}}
        {{/each}}
      </ul>
    </div>

    <br/>

    <form id="includeEntry">
      <select name="entryToInclude" id="entryToInclude">
        {{#each potentialEntry in availableEntries}}
          {{> myForm_option potentialEntry}}
        {{/each}}
      </select>
      <input type="submit" value="Include Entry">
    </form>
  </div>
</template>

<template name="myForm_entry">
  <li>
    <div class="button removeEntry" data-id="{{_id}}">X</div>
    <span>{{name}}</span>
  </li>
</template>

<template name="myForm_option">
  <option value="{{_id}}">{{name}}</option>
</template>

JavaScript:

Template.myForm.helpers({
  availableEntries: function () {
    return _.filter(Session.get('someEntries'), function(o) {
      return Session.get('selectedEntryIds').indexOf(o._id) == -1;
    });
  },
  selectedEntries: function () {
    return _.filter(Session.get('someEntries'), function(o) {
      return Session.get('selectedEntryIds').indexOf(o._id) != -1;
    });
  }
});

Template.myForm.events({
  'submit #includeEntry': function (event) {
    event.preventDefault();

    if (_.isEmpty(Session.get('selectedEntryIds'))) {
      Session.set('selectedEntryIds', [$('#entryToInclude').val()]);
    } else {
      let selectedEntryIds = Session.get('selectedEntryIds');
      selectedEntryIds.push($('#entryToInclude').val());
      Session.set('selectedEntryIds', selectedEntryIds);
    }
    $('#entryToInclude').selectmenu('refresh')
  },
  'click .removeEntry': function (event) {
    event.preventDefault();

    let selectedEntryIds = Session.get('selectedEntryIds');
    selectedEntryIds = _.pull(selectedEntryIds, $(event.target).parent().attr('data-id'));
    Session.set('selectedEntryIds', selectedEntryIds);
  }
});

Template.myForm.onCreated(function () {
  let someEntries = [{
    _id:'1',
    name:'One'
  },{
    _id:'2',
    name:'Two'
  },{
    _id:'3',
    name:'Three'
  },{
    _id:'4',
    name:'Four'
  },{
    _id:'5',
    name:'Five'
  },{
    _id:'6',
    name:'Six'
  }];
  Session.set('someEntries', someEntries);
  Session.set('selectedEntryIds', []);
});

Template.myForm.onRendered(function () {
  $('#entryToInclude').selectmenu();
  $('input:submit').button();
});
Template.myForm_entry.onRendered(function () {
  $('.button').button();
});
Template.myForm_option.onRendered(function () {
  if ($('#entryToInclude').is(':ui-selectmenu')) {
    $('#entryToInclude').selectmenu('refresh');
  }
});

Template.myForm_option.onDestroyed(function () {
  $('#entryToInclude').selectmenu('refresh');
});

Tracker.autorun(function () {
  if (Session.get('selectedEntryIds')) {
    if ($('#entryToInclude').is(':ui-selectmenu')) {
      $('#entryToInclude').selectmenu('refresh');
    }
  }
});

#entryToInclude 选择菜单继续包含刚刚选择的条目;选择编号为高或更高的第二个条目实际上会选择后续条目(例如,选择 4 然后选择 5 实际上会选择 4 和 6),除了在成功选择后立即选择最后一个条目只会刷新选择菜单。

4

1 回答 1

0

向条目模板的 onRendered 函数添加刷新可以使这项工作正常进行。

Template.myForm_entry.onRendered(function () {
  $('.button').button();
  if ($('#entryToInclude').is(':ui-selectmenu')) {
    $('#entryToInclude').selectmenu('refresh');
  }
});

但是对整个问题的更好方法将不胜感激。

于 2016-08-23T21:46:01.543 回答