要求:我将从服务器使用REST服务获取json数据。该json数据将告诉我向用户呈现的控件类型(ControlID)以及需要在这些控件中插入的数据是什么。因此,基本需要是有多个客户端控件,当视图加载时,它应该根据控件和需要显示的数据进行布局。它是一种仪表板概念,其中所有的瓷砖都是一种自定义控件,例如。的iGoogle。
我将从服务器获取的json数据将包含controlId属性的集合和其他属性,其中包含用于自定义它的值以及需要进入控件的数据。例如:
{
controlID: 'xxx',
fontSize: 2
}
因此,我必须使用多个控件ID,我想我必须管理一个配置文件,该文件可以在文件夹中具有id和相应的模块/窗口小部件/控件的名称或路径以便加载。
我研究和实施的内容:我已经开始研究单页应用程序,现在我正在使用带有asp.net mvc5的Durandaljs。下面是我用它创建了两个小部件的代码 - “标签”和“文本框”。这两个没有任何花哨的定制,但我只是想看看我怎样才能做到这一点。 我开始研究小部件,因为我认为它是一个很好的选择 - 一个单独的视图和处理逻辑 - 每个小部件的视图和视图模型。如果我的要求有其他选择,我可能会错。
现在,我只是在我的示例视图中使用这两个小部件,并从其视图模型中传递一些属性。
我的问题 - 请尽可能使用样本/ gist / jsfiddle回答。
但是,我确实想要加载一个小部件说“A”,然后这个小部件也应该使用小部件标签和文本框。从逻辑上讲,它将成为由其他组件组成的自定义组件。我们的想法是将一个大的小部件分成不同的小部件,以便它们可以独立工作,具有独特的自定义和视图,并且可以将它们组合在一起以呈现给用户。
我应该研究durandaljs小部件的其他替代品吗?如果可能请举例。
正如我上面提到的,我需要从服务器读取json数据以生成每个视图并识别要加载的控件。到目前为止,我只使用静态HTML,但这对我来说有点不同。任何人都可以帮我找一种根据服务器的json数据按需加载这些自定义小部件的方法。
应用中的小部件代码和主视图:
小工具 - 标签
HTML:
<div data-bind="foreach: { data: settings.items }">
<br />
<label data-bind="text: $data.TextValue, style: { color: $data.TextColour }"></label>
的javascript:
"use strict";
define(['durandal/composition', 'jquery'], function(composition, $) {
var ctor = function () { };
ctor.prototype.activate = function(settings) {
this.settings = settings;
};
//ctor.prototype.getLabelText = function(item) {
// if (this.settings.textValue) {
// return item[this.settings.textValue];
// }
// return item.toString();
//};
return ctor;
});
小工具 - 文本框
HTML:
<div data-bind="foreach: { data: settings.items }">
<br />
<input type="text" data-bind="value: $data.TextValue, style: { color: $data.TextColour }" />
</div>
的javascript:
"use strict";
define(['durandal/composition', 'jquery'], function(composition, $) {
var ctor = function() {};
ctor.prototype.activate = function(settings) {
this.settings = settings;
};
return ctor;
});
我正在使用上述小部件的主html页面:
HTML:
<div class="well">
<h2>SimpleLabel</h2>
<div data-bind="simplelabel: {items:labels}"></div>
</div>
<hr />
<div class="well">
<h2>SingleLine Textbox</h2>
<div data-bind="singlelinetextbox: {items:boxes}"></div>
</div>
答案 0 :(得分:0)
简单解决方案
如果它不符合您的要求/其他人的答案,我现在可以让它变得更短,但是我可以在以后(大约4-5小时)为您提供更复杂的解决方案。
多个小部件数据共享
在窗口小部件之间共享数据非常简单 - 您只需在包含窗口小部件的视图模型中声明knockout observable属性,并将其作为设置传递给两个窗口小部件。
动态窗口小部件呈现
为此,我将更改您的小部件绑定语法。
<div id="widget1placeholder">
<h2 data-bind="Text: widget1.text"></h2>
<div data-bind="widget: {kind:widget1.type, items:widget1.data}">/div>
</div>
<hr />
<div id="widget2placeholder">
<h2 data-bind="Text: widget2.text"></h2>
<div data-bind="widget: {kind:widget2.type, items:widget2.data}">/div>
</div>
其中widget1和widget2是viewmodel中的可观察对象。可以从服务器加载的JSON数据轻松设置它们。虽然您可能需要制定一些关于窗口小部件输入数据的约定。
编辑+复杂解决方案
mapIdToType(controlId)
将控件ID作为输入并返回窗口小部件类型的名称。 widgetLoader
loadWidgets()
)
/app
/viewmodels
/dashboard.js
/widgetA.js
/widgetB.js
/widgetC.js
/views
/dashboard.html
/widgetA.html
/widgetB.html
/widgetC.html
define(['knockout', 'service/widgetLoader', 'viewmodels/widgetA', 'viewmodels/widgetB', 'viewmodels/widgetC'],
function (ko, widgetLoader, WidgetA, WidgetB, WidgetC) {
var widget1 = ko.observable();
var widget2 = ko.observable();
function getWidget(item)
{
if (mapIdToControll(item.controlId) === "WidgetA")
return new WidgetA(item));
else if (mapIdToControll(item.controlId) === "WidgetB")
return new WidgetB(item));
else if (mapIdToControll(item.controlId) === "WidgetC")
return new WidgetC(item));
else
throw new Error("Unknown widget type");
}
return {
widget1: widget1,
widget2: widget2,
activate: function() {
widgetLoader.loadWidgets().then(function(result) {
widget1 = getWidget(result[0]);
widget2 = gwtWidget(result[1]);
});
});
}
}
});
查看:
<div>
<div data-bind="compose: widget1"></div>
<div data-bind="compose: widget2"></div>
</div>
希望它能满足您的要求。