It's my first topic at this beautiful site;)
I cant fix this, I am trying to present names of states and products in drop down lists. Intelij is helping me by underlines these fields.
https://ibb.co/wKgV940 (cant add image)
When I am adding th:object to divs or form it doesn't help.
There are racords on my db, and mathod retrieves values properly.
<div class="row justify-content-center">
<div class="form-group col-md-8" >
<label for="firstName" class="col-form-label">Choose State</label>
<select class="form-control" th:field="*{state.id}" id="state">
<options items="${listStates}>"></options>
<option th:each="state : ${states}"
th:value="${state.id}"
th:utext="${state.stateName}"></option>
</select>
</div>
<div class="form-group col-md-8" >
<label for="firstName" class="col-form-label">Choose products</label>
<select class="form-control" th:field="*{product.id}" id="product">
<option th:each="product : ${products}"
th:value="${product.id}"
th:utext="${product.productName}"></option>
</select>
</div>
<div class="form-group col-md-8">
<label for="firstName" class="col-form-label">Start price</label>
<input id="firstName" type="number" value="1" min="0" max="1000" step="1"/>
</div>
<div class="form-group col-md-8">
<label for="firstName" class="col-form-label">Preferred final prize</label>
<input type="text" class="form-control"
id="lastName" placeholder=""/>
</div>
<div class="form-group col-md-8">
<label for="firstName" class="col-form-label">Logistic costs</label>
<input type="text" class="form-control"
id="email" placeholder=""/>
</div>
<div class="col-md-6">
<input type="submit" class="btn btn-primary" value=" Calculate ">
</div>
</div>
</form>
public class CalculateController {
#Autowired
private StateRepository stateService;
#Autowired
private ProductRepository productService;
#RequestMapping(value = { "/calculateForm" }, method = RequestMethod.GET)
public String selectState(Model model) {
List<Product> product = new ArrayList<>();
List<State> state = new ArrayList<>();
model.addAttribute("product", product);
model.addAttribute("state", state);
List<Product> products = productService.findAll();
List<State> states = stateService.findAll();
model.addAttribute("states", states);
model.addAttribute("products", products);
return "calculateForm";
}
}
public class Product {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String productName;
private String category;
private Double wholePrice;
public Product() {
}
public Product(String productName, String category, Double wholePrice) {
this.productName = productName;
this.category = category;
this.wholePrice = wholePrice;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getProductName() {
return productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
public String getCategory() {
return category;
}
public void setCategory(String category) {
this.category = category;
}
public Double getWholePrice() {
return wholePrice;
}
public void setWholePrice(Double wholePrice) {
this.wholePrice = wholePrice;
}
}
I have replaced this:
List<Product> product = new ArrayList<>();
List<State> state = new ArrayList<>();
model.addAttribute("product", product);
model.addAttribute("state", state);
by this:
Product product = new Product();
State state = new State();
model.addAttribute("product", product);
model.addAttribute("state", state);```
now it works. Thank you.
Related
Customer.java
#Entity
#Data
#AllArgsConstructor
#NoArgsConstructor
public class Customer {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String relative;
private String address;
private Long aadhar;
private Long contact;
private String townname;
public Long getAadhar() {
return aadhar;
}
public void setAadhar(Long aadhar) {
this.aadhar = aadhar;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getRelative() {
return relative;
}
public void setRelative(String relative) {
this.relative = relative;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public Long getContact() {
return contact;
}
public void setContact(Long contact) {
this.contact = contact;
}
public String getTownname() {
return townname;
}
public void setTownname(String townname) {
this.townname = townname;
}
CustomerController.java
#Controller
public class CustomerController {
#Autowired
private CustomerService customerService;
#Autowired
private TownService townService;
#GetMapping("/customer")
public String findAllCustomers(Model model) {
model.addAttribute("customers", customerService.findAllCustomers());
model.addAttribute("towns", townService.findAllTown());
return "customer";
}
#PostMapping("/customer/addnew")
public String addNew(Customer customer) {
customerService.saveCustomer(customer);
return "redirect:/customer";
}
#RequestMapping(value="/customer/findCustomerById/",method = RequestMethod.GET)
#ResponseBody
public Optional<Customer> findCustomerById(Long id) {
return customerService.getCustomerById(id);
}
}
CustomerService.java
#Service
public class CustomerService {
#Autowired private CustomerRepository customerRepository;
public List<Customer> findAllCustomers() {
return customerRepository.findAll();
}
public void saveCustomer(Customer customer) {
customerRepository.save(customer);
}
public Optional<Customer> getCustomerById(Long id) {
return customerRepository.findById(id);
}
}
customer.html
<a th:href="#{/customer/findCustomerById/(id=${customer.id})}"
type="button" class="btn btn-primary "
data-toggle="modal" data-target=".bd-edit-modal-lg">
<span class="material-icons" >edit</span></a>
<form class="row g-3">
<div class="col-md-8">
<label for="customername" class="form-label">Customer ID</label>
<input type="text" class="form-control" id="nameEdit" name="id"
onKeyup="this.value = this.value.toUpperCase()" readonly>
</div>
<div class="col-md-4">
<label for="aadhar" class="form-label">Aadhar No.</label>
<input type="number" min="0" max="999999999999" class="form-control" id="aadhar"
name="aadhar">
</div>
<div class="col-md-8">
<label for="customername" class="form-label">Customer Name</label>
<input type="text" class="form-control" id="nameEdit" name="name"
onKeyup="this.value = this.value.toUpperCase()" required>
</div>
<div class="col-md-6">
<label for="relative" class="form-label">S/O,D/O,C/O</label>
<input type="text"class="form-control" id="relativeEdit" name="relative"
onKeyup="this.value = this.value.toUpperCase()" required>
</div>
<div class="col-md-6">
<label for="contact" class="form-label">Contact No.</label>
<input type="number" minlength="10" max="9999999999" class="form-control"
id="contactEdit" name="contact">
</div>
<div class="col-12">
<label for="inputAddress5" class="form-label">Address</label>
<input type="text"class="form-control" id="addressEdit" name="address"
onKeyup="this.value = this.value.toUpperCase()" placeholder="1234 Main St" required>
</div>
<div class="col-md-4">
<label for="inputTown" class="form-label" id="selecttown">Town/Area</label>
<select class="form-control" id="selecttownEdit" name="townname" required>
<option selected>Choose...</option>
<option th:each="town:${towns}" th:value="${town.townname}"
th:text="${town.townname}">...
</option>
</select>
</div>
<div class="text-center" style="margin-bottom:10px">
<button type="submit" class="btn btn-primary mx-1 my-1">Submit</button>
<button type="reset" class="btn btn-secondary mx-1 my-1">Reset</button>
</div>
</form><!-- End Multi Columns Form -->
I checked my responsebody in postman,works fine.But i am stuck at how to populate this data to the form.anything i tried my html page becames blank
My Json Response Body:
{
"id": 1,
"name": "M",
"relative": "U",
"address": "130",
"aadhar": 8891,
"contact": 90,
"townname": "DAR"
}
I am using Spring and Thymeleaf templates. What I am trying is, to show a customer's addresses within a Thymeleaf template (using Bootstrap tabs) in a many-to-one relation.
I can't get the addresses to show up or add new ones. Any help is appreciated!
customerAddressform.html (Thymeleaf)
<html>
<head lang="en">
<!--/*/ <th:block th:include="fragments/headerinc :: head"></th:block> /*/-->
</head>
<body>
<div th:if="${not #lists.isEmpty(address)}">
<table class="table table-striped table-bordered table-hover">
<thead class="thead-dark">
<tr>
<th>Id</th>
<th>Address Id</th>
<th>Description</th>
<th>Price</th>
<th>Delete</th>
</tr>
</thead>
<tr th:each="address : ${address}">
<td th:text="${address.id}" href="/customer/${customer.id}/address/${address.id}">Id</td>
<td><a th:text="${address.addressId}" th:href="${ '/customer/' + customer.id + '/address/' + address.id}">Address
Id</a></td>
<td>description</td>
<td>price</td>
<td><a>Delete</a></td>
</tr>
</table>
</div>
<div>
<!-- Button trigger modal -->
<button type="button" href="#" class="btn-primary btn-sm btn-block btn-addrow" data-toggle="modal"
data-target="#modalNewCustomerAddress">+</button>
<!-- Modal -->
<div class="modal fade" id="modalNewCustomerAddress" tabindex="-1" role="dialog" aria-labelledby="New Address"
aria-hidden="true">
<div class="modal-dialog modal-dialog-centered modal-dialog-scrollable" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalScrollableTitle">New Address</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body margin-15">
<form id="customerAddressForm" th:object="${address}" th:action="#{/customer/{customer.id}/address/new}" method="post">
<div class="row">
<input type="hidden" />
<input type="hidden" />
<label for="streetName">Street:</label>
<input type="text" class="form-control form-control-lg" th:field="*{streetName}" id="streetName" />
<label for="houseNumber">House Number:</label>
<input type="text" class="form-control form-control-lg" id="houseNumber"/>
<label for="postalCode">Postal Code:</label>
<input type="text" class="form-control form-control-lg" id="postalCode"/>
<label for="city">City:</label>
<input type="text" class="form-control form-control-lg" id="city"/>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="submit" form="customerAddressForm" class="btn btn-primary">Save</button>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
AddressController.java
#Controller
public class AddressController {
private AddressService addressService;
#Autowired
public void setAddressService(AddressService addressService) {
this.addressService = addressService;
}
#RequestMapping(value = "/address", method = RequestMethod.GET)
public String list(Model model){
model.addAttribute("address", addressService.listAllAddress());
System.out.println("Returning address:");
return "customerAddress";
}
// #RequestMapping("address/{id}")
// public String showAddress(#PathVariable Integer id, Model model){
// model.addAttribute("address", addressService.getAddressById(id));
// return "addressshow";
// }
#RequestMapping("customer/{customer.id}/address")
public String edit(#PathVariable Integer id, Model model){
model.addAttribute("address", addressService.getAddressById(id));
return "customerAddressform";
}
#RequestMapping("customer/{customer.id}/address/new")
public String newAddress(Model model){
model.addAttribute("address", new Address());
return "customerAddressform";
}
// #RequestMapping(value = "address", method = RequestMethod.POST)
// public String saveAddress(Address address){
// addressService.saveAddress(address);
// //return "redirect:/addresss";
// return "redirect:/address/" + address.getId();
// }
#RequestMapping("customer/{customer.id}/deleteAddress")
public String deleteAddress(#RequestParam Integer id) {
addressService.deleteAddressById(id);
return "redirect:/customer/{customer.id}/address";
}
}
Address.java
#Entity
public class Address {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
#Version
private Integer version;
private String addressId;
private String addressType;
private String streetName;
private String houseNumber;
private String postalCode;
private String cityName;
private String country;
#ManyToOne(fetch = FetchType.LAZY, optional = false)
#JoinColumn(name = "customer_id", nullable = false)
#OnDelete(action = OnDeleteAction.CASCADE)
private Customer customer;
public Address(){
}
public Address(String addressId, String addressType, String streetName, String houseNumber, String postalCode, String cityName, String country, Customer customer){
this.addressId = addressId;
this.addressType = addressType;
this.streetName = streetName;
this.houseNumber = houseNumber;
this.postalCode = postalCode;
this.cityName = cityName;
this.country = country;
this.customer = customer;
}
Customer.java
#Entity
public class Customer {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
#Version
private Integer version;
private String customerId;
private String name;
#OneToMany(fetch=FetchType.LAZY, mappedBy="customer")
private Set<Address> address;
this is my html code my code always save null in foreign key columns
please help and try to correct my code please
<div th:if="${mode == 'MODE_NEW'}">
<div class="container">
<div class="row">
<form autocomplete="off"
th:action="#{/admin/user-task/save}"
th:object="${user_task}" method="post" class="form-horizontal"
role="form">
<fieldset>
<!-- Form Name -->
<legend>User Task Assignment</legend>
<!-- Text input-->
<input type="hidden" name="id" th:field="${user_task.id}" />
<div class="form-group">
<label class="col-md-4 control-label">User</label>
<div class="col-md-4 text-left">
<select class="selectpicker" data-live-search="true"
title="Select User" name="user" tabindex="-98">
<option th:each="user: ${users}" th:value="${user.id}"
th:text="${user.name}"></option>
</select>
</div>
</div>
<div class="form-group">
<label class="col-md-4 control-label">Task</label>
<div class="col-md-4 text-left">
<select class="selectpicker" data-live-search="true"
title="Select Task" name="task" tabindex="-98">
<option th:each="task: ${tasks}" th:value="${task.id}"
th:text="${task.name}"></option>
</select>
</div>
</div>
<!-- Button (Double) -->
<div class="form-group">
<label class="col-md-4 control-label" for="submitButton"></label>
<div class="col-md-8">
<button type="submit" id="submitButton" name="submitButton"
class="btn btn-success">Save</button>
<button type="button" class="btn btn-inverse"
onclick="window.history.back()">Cancel</button>
</div>
</div>
</fieldset>
</form>
</div>
</div>
</div>
this is my controller where i have tried every thing but it not save directly please suggest in my code
#RequestMapping(value = "/save", method = RequestMethod.POST)
public ModelAndView saveUserTask(#Valid UserTask userTask,BindingResult bindingResult) throws UserTaskException {
ModelAndView modelAndView = new ModelAndView("redirect:/admin/user-task/all");
modelAndView.addObject("auth", getUser());
modelAndView.addObject("control", getUser().getRole().getRole());
User user=new User();
user.getUserTask();
Task task =new Task();
task.getUserTask();
userTask.setTask(task);
userTask.setUser(user);
userTaskService.save(userTask);
return modelAndView;
}
this is my dao interface in which calls method
public interface UserTaskDao {
public void save(UserTask user_task) throws UserTaskException;
}
this my DaoImpl in which I use hibernate session
#Override
public void save(UserTask user_task) throws UserTaskException {
Session session = this.sessionFactory.getCurrentSession();
try {
session.save(user_task);
}catch(HibernateException e) {
throw new UserTaskException("Error while saving user Task id and role id: "+e);
}
}
this is my service class
#Service
#Transactional
public class UserTaskService {
#Autowired
private final UserTaskDao userTaskDao; //userTaskDao
public UserTaskService(UserTaskDao userTaskDao) {
this.userTaskDao = userTaskDao;
}
public void save(UserTask user_task) throws UserTaskException{
userTaskDao.save(user_task);
}
}
My UserTask.java Class
#Entity(name="user_task")
public class UserTask implements Serializable {
#Id
#GeneratedValue
private int id;
#ManyToOne
#JoinColumn(name = "USER_ID", referencedColumnName = "id")
private User user;
#ManyToOne
#JoinColumn(name = "TASK_ID", referencedColumnName = "id")
private Task task;
public UserTask(UserTaskBean userTaskBean) {
}
public UserTask() {
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public Task getTask() {
return task;
}
public void setTask(Task task) {
this.task = task;
}
}
In my User.java class
#OneToMany(mappedBy = "user")
private Set<UserTask> userTask = new HashSet<UserTask>();
In my Task.java class
#OneToMany(mappedBy = "task")
private Set<UserTask> userTask = new HashSet<UserTask>();
I am using SpringMVC and tring to read params from form. My bean looks like this :
public class ChannelBean {
private Integer id;
private Integer siteId;
private String name;
private Boolean active;
private Boolean premium;
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;
}
public Boolean getActive() {
return active;
}
public void setActive(Boolean active) {
this.active = active;
}
public Boolean getPremium() {
return premium;
}
public void setPremium(Boolean premium) {
this.premium = premium;
}
public Integer getSiteId() {
return siteId;
}
public void setSiteId(Integer siteId) {
this.siteId = siteId;
}
}
And on the front end i have handlebars template :
<script id="editFormTemplate" type="text/x-handlebars-template">
<form id="channelForm" class="form-horizontal" action="/admin/channel/save.action" method="POST">
<input type="hidden" readonly="readonly" name="siteId" value="${selectedSiteId}">
<input type="hidden" readonly="readonly" name="id" value="{{id}}">
<div class="form-group">
<label class="col-sm-2 control-label channelName">Name<span class="required">*</span></label>
<div class="col-sm-10">
<input class="form-control" type="text" name="name" value="{{name}}" />
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">Premium</label>
<div class="col-sm-10">
<input type="checkbox" name="premium" {{#if premium}}checked{{/if}} value="{{premium}}">
</div>
</div>
<cms:csrfToken />
<div class="modal-footer">
<button type="submit" class="btn btn-edit btn-primary has-spinner submitEditButton">Ok<span class="spinner"><i class="fa fa-refresh fa-spin"></i></span></button>
<button type="button" class="btn btn-warning" data-dismiss="modal">Cancel</button>
</div>
</form>
</script>
In the controller in Java when i receive Bean, 'name' value is set properly but premium that comes from checkbox is null ?
Since you are using Boolean you need to initialise the value to false when the page loads. So either initialize premium to false on the page load OR
change private Boolean premium in the ChannelBean.java to private boolean premium.
I created a form, that has 2 fields (product name and price) and dropdown list of category objects (product's categories).
I have no idea how to make this work, when I have got a of Category objects to be set in Product object.
Product:
public class Product {
private String name;
private Category category;
private int price;
public Product() {
}
public Product(String name, Category category, int price) {
this.name = name;
this.category = category;
this.price = price;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Category getCategory() {
return category;
}
public void setCategory(Category category) {
this.category = category;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
}
Product controller:
#ModelAttribute("categoryList")
public List<Category> categoryList() {
return categoryService.getCategories();
}
#RequestMapping("/products/add")
public ModelAndView addProductForm() {
ModelAndView mv = new ModelAndView("addProduct");
mv.addObject("product", new Product());
return mv;
}
#RequestMapping(value = "/products/add/process", method = RequestMethod.POST)
public ModelAndView addProduct(#ModelAttribute("product") Product product) {
ModelAndView mv = new ModelAndView("products");
System.out.println("added " + product.getName() + " " + product.getPrice());
return mv;
}
The form:
<form class="form-horizontal" action="#"
th:action="#{/products/add/process}" th:object="${product}"
method="post">
<fieldset>
<!-- Form Name -->
<legend>Add product</legend>
<!-- Text input-->
<div class="form-group">
<label class="col-md-4 control-label" for="textinput">Product
name</label>
<div class="col-md-4">
<input id="textinput" name="textinput" placeholder="Product name"
class="form-control input-md" required="" type="text"
th:field="*{name}"></input>
</div>
</div>
<!-- Select Basic -->
<div class="form-group">
<label class="col-md-4 control-label" for="selectbasic">Category</label>
<div class="col-md-4">
<select th:field="*{category}">
<option th:each="cat : ${categoryList}" th:value="${cat.getId()}"
th:text="${cat.getName()}"></option>
</select>
</div>
</div>
<!-- Text input-->
<div class="form-group">
<label class="col-md-4 control-label" for="textinput">Price</label>
<div class="col-md-4">
<input id="textinput" name="textinput" placeholder=""
class="form-control input-md" required="" type="text"
th:field="*{price}"></input>
</div>
</div>
<!-- Button -->
<div class="form-group">
<label class="col-md-4 control-label" for="singlebutton"></label>
<div class="col-md-4">
<button id="singlebutton" name="singlebutton"
class="btn btn-success">Add product</button>
</div>
</div>
</fieldset>
</form>
Additional Info from comments
When I submit it (see addProduct method - it's a form handler) I get: java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [com.example.shop.Category] for property 'category': no matching editors or conversion strategy found]. I simply can't convert String coming from dropdown to an object
Problem is that Spring doesn't have a built-in conversion ability from String to Category. It knows it needs a Category to use the setCategory(Category category) method of Product, but has no way of converting the String it gets from your posted drop down into one. Thus, you need to be a dear and help Spring some by telling it how to do the conversion and define a converter, see Spring docs for more info.
Easiest option is to use Converter SPI:
package com.example.shop.converter;
final class StringToCategoryConverter implements Converter<String, Category> {
public Category convert(String source) {
Category category;
// Put your conversion logic here
return category;
}
}
In your case, I'd guess you'll want to use: CategoryService.getCategory(int id) or a similar method.
Then you need to configure Spring to actually use your converter, here's an XML example of how to do that:
<mvc:annotation-driven conversion-service="conversionService" />
<bean id="conversionService"
class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<list>
<bean class="com.example.shop.converter.StringToCategoryConverter" />
</list>
</property>
</bean>