我创建了一个名为statusAlert
的“简单”警报窗口小部件,用于在数据无法按预期到达时显示消息。到目前为止,我无法将数据输入其中。我想我可以在窗口小部件中注入一个observable,并在observable设置为一个对象时显示并填充窗口小部件。但我还没弄清楚如何使这个概念有效。
statusAlert / view.html
<div class="alert alert-danger" role="alert" data-bind="visible: content">
<button type="button" class="close" aria-label="Close" data-bind="click: hide"><span aria-hidden="true"><i class="fa fa-times"></i></span></button>
<button type="button" class="close" aria-label="Show Details" data-bind="click: showDetails"><span aria-hidden="true"><i class="fa fa-info-circle"></i></span></button>
<p class="lead" data-bind="text: header"></p>
<p data-bind="text: message"></p>
<p data-bind="visible: detailsIsVisible"><pre data-bind="text: details"></pre></p>
</div>
statusAlert / viewmodel.js
define(['knockout'], function (ko) {
var ctor = function () {
this.content = ko.observable();
this.detailsIsVisible = ko.observable(false);
};
// Methods.
// Activate event handler.
ctor.prototype.activate = function () {
//TODO What goes here?
};
// Destroying the content will result in the alert becoming invisible.
ctor.prototype.hide = function () {
this.content(null);
};
ctor.prototype.showDetails = function () {
this.detailsIsVisible(true);
};
// Data fields: Computed observables that extract data from 'content.'
ctor.prototype.header = ko.computed(function () {
if (this.content) {
return this.content() ? this.content().header : null;
}
return null;
}, this);
ctor.prototype.message = ko.computed(function () {
if (this.content) {
return this.content() ? this.content().message : null;
}
return null;
}, this);
ctor.prototype.details = ko.computed(function () {
if (this.content) {
return this.content() ? this.content().details : null;
}
return null;
}, this);
return ctor;
});
来自父视图模型的相关代码
var statusAlertObservable = ko.observable();
$.ajax({
success: function (data, status, request) {
if (data.ResponseStatus.ErrorCode) {
statusAlertObservable({
header: "Service reports error.",
message: data.ResponseStatus.Message,
details: data.ResponseStatus
});
} else {
// (do something with data)
}
},
error: function (data, status, error) {
statusAlertObservable({
header: "Error getting application data.",
message: error,
details: data
});
}
});
return {
statusAlertObservable: statusAlertObservable,
//...
}
来自父视图的相关代码
<div data-bind="statusAlert: 0"></div>
答案 0 :(得分:1)
首先,需要调整父数据绑定。它应该如下:
<div data-bind="widget: {kind: 'statusAlert', ...}"></div>
省略号表示您可能传递到窗口小部件的属性:
<div data-bind="widget: {kind: 'statusAlert', config: {alertObservable: statusAlertObservable}}"></div>
请注意, config 属性是任意的。我可以把它命名为任何东西。我还可以包括我希望的任何其他自定义属性。
这里有一个微妙之处:在上面的代码中,我传递了可观察的本身,而不是可观察的值。这意味着在我的小部件的activate
处理程序中,我需要取消引用observable以获取它的值。或者,您可以通过这种方式传递值:
<div data-bind="widget: {kind: 'statusAlert', config: {alertObservable: statusAlertObservable()}}"></div>
请注意statusAlertObservable
上的括号。我不需要在小部件的viewModel中取消引用这个observable,因为它已被取消引用。
其他几件事
确保将窗口小部件的视图和viewModel放在窗口小部件文件夹中带有窗口小部件名称的文件夹下。这是我们的截图:
在您的情况下,小部件文件夹下的文件夹名称将为 statusAlert 。
其次,请确保为窗口小部件的viewModel viewModel.js
和窗口小部件的视图view.html
命名。如果不编写自定义viewLocator
,则不支持其他名称。因此,它是包含文件夹的名称 - 在本例中为 statusAlert - 即控制命名约定。
第三,在您的小部件的viewModel中添加一个名为activate
的激活处理程序(必须将其调用),您可以在其中传递widgetSettings
:
ctor.prototype.activate = function (widgetSettings) {
this.statusAlertObservable = widgetSettings.config.alertObservable;
//alternatively: this.statusAlertObservable = widgetSettings.config.alertObservable();
};
Durandal会自动将您的小工具绑定属性传递为&#34;设置&#34;在activate
处理程序上。
第四,为小部件的构造函数ctor
命名并不是一个好主意。这使得调试变得非常困难,特别是如果它们都以这种方式命名的话。在您的情况下,将其命名为StatusAlert
(在Pascal情况下,因为它是构造函数)。
最后,请查看Durandal关于小部件的文档here。
<强>更新强>
正如OP在他的评论中指出的那样,你可以注册你的小部件绑定,然后简单地用一个香草data-bind
绑定它们。
我不推荐这种方法。当你有很多小部件绑定时,特别是在大型应用程序中,它很难通过搜索访问它们。此外,其他人很难区分自定义Knockout绑定和小部件,因为没有明显的区别。在一个大的代码库中,程序员自己甚至可能开始怀疑哪个是哪个,然后必须访问他的main.js文件或他的自定义Knockout绑定来确定哪个是哪个。
至少,如果你坚持注册你的小部件,至少要给它们命名,例如Widget。因此,在OP的情况下,我们会调用小部件StatusAlertWidget
。