如何迭代传递提交的knockout表单元素

时间:2015-04-21 04:25:46

标签: javascript forms dom knockout.js

我有一个表单,我想用Knockout以正常方式提交,将它绑定到一个函数而不是访问像

这样的元素
 var value = form.element 

我想遍历表单元素。表单对象在访问之前似乎不包含元素,那么如何在不知道它们的id的情况下迭代它们呢?我想避免使用数字ID和for循环 以下是我的不起作用:

 saveChanges: function(form) {
        form.each(function( element ) {
            //do something 
        });

表单对象的console.log()输出是奇怪的:

 {"0":{},"1":{"__ko__1429589442426":"ko66"},     
 "2":{"__ko__1429589442426":"ko74"},
 "3":{"__ko__1429589442426":"ko79"},
 "4":{},"__ko__1429589442426":"ko60"}

有什么建议吗?

编辑:为什么我需要这样做?

我的表单元素来自我的api,它是用强类型语言制作的。 '偏好'每个都有' booleanvalue',' numericvalue',' stringvalue'以及首选类型的值,或者' bool','麻木'或' stri'在调用api时,我返回所有值,然后只显示首选的一个使用knockout' s if:binding。

从api返回的示例:

[{"type":"bool","stringvalue":null,"preference":"taxable","numericvalue":"0","id":3,"booleanvalue":true},{"type":"stri","stringvalue":"Acme inc.","preference":"company_name","numericvalue":"0","id":2,"booleanvalue":false}]

当我收集表单输入onsubmit时,我需要获取首选项的名称和列名,booleanvalue,stringvalue,numericvalue。我通过设置id属性来包含信息来做到这一点,这样我就可以解析id键来获取列名,并使用该值作为列值。这是一个例子:

id= company_name.stringvalue value= "acme co."

id= taxable.booleanvalue value= "true"

id= tax_rate.numericvalue value= "0.0112"

这是在Durandal应用程序内部,所以小提琴不起作用,但你可以看到我的html / js。 https://jsfiddle.net/ggja7qv2/

我没有硬编码这些的原因是因为我将来会从api添加更多首选项,并且我希望前端能够编辑这些首选项而不必返回它并更改内容。前端应该以

的形式将JSON发送到api
{"data":[{"preference":"company_name","stringvalue":"acme inc"},{"preference":"taxable","booleanvalue":"false"}]}

2 个答案:

答案 0 :(得分:1)

使用纯粹淘汰赛解决这个问题很有趣:)

您需要的第一件事是处理您奇怪的多类型偏好的视图模型。我们称之为Preference

// dictionary to convert preference types to 
// the properties that hold their values
var typeToValueName = {
    bool: 'booleanvalue',
    stri: 'stringvalue',
    nume: 'numericvalue',
};
// dictionary from types to valid html input types
var typeToInputType = {
    bool: 'checkbox',
    stri: 'text',
    nume: 'number',
};

function Preference(data) {
    this.preference = data.preference;
    this.valueTypeName = typeToValueName[data.type];
    this.inputType = typeToInputType[data.type];
    this.value = ko.observable(data[this.valueTypeName]);
    // if this is a checkbox, the value is bound differently (you can make this computed if you're dynamically changing your input types)
    this.isCheckbox = this.inputType === 'checkbox';
}

然后你需要将这些数组绑定到你的表单:

<form data-bind="submit: save">
    <!-- ko ifnot: preferences().length -->
    Loading preferences...
    <!-- /ko -->
    <!-- ko foreach: preferences -->
    <label>
        <span data-bind="text: preference"></span>
        <!-- ko if: isCheckbox -->
        <input data-bind="attr: {type: inputType}, checked: value"/>
        <!-- /ko -->
        <!-- ko ifnot: isCheckbox -->
        <input data-bind="attr: {type: inputType}, value: value"/>
        <!-- /ko -->
    </label>
    <br/>
    <!-- /ko -->
    <input type="submit" value="Save"></input>
</form>

最后,当您提交表单时,您需要将此数组映射到更简单的数组:

var vm = {
    preferences: ko.observable([]), // no need to make this an observable array unless you're dealing with adding/removing preferences one by one.

    save: function () {
        console.log(this.preferences().map(function(p){
            var outputFormat = { preference: p.preference };
            outputFormat[p.valueTypeName] = p.value();
            return outputFormat;
        }));
    }
};

你可以自动化上面的很多内容,但这是明确的,因此它可以帮助你开始考虑“淘汰赛方式”。祝你好运,这里有一个小小的玩法:http://jsfiddle.net/h2qq0k42/

答案 1 :(得分:1)

您可以使用jquery:

$(form).find('input')

这将返回所有表单元素。

OTOH,请不要将信息存储在ID中。您可以使用data-属性,每个信息对应一个属性,然后以这种方式阅读它们:

$(form).find('input')[0].attr('data-booleanvalue')

生成的输入应如下所示:

<input type="...." data-booleanvalue="true" ... />