Search code examples
javaspring-bootthymeleaf

How to add value in java list in thymeleaf


I am working with Java ArrayList and thymeleaf. I need to use the list in thymeleaf for adding value dynamically. I don't understand how to do that?

Model

public class MedicineDTO {
    private Long brandId;
    private Long stockId;
    private double quantity;
    private double discount;
    private double total;
}

public class InvoiceDTO {
    private String customerName;
    private String mobileNumber;
    private List<MedicineDTO> medicineDTOList;
    private double averageDiscount;
    private double totalDiscount;
    private double grandTotal;
}

Controller

@RequestMapping(value = "/pos")
public String getPOS(Model model) {
   List<Brand> brandList = brandService.getAllBrands();
   List<MedicineDTO> medicineDTOList = new ArrayList<>();
   InvoiceDTO invoiceDTO = new InvoiceDTO();
   invoiceDTO.setMedicineDTOList(medicineDTOList);
   model.addAttribute("medicinedto", new MedicineDTO());
   model.addAttribute("invoicedto", invoiceDTO);
   model.addAttribute("brands", brandList);
   return "pos";
}

@PostMapping(value="/pos/payment")
public String makePayment(InvoiceDTO invoiceDTO){
    System.out.println(invoiceDTO);
    service.makePayment(invoiceDTO);
    return "invoice/invoice";
}

pos.html

<form id="posForm" th:action="@{/pos/payment}" th:object="${invoicedto}" method="post">
   <div class="card-body">
      <div class="form-group row">
         <label class="col-sm-2 col-form-label" for="name">Customer Name</label>
         <div class="col-sm-3">
            <input type="text" class="form-control" id="name"
               th:field="*{customerName}"
               placeholder="Enter Customer Name">
         </div>
      </div>
      <div class="form-group row">
         <label class="col-sm-2 col-form-label" for="mobile">Mobile No</label>
         <div class="col-sm-3">
            <input type="text" class="form-control" id="mobile"
               th:field="*{mobileNumber}"
               placeholder="Enter Mobile Number">
         </div>
      </div>
      <div class="col-sm-4 col-md-2">
         <button type="button" class="btn btn-success btn-sm add-row">
         Add
         </button>
         <button type="reset" class="btn btn-primary btn-sm">
         Reset
         </button>
      </div>
      <table class="table" id="brand_tbl">
         <thead>
            <tr>
               <th>Brand Name</th>
               <th>Expired Date</th>
               <th>Stock</th>
               <th>Quantity</th>
               <th>Price</th>
               <th>Discount %</th>
               <th>Total</th>
               <th>Action</th>
            </tr>
         </thead>
         <tbody>
            <tr th:object="${medicinedto}">
               <td>
                  <select id="selectBrand1" class="form-control select2"
                     th:field="*{brandId}"
                     onchange="changeBrand(this);"
                     style="width: 100%;">
                     <option value=""> --</option>
                     <option th:each="brand : ${brands}"
                        th:value="${brand.id}"
                        th:utext="${brand.name}">
                  </select>
               </td>
               <td style="width:15%">
                  <select id="selectDate1" class="form-control select2"
                     onchange="changeDate(this);"
                     style="width: 100%;">
                     <option value=""> --</option>
                  </select>
               </td>
               <td style="width:10%">
                  <input type="number" class="form-control" id="stock1"
                     placeholder="" disabled>
                  <input type="hidden" id="stockId1" th:field="*{stockId}">
               </td>
               <td style="width:10%">
                  <input type="number" class="form-control" id="quantity1"
                     th:field="*{quantity}"
                     onchange="changeQuantity(this);"
                     placeholder="">
               </td>
               <td style="width:12%">
                  <input type="number" class="form-control" id="price1"
                     placeholder="" disabled>
               </td>
               <td style="width:12%">
                  <input type="number" class="form-control" id="discount1"
                     onchange="changeDiscount(this);"
                     placeholder="0">
                  <input type="hidden" id="discountAmount1" th:field="*{discount}">
               </td>
               <td style="width:12%">
                  <input type="number" class="form-control" id="total1"
                     th:field="*{discount}"
                     placeholder="" readonly>
               </td>
               <td>
                  <button type="button"
                     class="btn btn-block btn-danger btn-sm delete-row">
                  Delete
                  </button>
               </td>
               <div th:text="${invoicedto.medicineDTOList.add(medicinedto)}" th:remove="all"></div>
            </tr>
         </tbody>
      </table>
      </br>
      </br>
      </br>
      <div class="form-group row justify-content-end">
         <label class="col-sm-2 col-form-label" for="average_discount">
         Average Discount
         </label>
         <div class="col-sm-2">
            <input type="number" class="form-control" id="average_discount"
               th:field="*{averageDiscount}"
               onchange="changeAverageDiscount();">
         </div>
         <div class="col-sm-1">
         </div>
      </div>
      <div class="form-group row justify-content-end">
         <label class="col-sm-2 col-form-label justify-content-end" for="total_discount">
         Total Discount
         </label>
         <div class="col-sm-2">
            <input type="number" class="form-control" id="total_discount"
               th:field="*{totalDiscount}"
               readonly>
         </div>
         <div class="col-sm-1">
         </div>
      </div>
      <div class="form-group row justify-content-end">
         <label class="col-sm-2 col-form-label" for="vat">
         Vat
         </label>
         <div class="col-sm-2">
            <input type="number" class="form-control" id="vat" disabled>
         </div>
         <div class="col-sm-1">
            <input type="checkbox" id="vat_checkbox" name="vat_checkbox">
         </div>
      </div>
      <div class="form-group row justify-content-end">
         <label class="col-sm-2 col-form-label" for="tax">
         Tax
         </label>
         <div class="col-sm-2">
            <input type="number" class="form-control" id="tax" disabled>
         </div>
         <div class="col-sm-1">
            <input type="checkbox" id="tax_checkbox" name="tax_checkbox">
         </div>
      </div>
      <div class="form-group row justify-content-end">
         <label class="col-sm-2 col-form-label" for="total_tax">
         Total Tax
         </label>
         <div class="col-sm-2">
            <input type="number" class="form-control" id="total_tax" disabled>
         </div>
         <div class="col-sm-1">
         </div>
      </div>
      <div class="form-group row justify-content-end">
         <label class="col-sm-2 col-form-label" for="grand_total">
         Grand Total
         </label>
         <div class="col-sm-2">
            <input type="number" class="form-control" id="grand_total"
               th:field="*{grandTotal}"
               readonly>
         </div>
         <div class="col-sm-1">
         </div>
      </div>
      <div class="form-group row justify-content-end">
         <label class="col-sm-2 col-form-label" for="paid_amount">
         Paid Amount
         </label>
         <div class="col-sm-2">
            <input type="number" class="form-control" id="paid_amount"
               onchange="changePaidAmount();">
         </div>
         <div class="col-sm-1">
         </div>
      </div>
      <div class="form-group row justify-content-end">
         <label class="col-sm-2 col-form-label" for="change">
         Change
         </label>
         <div class="col-sm-2">
            <input type="number" class="form-control" id="change" disabled>
         </div>
         <div class="col-sm-1">
         </div>
      </div>
   </div>
   <!-- /.card-body -->
   <div class="card-footer">
      <button type="submit" class="btn btn-primary">Submit</button>
   </div>
</form>

I am trying to add list value in thymeleaf frontend this way. I am passing two object from controller to html. And i am using <div th:text="${invoicedto.medicineDTOList.add(medicinedto)}" th:remove="all"></div> for adding medicindto object. But It passes null list to controller. Do you have any idea how i solve my problem? thanks in advance. enter image description here


Solution

  • Thymeleaf is used to process HTML templates, add data to it, do some checks such as th:if, th:unless and also loops through an array of objects using th:each etc. But all of this is done on the server side. Once the HTML template has been delivered to the client (the browser in this case), thymeleaf is not applicable there.

    So on the client side, you have to rely on HTML and JavaScript to get everything done, including preparing your data to be submitted in the form.

    Based on the explanation above, you can do some more research on how to handle list on html forms. I found this solution to be appropriate for your use case, you can study it and use it.

    He has used Ratings[' + rating + '][Value] in his solution, you will use something like medicineDTOList[' + index + '][brandId]. Why medicineDTOList? because in InvoiceDto which is your form's th:object, the list of MedicineDto is called medicineDTOList.

    The [index] refers to the array index, which will correspond to the position of the MedicineDto in your arraylist and [brandId] correspond to the property of the MedicineDto at that index.

    Upon submitting the form, java will parse the form's data into your "DTO" which is InvoiceDTO.