杂项对象的Knockout数组

时间:2014-08-06 16:29:22

标签: knockout.js

我正在使用Knockout编写基本调查应用程序的演示。我需要在调查中包含两类问题,用户可以按照自己的意愿添加。例如,他们可能希望在调查中添加一个基本问题,然后是多项选择题。基本问题包括文本标签(用于问题)和最终用户输入的文本字段。多项选择题包含一行或多行,每行包含一个文本标签和一个复选框。

我已经写了一些Knockout: - 生成基本问题列表 - 为多项选择题生成选择选项列表

我现在需要的是将两种类型的问题存储在一个数组中,所以我猜数组对象需要是调查问题的更通用版本 - 一个可能是基本文本问题或多选题本身一系列选择选项。

我曾想过使用一个包含所有类型问题所有元素的通用问题对象,但由于每个简单的文本问题都需要包含一系列选择选项,因此需要大量开销。我添加其他类型的问题只会变得更糟。

有人能建议最好的(或最简洁的)前锋吗?

感谢您寻找:)

好的,我已将以下内容添加为我的JavaScript:

var SurveyModel = function () {
    var self = this;
    self.questions = ko.observableArray([]);
    self.addQuestion = function (item) {
        self.questions.push( item );
    };
    self.addQuestion("{ name: 'basic-question-template' }");
    self.addQuestion("{ name: 'checkbox-question-template' }");
    self.addQuestion("{ name: 'checkbox-question-template' }");
};

window.jQuery(function () {
    var viewModel = new SurveyModel();
    ko.applyBindings(viewModel);
});

...我的标记看起来像这样:

<script type="text/html" id="basic-question-template">
    <table>
        <tr>
            <td>Please enter a question:</td>
            <td><input data-bind="value: txtQuestion" /></td>
        </tr>
        <tr>
            <td>Please enter a hint:</td>
            <td><input data-bind="value: txtResponse" /></td>
        </tr>
    </table>
</script>

<script type="text/html" id="checkbox-question-template">
    <table>
        <tr>
            <td>Please enter a question:</td>
            <td><input data-bind="value: txtQuestion" /></td>
        </tr>
        <tr>
            <td>Please enter a hint:</td>
            <td><input type="checkbox" value="cbValue" data-bind="checked: false" /></td>
        </tr>
    </table>
</script>

<div id="frmSurvey" class="">
    <h2>Questions</h2>
    <div data-bind='template: { name: scriptID, foreach: questions }'> </div>
</div>
</code>

2 个答案:

答案 0 :(得分:1)

你的obserableArray中的对象没有必要属于同一类型。

我会推荐这样的东西:

  • 为每种问题类型的显示模式创建脚本HTML模板。
  • 为所有问题都有共同点的属性创建一个BaseQuestionModel类,但至少有一个标识符属性和一个属性来存储要调用的显示模板。
  • 例如,您也可以使用编辑模板,因此可以使用与自由格式文本问题等不同的方式编辑多项选择题。
  • 使用BaseQuestionModel.apply(this,arguments)为每个问题类型创建BaseQuestionModel的子类,并显式设置display-template属性。
  • 将这些子类的实例推送到observableArray。
  • 使用模板绑定根据其显示模板正确显示问题。

更新:

所以...你的新代码很接近,但并不完全。

您只是将字符串推送到问题数组,而不是实际对象。所以你需要这样的东西:

var CheckboxQuestion = function() {
var self = this;
self.scriptID = ko.observable('checkbox-question-template');
self.txtQuestion = ko.observable();
self.checked = ko.observable();
}

var BasicQuestion = function() {
var self = this;
self.scriptID = ko.observable('basic-question-template');
self.txtQuestion = ko.observable();
self.txtResponse = ko.observable();
}

var SurveyModel = function () {
var self = this;
self.questions = ko.observableArray([]);
self.addQuestion = function (item) {
self.questions.push( item );
};

bq1 = new BasicQuestion();
bq1.txtQuestion('What is your name?');
bq1.txtResponse('Hint goes here');

self.addQuestion( bq1 );

cbq1 = new CheckboxQuestion();
cbq1.txtQuestion('Are you a zombie?');

self.addQuestion(cbq1);

};

现在,当您的视图通过questions的每个成员时,它将找到模板的scriptID值,然后每个模板将获取该项并将可观察值应用于模板

答案 1 :(得分:0)

我不知道为什么会有开销,或者我可能不理解你的问题。如果你使用这样的东西:

function MainViewModel() {
  var self = this;
  this.questions = ko.observableArray();
}

function QuestionViewModel(type)
{
  var self = this;
  this.type = type;
  this.textQuestion = ko.observable();
  this.options = ko.observableArray();
  this.addOption = function() { self.options.push(new OptionValueViewModel()); }
}

function OptionValueViewModel() 
{
  this.text = ko.observable();
  this.checked = ko.observable(false);
}

你可以创建一个新的QuestionViewModel,传递一个类型字符串(&#39; text&#39;或&#39; select&#39;,或者对你有意义的东西)然后根据UI可以绘制一个或另一个的类型问题的类型。

如果您为某个问题添加了一个选项,则永远不会将该数组添加到其他问题中,因为它们中的每一个都独立于viewModel.questions数组中。

如果没有......我真的不明白这个问题。