0

I have a small project where i can add categories to a table in my SQL database. I have another table called products. In the "/addProducts" screen i want a drop down to appear in my form. I would like the dropdown to be populated from the data in the "Categories" table from my database. But at the moment, I am unable to do it.

So if anyone could help me with some thymleaf/html code to show the data in my form i would appreciate it.

Any advice is greatly appreciated.

PS i am not using a DAO class nor do i wish to hardcode the values. Simply would like to be able to fetch the data directly from the database and display it in a dropdown on a form. Thanks :

1 CategoryController

@Slf4j
@Controller

public class CategoryController implements Serializable {
private CategoryRepository categoryRepository;

public CategoryController(CategoryRepository categoryRepository) {
    this.categoryRepository = categoryRepository;
}

@Autowired
CategoryRepository service;

@Autowired
private UserRepository userRepository;


@GetMapping("/category")
public String displayCategory(Model model) {

    model.addAttribute("category", service.findAll());

    return "/category";
}

@GetMapping("/categoryUserView")
public String displayCategoryUser(Model model) {

    model.addAttribute("category", service.findAll());

    return "/categoryUserView";
}





@PostMapping("/addCategory")
public String processOrder(@Valid Category category, BindingResult result, SessionStatus 
  sessionStatus, Model model) {
    if (result.hasErrors()) {
        return "addCategory";
    }

    service.save(category);
    model.addAttribute("category", service.findAll());
    return "category";
}


@GetMapping("/editCategory/{id}")
public String showUpdateCategoryForm (@PathVariable("id") long id, Model model){
    Category category = service.findAllById(id);
    model.addAttribute("category", category);
    return "editCategory";
}

@PostMapping("/updateCategory/{id}")
public String updateFixtures ( @PathVariable("id") long id, @Valid Category category,
                               BindingResult result, Model model){
    if (result.hasErrors()) {
        category.setId((int) id);
        return "editFixtures";
    }


    service.save(category);
    model.addAttribute("category", service.findAll());
    return "redirect:/category";
}


 @GetMapping("/deleteCategory/{id}")
 public String deleteCategory(@PathVariable("id") long id, Model model) {
    Category category  = categoryRepository.findById(id)
            .orElseThrow(() -> new IllegalArgumentException("Invalid user Id:" + id));
    categoryRepository.delete(category);
    model.addAttribute("category", categoryRepository.findAll());
    return "redirect:/category";
  }
 }

ProductController

    @Slf4j
    @Controller
    public class ProductController implements Serializable {
    private ProductRepository productRepository;

    public ProductController(ProductRepository productRepository) {
     this.productRepository = productRepository;
     };


    @Autowired
    ProductRepository service;

    @Autowired
    private UserRepository userRepository;


    @GetMapping("/products")
    public String displayCategory(Model model) {

     model.addAttribute("product", service.findAll());

    return "/product";
   }


   @GetMapping("/addProduct")
   public String showSignUpForm(SessionStatus sessionStatus,
                             @AuthenticationPrincipal User user, Product product, Model 
    model) {

        model.addAttribute("category",service.findAll());


    return "addProduct";
   }

   @PostMapping("/addProduct")
   public String processOrder(@Valid Product product, BindingResult result, SessionStatus 
    sessionStatus, Model model) {
    if (result.hasErrors()) {
        return "addProduct";
    }

    //category.setUser(user);
    service.save(product);
    model.addAttribute("product", service.findAll());
    return "product";
    }

   }

Category Model

   @Data
   @Entity
   @Table(name = "product_categories")
   public class Category {

   @Id
   @GeneratedValue(strategy = GenerationType.AUTO)
   @Column(name = "product_category_id")
   private long id;

   @Column(name = "category_name")
   private String name;

   @Column(name = "category_description")
   private String desc;


   public long 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 getDesc() {
     return desc;
   }

    public void setDesc(String desc) {
    this.desc = desc;
    }
    }

Product Model

    @Data
    @Entity
    @Table(name = "product")
     public class Product {


    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "product_id")
    private long id;

    @OneToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "product_id", referencedColumnName = "product_category_id")
    public Category category;

    @Column(name = "product_name")
    private String name;

    @Column(name = "producy_description")
    private String desc;

    @Column(name = "producy_quanitity")
    private int quantity;

    @Column(name = "producy_price")
    private double price;
   }
  }

AddProducts HTML

    <h1> Add your Products Here</h1>

   <form method="POST" th:action="@{/addProduct}" class="form- 
    container" id="aboutForm">
   
   <div class="form-group col-md-8">
   <label  class="col-form-label">Category </label>
   <select  id="category" name="category" th:field="*{category.id}" >
    <option th:each="category : ${category}" th:value="${category.id}" 
    th:utext="${category.name}"/>
    </select>
   </div>
 </form>

Error from HTMl

    Bean property 'id' is not readable or has an invalid getter 
    method: 
    Does the return type of the getter match the parameter type 
Eamon Mac
  • 181
  • 5
  • 18
  • You can see examples of Thymeleaf drop-downs in some of the answers to this question: [How do I populate a drop down with a list using thymeleaf and spring](https://stackoverflow.com/questions/37715276). That should point you in the right direction. – andrewJames Jul 31 '20 at 00:00
  • I’ve tried them and their approach’s don’t seem to work. – Eamon Mac Jul 31 '20 at 06:11
  • Can you edit your question to show what you have tried, describe the results, and show any error messages? – andrewJames Jul 31 '20 at 11:47
  • Added. I also added the error message i receive when accessing the "/addProducts" page. – Eamon Mac Jul 31 '20 at 16:42
  • Also, every solution i see uses a list but i do not wish to use one. So is there a workaround? – Eamon Mac Jul 31 '20 at 18:26
  • 1
    Unless you want to hard-code the list of items in your drop-down's HTML, you need to pass in a list for Thymeleaf to iterate over. When defining an iterator, you need to give the iteration variable a different name from the list variable. So, this is not appropriate: `th:each="category : ${category}"`. Typically you would have a list called `${categories}` and then refer to each item as `th:each="category : ${categories}"`, Now you have a `${category}` object - and that will have an `id` for you to access (with a valid getter!). – andrewJames Jul 31 '20 at 18:49
  • Thanks man, i literally just made a list to see if it worked...and of course it did. Thanks a million :) – Eamon Mac Jul 31 '20 at 18:58

2 Answers2

0

As specified in the error message you are using two different data type in getter and setter method. Can you try updating your setter from

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

to this

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

Note: Hope you have not tried it.

Vipul Kumar
  • 423
  • 4
  • 11
0

so i followed the advice provided. I created a list and used the findAll method in my repository to display all in the dropdown.

Thanks

Eamon Mac
  • 181
  • 5
  • 18