オプションが動的な場合、Meteor アプリで jQueryUI selectmenu を機能させるのに問題があります。私は使っている:
- メテオ 1.4.1
- jQuery 2.2.4
- jQueryUI 1.11.4
- ロダッシュ 4.15.0
physiocoder は別の質問で、「Meteor の反応性により、DOM 更新の担当者を選択する必要があります。」と述べています。
これがここでの私の問題の基本であることを認識しています。したがって、ページ/テンプレートが Meteor にすべてのページ コンテンツ/データをロードさせてから、DOM コントロールを jQueryUI のウィジェットに渡すことができる場合、問題はありません。ただし、ケーキを持って食べたい場合もあります-MeteorにjQueryUIウィジェットのオプション(特に現時点ではselectmenu)を反応的にフィードさせたいが、それでもjQueryUIにスタイリング/テーマを処理させたい.
テンプレート onRendered 関数での jQueryUI ウィジェットの初期化は問題なく機能し、必要に応じてテンプレート onDestroyed 関数で jQueryUI ウィジェットを破棄することもできます。selectmenu('refresh')
オプション テンプレートの onRendered 関数を呼び出すと、新しいオプションが利用可能になったときに selectmenu が更新されます。ただし、オプション テンプレートではなく、Meteor データ コンテキストを変更するイベントの最後ではなく、selectmenu が新しい正しい UI 状態に更新されるように、オプションが反応的に削除されたときに、refresh を効果的に呼び出すことができる場所を見つけることができません。 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 selectmenu には、選択したばかりのエントリが引き続き含まれます。high 以上の番号が付いた 2 番目のエントリを選択すると、実際には次のエントリが選択されます (たとえば、4 を選択してから 5 を選択すると、実際には 4 と 6 が選択されます)。