我想禁用一个选项,如果它已经在对象组之一中被选中。
因此,如果我选择“2013”然后添加另一个示例,则“2013”在该组中将不可用,除非在原始组中更改了该选项。
有没有一种简单的方法可以做到这一点,而我却缺少了?做出选择时,我需要以反应方式更新架构吗?
samples:{
type: Array,
optional: true,
maxCount: 5
},
"samples.$":{
type: Object,
optional: true
},
"samples.$.sample":{
type:[String],
autoform: {
type: "select",
options: function () {
return [
{
optgroup: "Group",
options: [
{label: "2013", value: 2013},
{label: "2014", value: 2014},
{label: "2015", value: 2015}
]
}
];
}
}
},
最佳答案
概念证明
我知道此职位大约3岁。但是,我遇到了同样的问题,并希望为所有也为这篇文章而迷迷糊糊的人提供答案。
该答案仅是概念证明,并未提供可在生产应用程序上使用的完整的通用解决方案。
完全通用的解决方案需要对AutoForm
中如何生成和更新选择字段选项的代码进行深刻的更改。
一些先前的注意事项。
我正在使用Autoform> = 6,它提供a good API来立即获取SimpleSchema中的字段和表单值,而不会带来更多麻烦。 SimpleSchema
包含在npm软件包中,并且Tracker
必须传递给它,以确保Meteor反应性。
像AutoForm.getFieldValue这样的函数是反应式的,这确实是一个很大的改进。但是,基于反应性值来反应性地更改选择选项会导致大量更新周期,并且会降低性能(我们将在后面看到)。
在对象字段的选项中使用AutoForm.getFormValues时不起作用。在“数组”字段中工作时,它将在“对象”字段中没有反应,因此不会更新对它们的过滤。
处理选择输入数组的选项(失败)
您不能将其与字段的数组类型一起使用。这是因为,如果更改选择选项,它将应用于数组中的所有选择实例。因此,它也将应用于您已经选择的值,并将它们也剥离掉。这使您的选择看起来总是“未选择”
您可以使用以下示例代码进行测试:
new SimpleSchema({
samples:{
type: Array,
optional: true,
maxCount: 5
},
"samples.$":{
type: String,
autoform: {
type: "select",
options: function () {
const values = AutoForm.getFormValues('sampleSchemaForm') || {};
const samples = values && values.insertDoc && values.insertDoc.samples
? values.insertDoc.samples
: [];
const mappedSamples = samples.map(x => x.sample);
const filteredOpts = [
{label: "2013", value: "2013"},
{label: "2014", value: "2014"},
{label: "2015", value: "2015"}
].filter(y => mappedSamples.indexOf(y.value) === -1);
return [
{
optgroup: "Group",
options:filteredOpts,
}
];
}
}
},
}, {tracker: Tracker});
在对象字段上使用固定值
仔细查看架构时,我看到了
maxCount
属性。这让我想到,如果您仍然有一个最大选项列表,则可以通过在samples
对象上具有固定的属性来解决此问题(顺便说一句:当只有三个选择选项时,maxCount: 5
毫无意义)。这会导致每个选择都有自己的更新,不会干扰其他选择。它需要一个外部函数,该函数可以跟踪所有选定的值,但是显示出来非常容易。
考虑以下代码:
export const SampleSchema = new SimpleSchema({
samples:{
type: Object,
optional: true,
},
"samples.a":{
type: String,
optional:true,
autoform: {
type: "select",
options: function () {
const samples = AutoForm.getFieldValue("samples");
return getOptions(samples, 'a');
}
}
},
"samples.b":{
type: String,
optional:true,
autoform: {
type: "select",
options: function () {
const samples = AutoForm.getFieldValue("samples");
return getOptions(samples, 'b');
}
}
},
"samples.c":{
type: String,
optional:true,
autoform: {
type: "select",
options: function () {
const samples = AutoForm.getFieldValue("samples");
return getOptions(samples, 'c');
}
}
},
}, {tracker: Tracker});
上面的代码具有三个示例条目(a,b和c),这将使它们的选项由外部函数计算。
此功能需要满足某些要求:
samples
选择的选项select 该函数的代码如下:
function getOptions(samples={}, prop) {
// get keys of selections to
// determine, for which one
// we will filter options
const sampleKeys = Object.keys(samples);
// get sample values to
// determine which values
// to filter here
const sampleValues = Object.values(samples);
const filteredOptiond = [
// note that values are stored as strings anyway
// so instead of parsing let's make them strings
{label: "2013", value: "2013"},
{label: "2014", value: "2014"},
{label: "2015", value: "2015"}
].filter(option => {
// case 1: nothing is selected yet
if (sampleKeys.length === 0) return true;
// case2: this selection has a
// selected option and current option
// is the selected -> keep this option
if (sampleKeys.indexOf(prop) > -1 && option.value === samples[prop])
return true;
// case 3: this selection has no value
// but others may have selected this option
return sampleValues.indexOf(option.value) === -1;
});
return [
{
optgroup: "Group",
options: filteredOptiond,
}
]
};
有关此概念的一些注意事项
好:
-有用
-您基本上可以将其扩展并扩展到所需的复杂度(optgroup,
samples
上的更多字段,与其他字段进行对照的其他字段等)坏:
-表现
-绑定(bind)到给定的(或最接近的)表单上下文(请参阅here)
-比数组要写的代码要多得多。
关于javascript - meteor 自动格式-禁用对象字段数组中的选择选项,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/27259586/