我正在使用RPNiemeyer kendo-knockout库。我有一个网格。当用户点击一行网格时,会显示一个弹出窗口。当您关闭窗口并以相同的方式再次打开它时,应用程序冻结关闭动画。我尽可能地尝试用小提琴重现这个场景。 当您关闭弹出窗口并再次单击该行时,没有任何反应并重新加载浏览器。我坚信在我的申请中会发生类似的事情。
HTML:
<div data-viewId="languageList" >
<div id="languageList" data-bind="with: viewModel">
<div id="languageListGrid" data-bind="kendoGrid: { data: languageViewModels, columns: [
{
template: '<a href=\'\' data-bind=\'click: function() { onLanguageSelected("#=Language#") }\'>#=Language#</a>',
field: 'Language',
title: 'Language',
width: 50
}
],
scrollable: false, sortable: true, pageable: false }" style="height: 380px">
</div>
</div>
</div>
<div data-viewid="languageDetails">
<div id="languageDetails" data-bind="with: viewModel" class="hidden">
<form id="languageDetailsForm" action="" style="font-family: Trebuchet MS, Verdana, Helvetica, Sans-Serif;">
<div data-bind="kendoWindow: {isOpen: isOpen, title:'Language', width: 400, height: 200, modal: true }" >
test
<button id="cancelLanguage" class="k-button" data-bind="click: cancelLanguage">Cancel</button>
</div>
</form>
</div>
</div>
的javascript:
$(function () {
var elementIsBoundNew = function (element) {
return !!ko.dataFor(element);
}
var applyBindings = function (viewModel, elementId) {
var element = $('div[data-viewId="' + elementId + '"]')[0];
if (!elementIsBoundNew(element)) {
var parentViewModel = { viewModel: viewModel };
ko.applyBindings(parentViewModel, element);
}
};
var FranchiseDetailsViewModel = function () {
var
self = this,
initialize = function () {
self.languagesInfoViewModel(new LanguageListViewModel(self));
applyBindings(self.languagesInfoViewModel, "languageList");
};
FranchiseDetailsViewModel.prototype.languagesInfoViewModel = ko.observable();
initialize();
};
var LanguageListViewModel = function (franchise) {
var
self = this,
initialize = function () {
var languageViewModel = new LanguageDetailsViewModel(franchise);
self.languageViewModels.push(languageViewModel);
};
LanguageListViewModel.prototype.languageViewModels = ko.observableArray([]);
LanguageListViewModel.prototype.selectedLanguageViewModel = ko.observable();
LanguageListViewModel.prototype.onLanguageSelected = function (selectedLanguage) {
// when you uncomment this line everyting works fine
//var language = new LanguageDetailsViewModel();
self.selectedLanguageViewModel(self.languageViewModels()[0]);
applyBindings(self.selectedLanguageViewModel, "languageDetails");
self.selectedLanguageViewModel().openPopUp();
};
initialize();
};
var LanguageDetailsViewModel = function () {
var
self = this,
closePopUp = function () {
self.isOpen(false);
};
self.Language = ko.observable("English");
LanguageDetailsViewModel.prototype.isOpen = ko.observable(false);
LanguageDetailsViewModel.prototype.openPopUp = function () {
self.isOpen(true);
};
LanguageDetailsViewModel.prototype.cancelLanguage = function () {
closePopUp();
};
};
var initialize = new FranchiseDetailsViewModel();
});
奇怪的是,如果我将这行代码添加到我的onLanguageSelected方法中,每个工作都很好:
var language = new LanguageDetailsViewModel();
小提琴:
非常感谢任何有关工作示例的帮助。谢谢!
根据RPNiemeyer的帖子更新:
我添加了这些代码行以使用此处Kendo-Knockout: Calling a method that changes viewmodel property from a template with data-binding inside a grid, breaks bindings的技术:
ko.bindingHandlers.preventBinding = {
init: function() {
return { controlsDescendantBindings: true };
}
};
ko.bindingHandlers.kendoGrid.options.dataBound = function(data) {
var body = this.element.find("tbody")[0];
if (body) {
ko.applyBindings(ko.dataFor(body), body);
}
};
这正是我的应用程序中发生的事情。当我打开弹出窗口时,关闭它然后再次打开它第二次没有正确关闭。请看我更新的小提琴:
我错过了什么?再次感谢您的反馈!
答案 0 :(得分:1)
看起来窗户关闭后没有正确清理。这通常不是问题(并且是可取的),但如果网格被重新渲染,则初始化新的kendoWindow
,但不知道那里已经存在窗口。
可能可以在knockout-kendo代码中处理这个问题。窗口的destroy
方法已被调用,因此我需要研究为什么它实际上没有删除窗口元素。
现在的解决方法是为窗口关闭时配置全局处理程序,如:
ko.bindingHandlers.kendoWindow.options.close = function() {
$('.k-window, .k-overlay').remove();
};
答案 1 :(得分:1)
这是淘汰赛中的一个错误。
不调用窗口的destroy
方法。这是因为knockout-kendo检测到从dom中删除小部件时需要销毁它。但是,kendoWindow
会将元素移动到dom的末尾。当knockout.js在更新期间清除或删除元素时,它不会删除元素,因为元素已被移动。
这可以通过修改knockout-kendo来修复,这样就可以留下创建kendoWindow
的元素所在的代理元素,以及destroy
小部件kendoWindow
代理元素被处置。对knockout-kendo 0.7.0的以下更改实现了这一点:
--- knockout-kendo-0.7.0.js
+++ knockout-kendo-0.7.0.js
@@ -62,14 +62,19 @@
return { controlsDescendantBindings: true };
}
};
//build the core logic for the init function
binding.setup = function(element, options, context) {
- var widget, $element = $(element);
+ var widget, $element = $(element), $disposeProxy;
+ // Create proxy in original location to capture when the element would have been disposed
+ if (widgetConfig.destroyByProxy) {
+ $disposeProxy = $('<div style="display: none" />').insertAfter($element);
+ }
+
//step 2: setup templates
self.setupTemplates(widgetConfig.templates, options, element, context);
//step 3: initialize widget
widget = self.getWidget(widgetConfig, options, $element);
@@ -78,12 +83,17 @@
//step 5: set up computed observables to update the widget when observable model values change
self.watchValues(widget, options, widgetConfig, element);
//step 6: handle disposal, if there is a destroy method on the widget
if(widget.destroy) {
+ if ($disposeProxy) {
+ ko.utils.domNodeDisposal.addDisposeCallback($disposeProxy[0], function() {
+ widget.destroy();
+ });
+ }
ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
widget.destroy();
});
}
};
@@ -768,13 +778,16 @@
}
},
watch: {
content: CONTENT,
title: TITLE,
isOpen: [OPEN, CLOSE]
- }
+ },
+ // The dom element that contains the window isn't going to be disposed when the template containing it is rendered again.
+ // This is because the window's dom element is placed at the end of the document structure by kendoWindow
+ destroyByProxy: true
});
createBinding({
name: "kendoChart",
watch: {
data: function(value) {