Play Framework - 为动态字段注册自定义 DataBinder
Play Framework - Register a custom DataBinder for dynamic fields
使用 Play 2.3.7 (Java) 我有以下场景。
我有一个 class CSVData
,其中包含 CSVField
类型的列表。以下是这些 classes 的属性:
public class CSVData{
private String name;
private String description;
private String dataFilePath;
private List<CSVField> fields;
private Double latitude;
private Double longitude;
// rest of class... }
和
public class CSVField {
private String name;
private String type;
...}
制作表单以输入 CSVData
的困难在于我有这个嵌套的 List<CSVField>
属性,而 CSVField
是包含两个字符串的自定义类型。我需要表单是动态的,因为它应该能够接受任意数量的 CSVField
s(至少 1)。跟Java Form Documentation, it seems like I should register a custom DataBinder for CSVField, however I can't find any examples that do this with multiple input strings. This example类似,不过它只绑定一个字段。
Here is a video of what type of user input I would like to have. I made my view using this example code for adding dynamic fields。文本字段(名称)和 select 下拉项(类型)的组合是我需要绑定到 CSVField
然后添加到 CSVData
中的 List<CSVField> fields
目的。 如何使用 Play Framework 执行此操作?
编辑:在我的控制器中我试过这个
Form<CSVData> formData = Form.form(CSVData.class).bindFromRequest();
我在视图中尝试了这个
@helper.repeat(csvForm("fields"), min = 1) { csvField =>
@multiDataField(csvField,
label = "Column Name and Type",
gsnTypes,
help = "Enter the column names and respective types for the data items in the file")
}
其中 multiDataField
是 this 模板。但它没有正确绑定动态字段并在 fields
上抛出无效验证错误。我想我的问题是我不知道在我的 multiDataField
模板中使用什么 name
属性。有什么建议吗?
您不需要任何客户数据绑定器。无需任何额外的绑定注册即可支持包含复杂对象的列表。
在视图中您可以使用 @repeat
Helper,在控制器中您已经做得很好了。
这里有一个关于 Play and Forms, or directly in TypeSafe
的完整示例
编辑
在重复块内,csvField
是列表中每个 Form 对象的实例。然后,您需要添加视图所需的所有 HTML 元素。例如(没有 Bootstrap 的简化):
@helper.repeat(csvForm("fields"), min = 1) { csvField =>
Name: <input type="text" name='@csvField("name").name' value='@csvField("name").value'>
Type: <input type="text" name='@csvField("type").name' value='@csvField("type").value'>
}
您可以在 samples provide in Play 2.2.x 中找到更完整的示例。要在 2.3.x 中编译它,可能需要稍微更改一些内容,而不是使用 Bootstrap 3.x,但逻辑是相同的。
编辑 (2)
如果要向视图中动态添加 元素,您需要注意在添加新元素时设置正确的数组编号。为此,您需要使用 JQuery:
$('.addCSVField').click(function() {
var CSVFields = $(this).parents('.CSVField');
var template = $('.CSVField_template', CSVFields);
template.before('<div class="clearfix CSVField">' + template.html() + '</div>');
renumber();
})
$('.removeCSVField').click(function() {
$(this).parents('.CSVField').remove();
renumber();
})
var renumber = function() {
$('.CSVField').each(function(i) {
$('input', this).each(function() {
$(this).attr('name', $(this).attr('name').replace(/fields\[.+?\]/g, 'fields[' + i + ']'));
})
})
}
然后您需要将 HTML/Scala 代码更改为类似的代码:
@fieldGroup(field: Field, className: String = "CSVField") = {
<div class="well @className">
<a class="removeCSVField btn danger pull-right">Remove this field</a>
Name: <input type="text" name='@field("name").name' value='@field("name").value'>
Type: <input type="text" name='@field("type").name' value='@field("type").value'>
</div>
}
@repeat(csvForm("fields")) { csvField =>
@fieldGroup(csvField)
}
@**
* Keep an hidden block that will be used as template for Javascript copy code
**@
@fieldGroup(csvForm("fields[x]"),className = "CSVField_template")
<a class="addCSVField btn success">Add another field</a>
并添加CSS样式.CSVField_template{display: none;}
我没有测试任何一个,所以它可能无法编译。但是,我只是遵循了与 Forms example (play 2.2.x
中类似的方法
使用 Play 2.3.7 (Java) 我有以下场景。
我有一个 class CSVData
,其中包含 CSVField
类型的列表。以下是这些 classes 的属性:
public class CSVData{
private String name;
private String description;
private String dataFilePath;
private List<CSVField> fields;
private Double latitude;
private Double longitude;
// rest of class... }
和
public class CSVField {
private String name;
private String type;
...}
制作表单以输入 CSVData
的困难在于我有这个嵌套的 List<CSVField>
属性,而 CSVField
是包含两个字符串的自定义类型。我需要表单是动态的,因为它应该能够接受任意数量的 CSVField
s(至少 1)。跟Java Form Documentation, it seems like I should register a custom DataBinder for CSVField, however I can't find any examples that do this with multiple input strings. This example类似,不过它只绑定一个字段。
Here is a video of what type of user input I would like to have. I made my view using this example code for adding dynamic fields。文本字段(名称)和 select 下拉项(类型)的组合是我需要绑定到 CSVField
然后添加到 CSVData
中的 List<CSVField> fields
目的。 如何使用 Play Framework 执行此操作?
编辑:在我的控制器中我试过这个
Form<CSVData> formData = Form.form(CSVData.class).bindFromRequest();
我在视图中尝试了这个
@helper.repeat(csvForm("fields"), min = 1) { csvField =>
@multiDataField(csvField,
label = "Column Name and Type",
gsnTypes,
help = "Enter the column names and respective types for the data items in the file")
}
其中 multiDataField
是 this 模板。但它没有正确绑定动态字段并在 fields
上抛出无效验证错误。我想我的问题是我不知道在我的 multiDataField
模板中使用什么 name
属性。有什么建议吗?
您不需要任何客户数据绑定器。无需任何额外的绑定注册即可支持包含复杂对象的列表。
在视图中您可以使用 @repeat
Helper,在控制器中您已经做得很好了。
这里有一个关于 Play and Forms, or directly in TypeSafe
的完整示例编辑
在重复块内,csvField
是列表中每个 Form 对象的实例。然后,您需要添加视图所需的所有 HTML 元素。例如(没有 Bootstrap 的简化):
@helper.repeat(csvForm("fields"), min = 1) { csvField =>
Name: <input type="text" name='@csvField("name").name' value='@csvField("name").value'>
Type: <input type="text" name='@csvField("type").name' value='@csvField("type").value'>
}
您可以在 samples provide in Play 2.2.x 中找到更完整的示例。要在 2.3.x 中编译它,可能需要稍微更改一些内容,而不是使用 Bootstrap 3.x,但逻辑是相同的。
编辑 (2)
如果要向视图中动态添加 元素,您需要注意在添加新元素时设置正确的数组编号。为此,您需要使用 JQuery:
$('.addCSVField').click(function() {
var CSVFields = $(this).parents('.CSVField');
var template = $('.CSVField_template', CSVFields);
template.before('<div class="clearfix CSVField">' + template.html() + '</div>');
renumber();
})
$('.removeCSVField').click(function() {
$(this).parents('.CSVField').remove();
renumber();
})
var renumber = function() {
$('.CSVField').each(function(i) {
$('input', this).each(function() {
$(this).attr('name', $(this).attr('name').replace(/fields\[.+?\]/g, 'fields[' + i + ']'));
})
})
}
然后您需要将 HTML/Scala 代码更改为类似的代码:
@fieldGroup(field: Field, className: String = "CSVField") = {
<div class="well @className">
<a class="removeCSVField btn danger pull-right">Remove this field</a>
Name: <input type="text" name='@field("name").name' value='@field("name").value'>
Type: <input type="text" name='@field("type").name' value='@field("type").value'>
</div>
}
@repeat(csvForm("fields")) { csvField =>
@fieldGroup(csvField)
}
@**
* Keep an hidden block that will be used as template for Javascript copy code
**@
@fieldGroup(csvForm("fields[x]"),className = "CSVField_template")
<a class="addCSVField btn success">Add another field</a>
并添加CSS样式.CSVField_template{display: none;}
我没有测试任何一个,所以它可能无法编译。但是,我只是遵循了与 Forms example (play 2.2.x
中类似的方法