2016-07-25 9 views
2

Thymeleafによって処理されるHTMLフォームを使用して、Spring内のProjectオブジェクトを生成またはバインドしたいとします。すべてがこれまでのところ働いていますが、チェックボックスをチェックすることでロールで埋められるリストフィールドはまだ機能していません。Spring Thymeleafチェックボックスの値をコレクションフィールドにバインドする方法

Projectクラス

package com.floriantoenjes.instateam.model; 

import javax.persistence.*; 
import java.util.List; 

@Entity 
public class Project { 

    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    private int id; 
    private String name; 
    private String description; 
    private String status; 

    @ManyToMany 
    private List<Role> rolesNeeded; 

    @ManyToMany 
    private List<Collaborator> collaborators; 

    public Project() { 
    } 

    public int getId() { 
     return id; 
    } 

    public void setId(int id) { 
     this.id = id; 
    } 

    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 

    public String getDescription() { 
     return description; 
    } 

    public void setDescription(String description) { 
     this.description = description; 
    } 

    public String getStatus() { 
     return status; 
    } 

    public void setStatus(String status) { 
     this.status = status; 
    } 

    public List<Role> getRolesNeeded() { 
     return rolesNeeded; 
    } 

    public void setRolesNeeded(List<Role> rolesNeeded) { 
     this.rolesNeeded = rolesNeeded; 
    } 

    public List<Collaborator> getCollaborators() { 
     return collaborators; 
    } 

    public void setCollaborators(List<Collaborator> collaborators) { 
     this.collaborators = collaborators; 
    } 
} 

役割クラス

package com.floriantoenjes.instateam.model; 

import javax.persistence.Entity; 
import javax.persistence.GeneratedValue; 
import javax.persistence.GenerationType; 
import javax.persistence.Id; 

@Entity 
public class Role { 

    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    private Integer id; 
    private String name; 

    public Role() { 
    } 

    public Integer getId() { 
     return id; 
    } 

    public void setId(Integer id) { 
     this.id = id; 
    } 

    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 
} 

コントローラ

package com.floriantoenjes.instateam.web.controller; 

import com.floriantoenjes.instateam.model.Project; 
import com.floriantoenjes.instateam.model.Role; 
import com.floriantoenjes.instateam.service.ProjectService; 
import com.floriantoenjes.instateam.service.RoleService; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.stereotype.Controller; 
import org.springframework.ui.Model; 
import org.springframework.web.bind.annotation.RequestMapping; 
import org.springframework.web.bind.annotation.RequestMethod; 

import java.util.List; 

@Controller 
public class ProjectController { 
    @Autowired 
    ProjectService projectService; 

    @Autowired 
    RoleService roleService; 

    @RequestMapping("/add") 
    public String newProjectForm(Model model) { 
     List<Role> roles = roleService.findAll(); 

     model.addAttribute("project", new Project()); 
     model.addAttribute("roles", roles); 

     return "edit_project"; 
    } 

    @RequestMapping(value = "/add", method = RequestMethod.POST) 
    public String addProject(Project project) { 
     projectService.save(project); 
     return "redirect:/index"; 
    } 

} 

テンプレート

<!DOCTYPE html> 
<html> 
    <head th:replace="layout :: head('Edit Project')"></head> 
    <body> 
     <header> 
      <div class="container"> 
       <div class="site-header"> 
        <a class="logo" href="index.html">InstaTeam</a> 
        <a class="new-project button icon-left" href="#"><i class="material-icons">add</i> New Project</a> 
       </div> 
      </div> 
     </header> 
     <nav> 
      <ul> 
       <li class="selected"><a href="index.html">Projects</a></li> 
       <li><a href="collaborators.html">Collaborators</a></li> 
       <li><a href="roles.html">Roles</a></li> 
      </ul> 
     </nav> 
     <section> 
      <div class="container wrapper"> 
       <form th:object="${project}" action="" method="post"> 
        <div> 
         <label for="project_name"> Project Name:</label> 
         <input type="text" th:field="*{name}" name="project_name"/> 
        </div> 
        <div> 
         <label for="project_description">Project Description:</label> 
         <textarea rows="4" th:field="*{description}" name="project_description"></textarea> 
        </div> 
        <div> 
         <label for="project_status">Project Status:</label> 
         <div class="custom-select"> 
         <span class="dropdown-arrow"></span> 
          <select th:field="*{status}" name="project_status"> 
           <option value="active">Active</option> 
           <option value="archived">Archived</option> 
           <option value="not_started">Not Started</option> 
          </select> 
         </div> 
        </div> 
        <div> 
         <label for="project_roles">Project Roles:</label> 
         <ul class="checkbox-list"> 
          <li th:each="role : ${roles}"> 
           <input type="checkbox" th:field="*{rolesNeeded}" name="project_roles" th:value="${role.id}"/> 
           <span class="primary" th:text="${role.name}"></span> 
          </li> 
         </ul> 
        </div> 
        <div class="actions"> 
         <input type="submit" value="Save" class="button"/> 
         <a href="#" class="button button-secondary">Cancel</a> 
        </div> 
       </form> 
      </div> 
     </section> 
    </body> 
</html> 

ご覧のとおり、rolesNeededはコレクションで、ロールのチェックボックスにチェックを入れ、フォームを送信すると、 "rolesNeeded"コレクションに割り当てられたロールを持つProjectオブジェクトを生成できます。私は今すぐ*{rolesNeeded}{role.id}と入力しているので動作しません。

今私は、次のエラーを取得しています:

There was an unexpected error (type=Bad Request, status=400). Validation failed for object='project'. Error count: 1

うまくいけば、誰かがこれを解決する方法や、おそらく私は、より詳細なエラーメッセージを取得することができていますか提案を持っています。

種類よろしく、 フロリアン

+0

エラーについて:最も有用な方法は、おそらくブラウザのデバッガで[ネットワーク]タブを開いて、送信されているリクエストデータを調べることです。 – chrylis

+0

"$ {role.id}" />と$ {role.name} ">に関する質問。ロールBean(pojo)クラスを表示できますか? –

+0

chrylisはすばらしいコメントをいただき、ありがとうございました。投稿のリクエストに選択したロールのロールIDが含まれていることを確認してください。 Hey Georges私の質問にロールクラスを追加しました。 – Florian

答えて

1

私は、「役割」に「文字列」から変換@Componentとしてそのクラスをマークし、@Beanを作成するために、自分自身の春Converterを書かなければなりませんでした。それは魅力のように働いた。

@Component 
public class StringRoleConverter implements Converter<String, Role> { 

    @Override 
    public Role convert(String source) { 
     Role role = new Role(); 
     int id = Integer.parseInt(source); 
     role.setId(id); 
     return role; 
    } 

    @Bean 
    public ConversionService getConversionService() { 
     ConversionServiceFactoryBean bean = new ConversionServiceFactoryBean(); 
     Set<Converter> converters = new HashSet<>(); 
     converters.add(new StringRoleConverter()); 
     bean.setConverters(converters); 
     return bean.getObject(); 
    } 
} 
0

は、私の場合、私は2つのコンバータを作成しました:

@Component 
public class RoleStringConverter implements Converter<Role, String> { 

    @Override 
    public String convert(Role role) { 
     return role.getId().toString(); 
    } 

} 

@Component 
public class StringRoleConverter implements Converter<String, Role> { 

    @Autowired 
    private RolesRepository rolesRepository; 

    @Override 
    public Role convert(String source) { 
     return rolesRepository.findOne(Long.parseLong(source)); 
    } 

} 

私はaddFormattersメソッドを上書きし、私のWeb設定でそれらを追加しました。何もする必要はありません。

@Configuration 
@ComponentScan(value = { "controllers", "services", "converters" }) 
@Import(value = { ThymeleafConfig.class, i18nConfig.class }) 
@EnableWebMvc 
public class WebConfig extends WebMvcConfigurerAdapter{ 

    @Autowired 
    private LocaleChangeInterceptor localeChangeInterceptor; 
    @Autowired 
    private StringRoleConverter stringRoleConverter; 
    @Autowired 
    private RoleStringConverter roleStringConverter; 

    @Override 
    public void addViewControllers(ViewControllerRegistry registry) { 
     registry.addViewController("/403").setViewName("403"); 
     registry.addViewController("/about").setViewName("frontend/about"); 
     registry.addViewController("/admin").setViewName("admin/index"); 
     registry.addViewController("/admin/login").setViewName("admin/login"); 
    } 

    @Override 
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { 
     // habilitar procesamiento de contenido estático 
     configurer.enable(); 
    } 

    @Override 
    public void addInterceptors(InterceptorRegistry registry) { 
     registry.addInterceptor(localeChangeInterceptor); 
     registry.addInterceptor(new CacheControlHandlerInterceptor()); 
    } 

    @Bean(name="multipartResolver") 
    public MultipartResolver provideMultipartResolver(){ 
     return new StandardServletMultipartResolver(); 
    } 

    @Override 
    public void addFormatters(FormatterRegistry registry) { 
     registry.addConverter(Role.class, String.class, roleStringConverter); 
     registry.addConverter(String.class, Role.class, stringRoleConverter); 
    } 
} 

私はこれが誰かを助けてくれることを願っています:)。

関連する問題