淘汰赛:不寻常的映射模式

时间:2014-10-14 20:01:20

标签: javascript jquery knockout.js

场景:我向服务器请求了一个部分。它给了我这个回报(它是假的,但代表了我所看到的):

{
PartNumber : "XYZ", 
Description: "ABCFOO", 
ProductClass: "Widget",
FieldList:[
    {Name: "PROGRAM TYPE", Value: "Program3"},
    {Name: "SHIP", Value: false},
    {Name: "NOTES", Value: "SomeValue1"}
],
MoreStuff : [{
    ...
}]
}

注意FieldList的元素列表,这里是焦点。

服务器还给了我一些字段,类型和默认值的列表。它看起来像这样:

[
{FieldName : "PROGRAM TYPE", FieldType: "List", Defaults: [{Name:"Program 1", Value: "Program1"},{Name:"Program 2", Value: "Program2"},{Name:"Program 3", Value: "Program3"}]},
{FieldName : "SHIP", FieldType : "Boolean", Defaults: []},
{FieldName : "NOTES", FieldType: "TextArea", Defaults: []}
]

这是一个单独的REST调用,以及加载我的Part之前。我用它来创建Part的HTML页面的一部分。当我要求参与Part时,您可以看到它们与FieldList部分的关系类似。

从那个"字段列表"和默认值 - 我在页面上生成适当的HTML元素。如果它是一个布尔字段类型,我创建一个复选框 - 如果它是一个列表,我创建一个SELECT(默认值中给出的选项),TextArea是一个文本区域等等。一切正常。它最终看起来像:

<input data-bind="textInput: PartNumber"/>
<textarea data-bind="textInput: Description"></textarea>

<!-- generating fieldlist - i create a pseudo attr because the field name can have spaces-->
<select field_label="PROGRAM TYPE">   <!-- how the heck do i bind to this??-->
   <option value="Program1">Program 1</option>
   <option value="Program2">Program 2</option>
   <option value="Program3">Program 3</option>
</select >
<input type="checkbox" field_label="SHIP" value="true"/> <!-- or this, how to bind to it?!-->
<!-- end of field list generation -->

现在我把对象(我给出的部分)放到我的ViewModel中 - 这一切都只是游泳。我让它变得简单,只需使用ko.mapping.fromJS(rest_data);就可以了。

数据绑定很困难 - 因为我能够绑定它。我的问题来自 - 我如何将FieldList映射到我为服务器提供给我的字段生成的HTML?。我的数据/我的viewmodel对象中有FieldList,带有我要映射到生成的东西的buncha。唯一真正的关键&#34;我有自己创建的field_label,因为服务器的FieldName可以有空格。

所以我想我要问的是,我有FieldList那个数组。我在视图模型中有整个Part对象,它很好。如何取出FieldList并将其映射到另一个对象的自生成字段集中(即,获取FieldList名称并将其绑定到具有field_label的元素的元素相同的值?

拼写出来 - 它如下:如何将FieldList映射到名称为&#34;程序类型&#34;到具有&#34; PROGRAM TYPE&#34;。

的field_label的HTML元素

我开始认为这样的事情可能是我应该走的方向: http://jsfiddle.net/MhdZp/128/ 但它超越了我的头脑。

1 个答案:

答案 0 :(得分:1)

解决此问题的一种方法:

function Option(definition) {
    this.definition = definition;
    this.value = ko.observable();
    this.templateName = 'input-template-' + definition.FieldType;
}

function ViewModel() {
    var self = this;

    // from REST call
    var fieldDefinition = [{
        FieldName: "PROGRAM TYPE",
        FieldType: "List",
        Defaults: [
            { Name: "Program 1", Value: "Program1" }, 
            { Name: "Program 2", Value: "Program2" }, 
            { Name: "Program 3", Value: "Program3" }
        ]
    }];

    self.options = ko.observableArray();
    // for the sake of the example
    self.options.push(new Option(fieldDefinition[0]));

    // methods    
    self.optionByName = function (name) {
        return ko.utils.arrayFirst(self.options(), function (option) {
            return option.Name = name;
        });
    };

    // poor man's init, imagine 2nd rest call instead
    self.optionByName("PROGRAM TYPE").value("Program3");
}

<script type="text/html" id="input-template-List">
    <label data-bind="text: definition.FieldName"></label>
    <select data-bind="
        value: value,
        options: definition.Defaults,
        optionsText: 'Name',
        optionsValue: 'Value',
        optionsCaption: 'Please select...'
    "></select>
</script>

<div data-bind="foreach: options">
  <div data-bind="template: templateName"></div>
</div>

根据需要添加更多模板,这应该很容易扩展。

jsFiddle:http://jsfiddle.net/0nxt2zte/