コンテンツの読み込み中に読み込み中のgifを表示するカスタムバインディングを作成しようとしています。
ko.bindingHandlers.loader = {
init: function (element) {
$('<div>').addClass('loader').hide().appendTo($(element));
},
update: function (element, valueAccessor) {
var isLoading = ko.utils.unwrapObservable(valueAccessor());
var $element = $(element);
var $children = $element.children(':not(.loader)');
var $loader = $(element).find('.loader');
if(isLoading) {
$children.stop(true).css('visibility', 'hidden').attr('disabled', 'disabled');
$loader.stop().fadeIn();
} else {
$loader.stop(true).fadeOut(function () {
$children.css('visibility', 'visible').removeAttr('disabled');
});
}
}
};
div.loader
に追加されているinitを確認できます。また、がtrueに変更されるとelement
update関数が起動することを確認できます。isLoading
しかし、イメージがロードされると(ロードされると、各イメージがそれぞれのロードイベントで解決されたpromiseを返すことを意味します)、一度isLoading
falseに設定された更新の起動は表示されません。
viewModel
function viewModel() {
var self = this;
self.movies = ko.observableArray([]);
self.searchValue = ko.observable();
self.isLoading = ko.observable(false);
self.search = function () {
self.isLoading = true;
$.getJSON(arguments[0].action, { name: this.searchValue() }, function (data) {
self.movies(data);
$.when.apply($, promises).done(function() {
setThumbnailHeight(function () {
self.isLoading = false;
});
});
});
};
var setThumbnailHeight = function(callback) {
var $items = $('.thumbnails li');
var maxHeight = Math.max.apply(null, $items.map(function () {
return $(this).innerHeight();
}).get());
$items.css('height', maxHeight);
callback();
};
}
ko.applyBindings(new viewModel());
setThumbnailHeight
は正しい時間に呼び出され(すべてのpromiseが解決されたら)、正しく機能しています。それぞれの高さをli
最大の高さに設定し、コールバック(この場合function(){ self.isLoading = false; }
は呼び出されている)を確認できます。
私のバインディング
<ul class="content thumbnails" data-bind="foreach: movies, loader: $root.isLoading">
<li class="movie">
...
</li>
</ul>
要約すると、問題は、がisLoading
trueに設定されている場合は読み込み中のgifが表示されますが、falseに設定されている場合は新しく読み込まれたコンテンツが非表示および表示されないことです。