シナリオ用のフィドルを作成しました:
最後にテンプレート バインディングを使用して、オブザーバブル SelectedListItem() をテンプレート バインディングの data プロパティにバインドします。
setTimeout が 4 秒の非同期 ajax 呼び出しを偽装しています。次に、オブザーバブルと SelectedListItem にアラーム アイテムを入力します。
しかし、これは 4 秒遅すぎます。なぜなら、テンプレートにバインドされている alarmNumber でバインディング エラーが発生する前だからです。
テンプレートには ko with: SelectedListItem() bind が必要ですが、見たことはありません。
さらに、次のような ko コメントバインディングを使用できます
<!-- ko with: SelectedListItem() -->
<!-- template binding here... -->
<!-- /ko -->
その場合、すべての AlarmViewModel で監視可能な currentChildTemplate() を設定する必要があるため、まったく意味がありません。
どうすれば解決できますか?
HTML
<div id="rightHeader" style="float: right; background: green; height: 100%; width: 10%;">
</div>
<div style="clear: both;"></div>
</div>
<div style="float: right; background-color: seagreen;"></div>
</div>
<!-- /ko -->
<script id="map" type="text/html">
<div style="position: absolute; top: 200px; background-color: green; width: 300px; height: 200px;" data-bind="text: alarmNumber"></div>
</script>
<script id="response" type="text/html">
<div style="position: absolute; top: 200px; background-color: red; width: 300px; height: 200px;" data-bind="text: alarmNumber"></div>
</script>
<div data-bind="template: { name: currentChildTemplate(), data: $root.SelectedListItem() }"></div>
CSS
body, html {
width: 100%;
height: 100%;
padding: 0;
margin: 0;
}
.alarmTemplate {
height: 80px;
margin: 10px;
background: lightgray;
border: black solid 1px;
padding-left: 5px;
}
#alarmListContainer {
height: 80px;
background: yellow;
vertical-align: middle;
background: gray;
border: black solid 1px;
display: table;
width: 100%;
margin: 0 auto;
}
#navigationWheeler {
background: yellow;
display: table-cell;
vertical-align: middle;
}
.selected {
background-color: #0094ff;
}
#toggleButtonLeft {
border: black solid 1px;
cursor: pointer;
text-align: center;
width: 40px;
}
#toggleButtonRight {
width: 40px;
border: black solid 1px;
cursor: pointer;
text-align: center;
}
* {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
.cellContainer {
width: 20%;
float: left;
}
ジャバスクリプト
function AlarmWheelViewModel(alarms) {
var self = this;
self.SelectedListItem = ko.observable();
self.selectListAlarm = function (alarm) {
self.SelectedListItem(alarm);
}
var alarms = [];
for (var i = 0; i < 10; i++) {
var alarmVM = new AlarmViewModel(i, 'test' + i, 'yeahh', self.SelectedListItem);
alarms.push(alarmVM);
}
self.currentChildTemplate = ko.observable('response');
self.visibleAlarms = ko.observableArray(); // Display only the first 5 alarms
self.hiddenAlarms = ko.observableArray(); // Hide the remaining alarms
// faking async ajax call here to test how the UI behaves when the SelectedListItem is not set yet
// the result is that alarmNumber can not be bound just as I have expected :/
setTimeout(getData, 4000);
function getData() {
self.visibleAlarms(alarms.slice(0, 5)); // Display only the first 5 alarms
self.hiddenAlarms(alarms.slice(5)); // Hide the remaining alarms
self.SelectedListItem(self.visibleAlarms()[1]);
};
self.hideCurrentAlarm = function () {
$('#currentAlarm').hide();
}
self.hideAlarmList = function () {
$('#currentAlarm').show();
};
}
function AlarmViewModel(alarmNumber, alarmMessage, alarmAddress, selected) {
var that = this;
that.alarmNumber = alarmNumber;
that.alarmMessage = alarmMessage;
that.alarmAddress = alarmAddress;
that.isSelected = ko.computed(function () {
return selected() === that;
});
}
var vm = new AlarmWheelViewModel();
ko.applyBindings(vm);