在 Autoform 中使用对象作为选项

Using objects as options in Autoform

在我的 Stacks 架构中,我有一个 dimensions 属性 定义如下:

dimensions: {
    type: [String],
    autoform: {
        options: function() {
            return Dimensions.find().map(function(d) {
                return { label: d.name, value: d._id };
            });
        }
    }
}

这非常有效,并且使用 Mongol 我能够看到通过表单插入数据的尝试效果很好(在本例中我选择了两个维度来插入)

然而,我真正了解的是存储实际维度对象的数据,而不是它的键。像这样:

[

为了尝试实现这一点,我将 type:[String] 更改为 type:[DimensionSchema],将 value: d._id 更改为 value: d。这里的想法是我告诉表单我期待一个对象,现在返回对象本身。

但是,当我 运行 这样做时,我的控制台出现以下错误。

Meteor does not currently support objects other than ObjectID as ids

四处寻找并将 type:[DimensionSchema] 更改为 type: DimensionSchema 我在控制台中看到了一些新错误(大概当 type 是数组时它们被掩埋了

看来 autoform 正在尝试获取我想要存储在数据库中的值并尝试将其用作 ID。关于执行此操作的最佳方法有什么想法吗?

参考这里是我的DimensionSchema

export const DimensionSchema = new SimpleSchema({
    name: {
        type: String,
        label: "Name"
    },
    value: {
        type: Number,
        decimal: true,
        label: "Value",
        min: 0

    },
    tol: {
        type: Number,
        decimal: true,
        label: "Tolerance"
    },
    author: {
        type: String,
        label: "Author",
        autoValue: function() {
            return this.userId
        },
        autoform: {
            type: "hidden"
        }
    },
    createdAt: {
        type: Date,
        label: "Created At",
        autoValue: function() {
            return new Date()
        },
        autoform: {
            type: "hidden"
        }
    }
})

目前我唯一可以建议的(如果值不支持 object 类型),是将对象转换为 string(即序列化字符串)并将其设置为"dimensions" 键(而不是对象)并将其保存到数据库中。

从数据库返回时,再次将该值 (string) 反序列化为 object

根据我的经验和自己在 this issue 中的经验,autoform 对对象数组的字段不是很友好。

我通常建议不要以这种方式嵌入这些数据。如果将来修改 dimension 文档,这会使数据更难维护。

备选方案

  • 您可以使用像 publish-composite 这样的包在发布中创建反应式连接,同时仅将 _id 嵌入到 stack 文档中。
  • 您可以使用 PeerDB 包之类的东西为您进行反规范化,这也会为您更新嵌套文档。考虑到它带有学习曲线。
  • 手动编码无法使用 AutoForm 轻松创建的特定表单。这给了你最大的控制权,有时它比所有的修补更容易。

如果你坚持使用AutoForm

虽然可以 create a custom input type(通过 AutoForm.addInputType()),但我不推荐它。它需要您创建一个模板并在其 valueOut 方法中修改数据,并且生成编辑表单并不是一件容易的事。

由于这是一个特定的用例,我认为最好的方法是使用稍微 修改过的模式 并在 Meteor 方法中处理数据.

用字符串数组定义模式:

export const StacksSchemaSubset = new SimpleSchema({
  desc: {
    type: String
  },
  ...
  dimensions: {
    type: [String],
    autoform: {
      options: function() {
        return Dimensions.find().map(function(d) {
            return { label: d.name, value: d._id };
        });
      }
    }
  }
});

然后,呈现一个 quickForm,指定模式和方法:

<template name="StacksForm">
  
  {{> quickForm
    schema=reducedSchema
        id="createStack"
        type="method"
        meteormethod="createStack"
        omitFields="createdAt"
  }}

</template>

并定义适当的助手来传递模式:

Template.StacksForm.helpers({
  reducedSchema() {
    return StacksSchemaSubset;
  }
});

并且在服务器上,定义方法并在插入之前改变 data

Meteor.methods({
  createStack(data) {
    // validate data
    const dims = Dimensions.find({_id: {$in: data.dimensions}}).fetch(); // specify fields if needed
    data.dimensions = dims;
    Stacks.insert(data);
  }
});