ko.toJSON似乎忽略了字段

时间:2011-09-08 01:43:13

标签: knockout.js

我使用knockoutjs编写动态查询编辑器,但是ko.toJSON在数据绑定表单元素修改之前不输出字段。使用以下视图查看this jsfiddle

<span data-bind="template: {name: 'filterGroupTemplate', data: viewModel}"></span>

<script type="text/x-jquery-tmpl" id="filterGroupTemplate">
    <div class="filterGroup">
        <div class="filterGroupParams">
            Match
            <select name="join" data-bind="value: join, options: joins"></select>
            of the following rules:
            <button class="addFilter" data-bind="click: addFilter">+</button>
            <button class="addGroup" data-bind="click: addGroup">{...}</button>
            <button class="removeGroup">x</button>
        </div>
        <span data-bind='template: {name: "filterTemplate", foreach: filters }'></span>
    </div>
</script> 

<script type="text/x-jquery-tmpl" id="filterTemplate"> 
    <div class="filter">
        {{if $data.filters }}       
            <div data-bind='template: "filterGroupTemplate"'> 
            </div>                 
        {{else}}
            <select data-bind="value: field, options: fields"></select>       
            <select data-bind="value: modifier, options: modifiers"></select>
            <input type="text" data-bind="value: criteria" />
            <button>x</button>
        {{/if}}
    </div>
</script>

<h2>ViewModel JSON</h2>
<div data-bind="text: dev()"></div>

这段代码:

// filter class
var Filter = function() {
    this.field = ko.observable();
    this.modifier = ko.observable();
    this.criteria = ko.observable();
};

// filter group class
var FilterGroup = function() {
    // Include a blank filter in every group
    this.join = ko.observable('All');
    this.filters = ko.observableArray([new Filter()]);
    this.addFilter = function() {
        var filter = new Filter();
        this.filters().push(filter);
        this.filters.valueHasMutated();
    };
    this.addGroup = function() {
        var group = new FilterGroup();
        this.filters().push(group);
        this.filters.valueHasMutated();
    };
};

// Data
var joins = ['All', 'Any'];
var modifiers = [
    'equals',
    'not equal to',
    'less than',
    'greater than',
    'contains',
    'does not contain',
    'starts with'
];
var fields = ['f1','f2','f3'];

var viewModel = new FilterGroup();
function dev(){
    return ko.toJSON(viewModel);
}

ko.applyBindings(viewModel);

虽然视图模型显然具有预初始化的字段(例如join属性),但在用户在UI中更改它们之前,它们不会显示在JSON对象中。

有人可以解释一下我做错了什么以及如何解决它?这实际上似乎是knockoutjs本身的一个错误。如果它归结为它,我只会在构建查询时使用默认值,如果值不存在,但这似乎是一个糟糕的解决方案

1 个答案:

答案 0 :(得分:8)

您的代码中存在一个微妙的问题,导致许多人扯掉头发。当您对select元素使用options绑定value绑定时,需要在options之前指定value

options绑定构建可用选项,然后值绑定强制所选选项和视图模型值同步。如果您的顺序错误,则value绑定首先运行,并且看到没有匹配的选项可供选择,因此它将值设置为null。

这是您改变订单的小提琴:http://jsfiddle.net/rniemeyer/32fYk/

这已经在github上记录了几次,最近一次是在https://github.com/SteveSanderson/knockout/issues/58。目前没有一种简单的方法来强制绑定在同一数据绑定中的另一个绑定之前运行。希望在某些时候这将得到解决。我可以通过让两个绑定检查是否列出另一个绑定来考虑一个专门处理这种情况的修复。