当表单是 marionette 布局视图时序列化表单数据

Serializing form data when form is a marionette layout view

我有一个看起来像这样的对象:

{
  "id": "someId",
  "name": "some name",
  "endpoints": [
    { "scheme": "http", "host":"localhost", "port":"8080" }
  ]
}

我想在 Marionette 应用程序中编辑此数据。我已经定义:

我的目标是拥有一个允许添加 N 个端点的表单,这样当提交表单时,我将保留整个对象(服务器数据和端点列表)。

为了实现这个,我首先重写了解析函数来实例化 Endpoints 集合,如下所示:

parse: function(response) {
    var data = response;
    if (response.endpoints) {
        data.endpoints = new Entities.EndpointCollection(response.endpoints, {parse: true});            
    }
    return data;
},

然后,我创建了一个 LayoutView,其中包含与我的服务器相关的字段并包含一个用于我的端点列表的区域。我的控制器实例化视图并传入服务器模型。我的控制器还实例化一个 CollectionView 并传入服务器的端点集合。

表单按预期呈现,带有 ID、名称的输入控件,以及与我的对象中一样多的端点的重复输入集。

但是,我不清楚序列化应该如何与此设置一起工作。如果我通过破坏其模型来删除端点,则在持久化数据时删除端点。但是,如果我更改任何端点数据,这些更改将被忽略。

在我的表单提交处理程序中,我可以遍历端点,但这些模型不反映更改后的表单值。

submitClicked: function (e) {
    e.preventDefault();
    var data = Backbone.Syphon.serialize(this); // I know this is not enough
    var endpoints = this.model.get("endpoints");
    for (var i = 0; i < endpoints.length; i++) {
        var endpoint = endpoints.models[i];
        alert("got endpoint: " + endpoint.get("host"));
    }
    this.trigger("form:submit", data);
},

我认为对于如何最好地处理表单中的重复组存在根本性的误解。我错过了什么?

我的思想变得紧张起来。布局视图确实不是问题。关键是表单需要具有唯一的 IDs/names。为此,我首先将项目的索引发送到视图:

Views.Endpoint = Marionette.ItemView.extend({
    template: endpointTpl,

    triggers: {
        "click button.btn-remove": "endpoint:remove"
    },

    initialize: function(options) {
        this.model.set("idx", options.childIndex);
    }

});

Views.Endpoints = Marionette.CollectionView.extend({
    childView: Views.Endpoint,
    childViewOptions: function(model, index) {
        return {
            childIndex: index
        }
    }
});

然后,在视图的模板中,我使用该索引设置 ID 和名称 属性:

<tr>
  <td><label for="endpoints[<%- idx %>][scheme]" class="control-label">Scheme:</label></td>
  <td><input id="endpoints[<%- idx %>][scheme]" name="endpoints[<%- idx %>][scheme]" type="text" value="<%= scheme %>"></input></td>
  <td></td>
</tr>

最后,在提交时,Siphon 将为我的重复组创建一个对象,而我真正想要的是一个数组,所以我用以下方法解决这个问题:

submitClicked: function (e) {
    e.preventDefault();
    var data = Backbone.Syphon.serialize(this);
    // need to convert endpoints object to array
    var endpoints = data.endpoints;
    delete data["endpoints"];
    data.endpoints = [];
    for (var idx in endpoints) {
        data.endpoints.push(endpoints[idx]);
    }
    this.trigger("form:submit", data);
}

现在我可以根据需要 add/remove/edit 端点并将它们适当地保存回对象。