Я использую платформу Play 2.2. У меня вопрос о нескольких флажках в форме и о том, как правильно связывать и обрабатывать их. Я ищу Java-решение.
Предположим, у нас есть сайт для блогов. Мы хотим реализовать функциональные возможности, которые, когда пользователи создают/редактируют запись в блоге, у них есть возможность добавить к этим блогам ноль ко многим тегам. Эти параметры тега отображаются как длинный список флажков в форме. Например, если он/она создает запись в блоге "10 вещей, которые нужно делать на луне в свободное время", и хочет связать ее с тегами "звездного взгляда", "ходьбы" и "гольфа", он просто проверьте соответствующие флажки в процессе создания.
Я не знаю, как привязать модели к представлению или как обработать список флажков после отправки запроса. Вот пример экспериментального кода.
Сначала у нас есть модели: (Они являются ebean-сущностями)
public class Blog extends Model {
...
@ManyToMany(cascade=CascadeType.REMOVE)
public List<Tag> tags = new ArrayList<>();
...
}
public class Tag extends Model {
@Id
public Long id;
public String name;
...
}
В представлении мы передаем полный список тегов для представления: (Я не уверен, что этот метод верен)
@(tags: java.util.List[Tag], blogEntryForm: Form[Blog])
...
@form(routes.Application.create(), 'id -> "blogEntryForm") {
...
@for((tag, index) <- tags.zipWithIndex) {
<div class="checkbox">
<label>
<input type="checkbox" name="tags[@index]" value="@tag.id">
@tag.name
</label>
</div>
}
...
}
В контроллере мы обрабатываем форму:
public static Result createBlogEntry() {
Form<Blog> filledForm = Form.form(Blog.class).bindFromRequest();
if (filledForm.hasErrors()) {
...
}
// process checkboxes
???
}
Любая помощь приветствуется.
Кажется, это работает.
@(tags: java.util.List[Tag], blogEntryForm: Form[Blog])
@helper.form(routes.Application.createBlogEntry(), 'id -> "blogEntryForm") {
@for((tag, index) <- tags.zipWithIndex) {
<div class="checkbox">
<label>
<input type="checkbox" name="tags[@index].id" value="@tag.id">
@tag.name
</label>
</div>
}
<input type="submit" />
}
в моем контроллере у меня есть
public static Result renderTestForm() {
Tag tag1 = new Tag();
tag1.id = 1L;
tag1.name = "tag1";
Tag tag2 = new Tag();
tag2.id = 2L;
tag2.name = "tag2";
List<Tag> tagList = new ArrayList<>();
tagList.add(tag1);
tagList.add(tag2);
Form<Blog> blogForm = Form.form(Blog.class);
return ok(views.html.testForm.render(tagList, blogForm));
}
public static Result createBlogEntry() {
Form<Blog> filledForm = Form.form(Blog.class).bindFromRequest();
if (filledForm.hasErrors()) {
return ok();
}
// process checkboxes
Blog b = filledForm.get();
b.save();
play.Logger.debug(filledForm.toString());
play.Logger.debug(filledForm.get().toString());
List<Blog> bList = Blog.finder.all();
List<Tag> tList = Tag.finder.all();
play.Logger.debug("********");
play.Logger.debug(bList.toString());
play.Logger.debug(tList.toString());
play.Logger.debug("********");
return ok();
}
Это просто, чтобы проверить, что все это работает, поэтому я создаю два тега для флажков в представлении и их рендеринг. Метод createBlogEntry
просто производит вывод отладки, чтобы убедиться, что данные были привязаны к объекту Blog
успешно.
У моих файлов маршрутов есть эти.
GET /testForm controllers.Application.renderTestForm
POST /testForm controllers.Application.createBlogEntry
и вот мои модели.
@Entity
@Table(name = "blogs")
public class Blog extends Model {
@Id
public Long id;
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name = "blog_tags")
public List<Tag> tags = new ArrayList<>();
public String toString() {
String s = "";
for (Tag t : tags) {
s += " " + t.toString();
}
return s;
}
public static final Finder<Long, Blog> finder = new Finder<>(Long.class, Blog.class);
}
@Entity
@Table(name = "tags")
public class Tag {
@Id
public Long id;
public String name;
@ManyToMany(mappedBy = "tags")
public List<Blog> blogs = new ArrayList<>();
public static final Model.Finder<Long, Tag> finder = new Model.Finder<>(Long.class, Tag.class);
}
У меня не было аннотаций в моем коде, потому что я не использовал базу данных, пока я тестировал, будет ли это работать.
bindFromRequest
работает непосредственно с этим кодом для привязки к модели блога. Разница заключается вtags[@index].id
вместоtags[@index]
и@tag.id
вместоtag.id
Я дополню свой ответ остальной частью моего кода, но я думаю, вы обнаружите, что он в основном совпадает с вашим, за исключением данных фиктивного тестирования.