我尝试渲染页面的不同部分,并为单个数组中包含的不同项目应用适当的绑定。数组中的每个项目都可以具有不同的结构/属性。
作为一个例子,我们可以有3种不同的问题类型,与该问题相关的数据可以采用不同的格式。
JSON数据
var QuestionTypes = { Textbox: 0, Checkbox: 1, Something: 2 }
var QuestionData = [
{
Title: "Textbox",
Type: QuestionTypes.Textbox,
Value: "A"
},
{
Title: "Checkbox",
Type: QuestionTypes.Checkbox,
Checked: "true"
},
{
Title: "Custom",
Type: QuestionTypes.Something,
Something: { SubTitle : "Something...", Description : "...." }
}
];
的JavaScript
$(document).ready(function(){
ko.applyBindings(new Model(QuestionData), $("#container")[0]);
})
function QuestionModel(data){
var self = this;
self.title = ko.observable(data.Title);
self.type = ko.observable(data.Type);
self.isTextbox = ko.computed(function(){
return self.type() === QuestionTypes.Textbox;
});
self.isCheckbox = ko.computed(function(){
return self.type() === QuestionTypes.Checkbox;
});
self.isSomething = ko.computed(function(){
return self.type() === QuestionTypes.Something;
});
}
function Model(data){
var self = this;
self.questionData = ko.observableArray(ko.utils.arrayMap(data, function(question){
return new QuestionModel(question);
}));
}
HTML
<div id="container">
<div data-bind="foreach: questionData">
<h1 data-bind="text: title"></h1>
<!-- ko:if isTextbox() -->
<div data-bind="text: Value"></div>
<!-- /ko -->
<!-- ko:if isCheckbox() -->
<div data-bind="text: Checked"></div>
<!-- /ko -->
<!-- ko:if isSomething() -->
<div data-bind="text: Something">
<h1 data-text: SubTitle></h1>
<div data-text: Description></div>
</div>
<!-- /ko -->
</div>
</div>
如果条件为true / false,则应用if条件中的绑定。这导致JavaScript错误......因为并非集合中的所有对象都具有“价值”和“错误”。财产等。
Uncaught ReferenceError: Unable to process binding "foreach: function (){return questionData }"
Message: Unable to process binding "text: function (){return Value }"
Message: Value is not defined
有没有办法阻止绑定应用于错误的对象?
概念JSFiddle:https://jsfiddle.net/n2fucrwh/
答案 0 :(得分:4)
请在不更改代码的情况下查看更新的提琴手。只需在循环中添加$ data
https://jsfiddle.net/n2fucrwh/3/
<!-- ko:if isTextbox() -->
<div data-bind="text: $data.Value"></div>
<!-- /ko -->
<!-- ko:if isCheckbox() -->
<div data-bind="text: $data.Checked"></div>
<!-- /ko -->
<!-- ko:if isSomething() -->
<div data-bind="text: $data.Something"></div>
<!-- /ko -->
在循环内部,你需要提供$ data.Value.It似乎值是淘汰与绑定冲突的关键词。
答案 1 :(得分:2)
首先,您的“QuestionModel”没有相应的属性:您只能从传入数据创建“type”和“title”字段。
建议的解决方案:
您可以为不同的数据类型使用不同的模板。 我已更新您的fiddle:
var QuestionTypes = { Textbox: 0, Checkbox: 1, Something: 2 }
var QuestionData = [
{
Title: "Textbox",
Type: QuestionTypes.Textbox,
templateName: "template1",
Value: "A"
},
{
Title: "Checkbox",
Type: QuestionTypes.Checkbox,
templateName: "template2",
Checked: "true"
},
{
Title: "Custom",
Type: QuestionTypes.Something,
templateName: "template3",
Something: "Something"
}
];
$(document).ready(function(){
ko.applyBindings(new Model(QuestionData), $("#container")[0]);
})
function QuestionModel(data){
var self = this;
self.title = ko.observable(data.Title);
self.type = ko.observable(data.Type);
self.data = data;
}
function Model(data){
var self = this;
self.questionData = ko.observableArray(ko.utils.arrayMap(data, function(question){
return new QuestionModel(question);
}));
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<script type="text/html" id="template1">
<div data-bind="text: Value"></div>
</script>
<script type="text/html" id="template2">
<div data-bind="text: Checked"></div>
</script>
<script type="text/html" id="template3">
<div data-bind="text: Something"></div>
</script>
<div id="container">
<div data-bind="foreach: questionData">
<h1 data-bind="text: title"></h1>
<!-- ko with: data -->
<!-- ko template: templateName -->
<!-- /ko -->
<!-- /ko -->
</div>
</div>
在上面的版本中,您可以摆脱“QuestionTypes”。
当然,您可以从问题类型计算模板名称。
错误原因说明。如果您检查原始视图模型:
function QuestionModel(data){
var self = this;
self.title = ko.observable(data.Title);
self.type = ko.observable(data.Type);
self.isTextbox = ko.computed(function(){
return self.type() === QuestionTypes.Textbox;
});
self.isCheckbox = ko.computed(function(){
return self.type() === QuestionTypes.Checkbox;
});
self.isSomething = ko.computed(function(){
return self.type() === QuestionTypes.Something;
});
}
你可以看到,“QuestionModel”具有以下属性:“title”,“type”,“isTextbox”,“isCheckbox”和“isSomething”。
因此,如果您尝试将模板绑定到“Value”,“Checked”或“Something”,则会出现错误,因为视图模型不包含此类属性。
将绑定语法更改为
<div data-bind="text: $data.Value"></div>
或类似的东西消除了错误,但在这种情况下总是不会显示任何内容。