【问题标题】:How to bind and process a list of checkboxes in a form using the play framework 2如何使用 play framework 2 绑定和处理表单中的复选框列表
【发布时间】:2014-04-21 19:02:46
【问题描述】:

我正在使用 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
  ???
} 

任何帮助将不胜感激。

【问题讨论】:

    标签: java forms checkbox playframework playframework-2.0


    【解决方案1】:

    这似乎行得通。

    @(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。我将用我的其余代码更新我的答案,但我想你会发现它与你的大部分相同,除了模拟测试数据。
    • 不幸的是,这种方法不适用于有人希望在数据库中保留多选类型数据的@ManyToMany 关系。它不能自动完成。我发现的最简单的选择是将 Play 扔出窗口并使用 AngularJS 和 ajax。
    • 我只需调用save()就可以让它持久化到数据库中。不确定您是使用进化还是手动设置数据库,但我将使用我使用的 Ebean 注释更新示例。
    • 那么如何将已经存在的数据条目绑定到表单中的复选框?例如,当您想通过添加/删除标签来编辑已经存在的博客文章时。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-02-09
    • 1970-01-01
    • 1970-01-01
    • 2015-08-30
    • 1970-01-01
    • 2014-11-20
    • 1970-01-01
    相关资源
    最近更新 更多