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),除了在成功选择后立即选择最后一个条目只会刷新选择菜单。