使用该平台的原生 FormData 功能,demo'd here。
我认为我们可以通过以下方式根据输入数据生成任意数量的输入:
- 将表单的状态存储在某个变量中
- 根据该表单状态下的属性有条件地显示进一步的选择/输入。
代码方面,看起来像这样:
{{#if (dataHasValueFor "fieldName")}}
Show previously hidden field
{{/if}}
当然,魔鬼在实现细节中,所以,一个完整的工作示例(使用我制作的示例数据——如果您想要针对您的特定数据集,我们可以对此进行迭代,只需在此帖子/答案上发表评论) .
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import { on } from '@ember/modifier';
import { get } from '@ember/helper';
// This could be your model data from your route
const DATA = {
fruits: [
'apple', 'banana', 'orange', 'mango',
'watermellon', 'avacado', 'tomato?'
],
veggies: ['cocumber', 'tomato?', 'green bean', 'kale', 'spinach'],
peppers: ['carolina reaper', 'habanero', 'jalapeño']
}
export default class Demo extends Component {
@tracked formData;
get categories() {
return Object.keys(DATA);
}
handleInput = (event) => {
let formData = new FormData(event.currentTarget);
let data = Object.fromEntries(formData.entries());
this.formData = data;
}
handleSubmit = (event) => {
event.preventDefault();
handleInput(event);
}
isSelected = (name, value) => this.formData?.[name] === value;
<template>
<form
{{on 'input' this.handleInput}}
{{on 'submit' this.handleSubmit}}
>
<label>
Food Category<br>
<select name="category" placeholder="Select...">
<option selected disabled>Select a food group</option>
{{#each this.categories as |name|}}
<option
value={{name}}
selected={{this.isSelected "category" name}}
>
{{name}}
</option>
{{/each}}
</select>
</label>
<hr>
{{#let (get this.formData "category") as |selectedCategory|}}
{{#if selectedCategory}}
<label>
{{selectedCategory}}<br>
<select name={{selectedCategory}}>
<option selected disabled>
Select {{selectedCategory}}
</option>
{{#each (get DATA selectedCategory) as |food|}}
<option
value={{food}}
selected={{this.isSelected selectedCategory food}}
>
{{food}}
</option>
{{/each}}
</select>
</label>
{{/if}}
{{/let}}
</form>
<hr>
FormData:
<pre>{{toJson this.formData}}</pre>
</template>
}
const toJson = (input) => JSON.stringify(input, null, 4);
这个演示是交互式的here, on limber.glimdown.com
请注意,此处使用的语法是即将到来的默认语法PolarisEmber 版本,可通过ember-template-imports 获取
更新(在 cmets 之后)
Demo here
我对如何字段是动态的,因为我认为这更容易显示问题中提出的概念:在表单中动态显示字段。
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import { on } from '@ember/modifier';
import { get } from '@ember/helper';
export default class Demo extends Component {
@tracked formData;
handleInput = (event) => {
let formData = new FormData(event.currentTarget);
let data = Object.fromEntries(formData.entries());
this.formData = data;
}
handleSubmit = (event) => {
event.preventDefault();
handleInput(event);
}
<template>
<form
{{on 'input' this.handleInput}}
{{on 'submit' this.handleSubmit}}
>
<div class="grid">
<label>
Name <input type="checkbox" name='hasName'>
</label>
<label>
Email <input type="checkbox" name='hasEmail'>
</label>
<label>
Alias <input type="checkbox" name='hasAlias'>
</label>
<hr>
{{#if (get this.formData 'hasName')}}
<label>
Name
<input type="text" name="name" class="border" />
</label>
{{/if}}
{{#if (get this.formData 'hasEmail')}}
<label>
Email
<input type="email" name="email" class="border" />
</label>
{{/if}}
{{#if (get this.formData 'hasAlias')}}
<label>
Alias
<input type="text" name="alias" class="border" />
</label>
{{/if}}
</div>
</form>
<hr>
FormData:
<pre>{{toJson this.formData}}</pre>
</template>
}
const toJson = (input) => JSON.stringify(input, null, 4);
而且......因为您似乎有很多领域,您可能希望尽可能动态:
demo here
这是以下代码:
<form
{{on 'input' this.handleInput}}
{{on 'submit' this.handleSubmit}}
>
<div class="grid">
{{#each FIELDS as |field|}}
<label>
{{field}} <input type="checkbox" name='has-{{field}}'>
</label>
{{/each}}
<hr>
{{#each FIELDS as |field|}}
{{#if (get this.formData (concat 'has-' field))}}
<label>
{{field}}
<input type="text" name={{field}} class="border" />
</label>
{{/if}}
{{/each}}
</div>
</form>