Populate a Select dropdown from Query with Spring Thymeleaf

Viewed 1342

I need to populate a dropdown list mapping from a entity (table) attribute for a form. Since the values are static (there's only 6 values repeated along the insert values), i thought that it might be a good idea get a list of those values and send to the Controller class and map into the view as Select button with Thymeleaf.

I know i could get the attribute 'Status' values directly from the entity, but i dont know the best way to do it

So, my question is:

Is it possible to populate a select dropdown button from a jpql query? Is there another better way to populate from unique entity attributes?

I tried to create a query like the next one, to get unique values from the attribute 'Status' which belongs to a entity named 'Orders', but this query generates a list without an associated id just the unique values (Also I thought about to create a query with a new temporary autoincrement id column, without success).

This is my entity:

@Data
@Entity
@Table(name="orders")
public class Orders implements Serializable {
    @Id
    private Integer orderNumber;
    
    @Column
    private String orderDate;
    
    @Column
    private String requiredDate;
    
    @Column
    private String shippedDate;
    
    @Column
    private String status;
// ...
}
@Repository("ordersDAO")
public interface OrdersDAO extends JpaRepository<Orders,Integer>{
    
    @Query("SELECT DISTINCT o.status FROM orders o")
// 
    @Transactional(readOnly = true)
    public List <Orders> getAllStatus();

From this point forward i can't resolve (neither the Controller nor form templates).

UPDATE

I'm trying this code, but it doesn't work. Let me know the errors to improve:

Service Implementation

public class OrdersServiceImpl implements OrdersService{
 @Override
    public List<Orders> getAllStatus() {
        return ordersDAO.getAllStatus();
    }
}

Controller

@Controller
@Slf4j
public class IndexController {

    String url = "";

    @Autowired
    @Qualifier("ordersServiceImpl")
    private OrdersService ordersService;
    
    @GetMapping("/")
    public String getStatusDropdown(Model model){
        
        List<Orders> statusDropdown = ordersService.getAllStatus();
        model.addAttribute("statusDropdown", statusDropdown);
        return "forms";
    }

HTML form

<div class="form-row align-items-center">
   <div th:object="${statusDropdown}" class="col-2 my-1">
      <label for="Estado" class="mr-sm-2">Estado</label>
      <select class="custom-select mr-sm-2" id="Estado" form="ordersForm">
      <option selected>Seleccione Estado</option>
      <option th:each="status : ${statusDropdown}" th:text="${status}" th:value="${status}">Estado 1</option>
      </select>
   </div>

   <div class="col align-self-end my-1">
      <input class="btn btn-info" type="submit" value="Buscar" th:href="@{/getOrdersByStatus}">    
   </div>
</div>
2 Answers

Assuming you already have data- Lets say you want to display the list of status (statuses) then

  1. In the controller
model.addAttribute("statuses",statuses);
  1. In thymleaf
 <select >
        <option th:each="status:${statuses}"><span th:text=${status}></span></option>
                   
   </select>

It will populate the dropdown with data whatever you sent

Finally, I got the solution (almost forgot to post it). I had to modify multiple line code in almost all layers:

HTML form (forms.html):

<form id="ordersForm" method="POST" form="ordersForm" 
                                      th:action="@{/searchOrders}" 
                                      th:object="${ordersList}">
        <div class="form-row">
                <div class="col-auto">
                        <label for="Estado">Estado
                        <select class="form-control custom-select" id="status" name="status" form="ordersForm"
                        th:object="${statusDropdown}">
                                <option selected>Seleccione Estado</option>
                                <option th:each="status : ${statusDropdown}" 
                                th:text="${status}" 
                                th:value="${status}">Estado</option>
                        </select>
                        </label>
                </div>
        </div>
        <div class="col-auto mr-1">
                <div>
                        <input class="btn btn-info" type="submit" value="Buscar"/>    
                </div>
        </div>
</form>

Controller

@Controller
public class IndexController {

    String url = "";

    @Autowired
    private OrdersService ordersService; 

@GetMapping("/")
public String getStatusDropdown(Model model){
        List<String> statusDropdown = ordersService.getAllStatus();
        model.addAttribute("statusDropdown", statusDropdown);
    return "forms";

}
}

Service Implementation

@Override
    public List<String> getAllStatus() {
        List<String> statusList = ordersDAO.getAllStatus();
        return statusList;
    }

Repository

@Repository("ordersDAO")
public interface OrdersDAO extends JpaRepository<Orders,Integer>{
    
    @Query(value = "SELECT DISTINCT o.status FROM orders o ORDER BY o.status", nativeQuery = true)
    @Transactional(readOnly = true)
    public List<String> getAllStatus();

Thank you all for your advice!

Related