Skip to content
Advertisement

How to set a object’s field using another objects field in thymeleaf

I’m trying to set boxes’ elements copied from medicineBox’s values like below. Can anyone help me in this. I need to post medicineOrder model to the controller

            <tr th:each="medicineBox : ${medicine.medicineBoxes}">
                <td class="text-center">
                    <input type="text" th:field="*{boxes[__${medicineBoxStat.index}__].boxNumber}" th:value="${medicineBox.box.number}" />
                </td>
                <td class="text-center" th:text="${medicineBox.medicineCount}"></td>
                <td><input type="number" th:field="*{boxes[__${medicineBoxStat.index}__].medicineCount}" class="form-control" /></td>
            </tr>

I’m using two object here –

  1. medicine and medicineOrder

——————> Controller method to get the page

    @GetMapping("/{medicineId}")
    public String loadMedicineDetailPage(@PathVariable("medicineId") long medicineId, Model model) {
        model.addAttribute("medicine", service.getMedicineById(medicineId));
        model.addAttribute("medicineOrder", new MedicineOrder());
        return WebPages.MEDICINE_DETAIL.toString();
    }

——————> thymeleaf html page

<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="ISO-8859-1"/>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
    <title>Spring Boot Application</title>
</head>
<body>
<div class="container">
    <br/>
    <a class="btn btn-primary" th:href="@{/mvc/medicine/list}">Back</a>
    <br/>
    <br/>
    <h3 class="text-center alert alert-success">Medicine Details</h3>
    <form class="row g-3" action="#" th:action="@{/mvc/medicine/sell}" method="post" th:object="${medicineOrder}">
        <div class="col-md-6 col-xs-12 col-sm-12">
            <label for="name" class="form-label">Name</label>
            <input type="text" style="background-color:#95edea" disabled class="form-control" id="name" th:field="${medicine.name}"/>
        </div>
        <div class="col-md-6 col-xs-12 col-sm-12">
            <label for="company" class="form-label">Company</label>
            <input type="text" disabled class="form-control" id="company" th:field="${medicine.companyStringName}"/>
        </div>
        <div class="col-md-6 col-xs-12 col-sm-12">
            <label for="price" class="form-label">Price</label>
            <input type="text" disabled class="form-control" id="price" th:field="${medicine.price}"/>
        </div>
        <!--<div class="col-md-6 col-xs-12 col-sm-12">
            <label for="count" class="form-label">Count</label>
            <input type="text" class="form-control" id="count" th:field="${medicine.count}"/>
        </div>-->
        <div class="col-md-6 col-xs-12 col-sm-12">
            <label for="volume" class="form-label">ML</label>
            <input type="text" disabled class="form-control" id="volume" th:field="${medicine.volume}"/>
        </div>

        <div class="col-md-6 col-xs-12 col-sm-12">
            <label for="purchaseDate" class="form-label">Date Purchased</label>
            <input type="text" disabled class="form-control" id="purchaseDate" th:field="${medicine.purchaseDate}"/>
        </div>
        <!--<div class="col-md-6 col-xs-12 col-sm-12">
            <label for="boxNo" class="form-label">Box Number</label>
            <input type="text" class="form-control" id="boxNo" th:field="${medicine.boxNumber}"/>
        </div>-->
        **<input type="hidden" th:field="*{medicineId}" th:value="${medicine.medicineId}"/>**
        <table class="table table-bordered">
            <tr class="table-primary">
                <td>Box Number</td>
                <td>Medicine Count</td>
                <td>Sell Count</td>
            </tr>
            <tr th:each="medicineBox : ${medicine.medicineBoxes}">
                <td class="text-center">
                    **<input type="text" th:field="*{boxes[__${medicineBoxStat.index}__].boxNumber}" th:value="${medicineBox.box.number}"** />
                </td>
                <td class="text-center" th:text="${medicineBox.medicineCount}"></td>
                <td><input type="number" th:field="*{boxes[__${medicineBoxStat.index}__].medicineCount}" class="form-control" /></td>
            </tr>
        </table>
        <button class="btn btn-primary" type="submit">Sell</button>
    </form>
</div>
</body>
</html>

—————> Controller method to handle the post request

    @PostMapping("/sell")
    public String sellMedicine(@ModelAttribute MedicineOrder medicineOrder, BindingResult bindingResult) {
        if(bindingResult.hasErrors()){
            // error handling
        }
        service.sellMedicine(medicineOrder);
        return "redirect:/mvc/medicine/list";
    }

—————-> Class MedicineOrder

package com.example.demo.dto;

import com.example.demo.model.Box;

import java.util.ArrayList;
import java.util.List;

public class MedicineOrder {

    private long medicineId;
    private List<OrderedBox> boxes = new ArrayList<>();

    public long getMedicineId() {
        return medicineId;
    }

    public void setMedicineId(long medicineId) {
        this.medicineId = medicineId;
    }

    public List<OrderedBox> getBoxes() {
        return boxes;
    }

    public void setBoxes(List<OrderedBox> boxes) {
        this.boxes = boxes;
    }

    @Override
    public String toString() {
        return "MedicineOrder{" +
                "medicineId=" + medicineId +
                ", boxes=" + boxes +
                '}';
    }
}

package com.example.demo.dto;

public class OrderedBox {

    private String boxNumber;
    private int medicineCount;

    public String getBoxNumber() {
        return boxNumber;
    }

    public void setBoxNumber(String boxNumber) {
        this.boxNumber = boxNumber;
    }

    public int getMedicineCount() {
        return medicineCount;
    }

    public void setMedicineCount(int medicineCount) {
        this.medicineCount = medicineCount;
    }

    @Override
    public String toString() {
        return "OrderedBox{" +
                "boxNumber='" + boxNumber + ''' +
                ", medicineCount=" + medicineCount +
                '}';
    }
}

Not able to get the MedicineOrder.medicineId and medicineBorder.boxes[*].boxNumber from template to model object.

Advertisement

Answer

After lot of searching I didn’t find any answer which is solving the issue only using thymeleaf. To solve this issue I had to add two hidden input field for medicineId and boxNumber on medicineOrder object and populate those input field using javascript as below. Anyway if anyone find the solution by only using thymeleaf, please let me know.

Populated those fields using javascript

<script>
    function function__02__number__assignment(_element){
        var __element = _element.children[0];
        var __tElement1 = __element.children[0];
        var __tElement2 = __element.children[1];
        // Copy value from 2 to 1
        __tElement1.value = __tElement2.value;
    }
    function function__01__box_traverse(){
        var rootElement = document.getElementsByClassName('box-stock-details');
        for(var __i=0 ; __i < rootElement.length ; __i++) {
            function__02__number__assignment(rootElement[__i]);
        }
        function_01_01_medicineId();
        return true;
    }
    function function_01_01_medicineId(){
        var _00_1_id_src = document.getElementById('00-1-id-src');
        var _00_1_id_dest = document.getElementById('00-1-id-dest');
        _00_1_id_dest.value = _00_1_id_src.value;
    }
</script>

updated template file

<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="ISO-8859-1"/>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
    <title>Spring Boot Application</title>
</head>
<body>
<div class="container">
    <br/>
    <a class="btn btn-primary" th:href="@{/mvc/medicine/list}">Back</a>
    <br/>
    <br/>
    <h3 class="text-center alert alert-success">Medicine Details</h3>
    <form class="row g-3" action="#" th:action="@{/mvc/medicine/sell}" method="post" th:object="${medicineOrder}">
        <div class="col-md-6 col-xs-12 col-sm-12">
            <label for="name" class="form-label">Name</label>
            <input type="text" style="background-color:#95edea" disabled class="form-control" id="name" th:field="${medicine.name}"/>
        </div>
        <div class="col-md-6 col-xs-12 col-sm-12">
            <label for="company" class="form-label">Company</label>
            <input type="text" disabled class="form-control" id="company" th:field="${medicine.companyStringName}"/>
        </div>
        <div class="col-md-6 col-xs-12 col-sm-12">
            <label for="price" class="form-label">Price</label>
            <input type="text" disabled class="form-control" id="price" th:field="${medicine.price}"/>
        </div>
        <!--<div class="col-md-6 col-xs-12 col-sm-12">
            <label for="count" class="form-label">Count</label>
            <input type="text" class="form-control" id="count" th:field="${medicine.count}"/>
        </div>-->
        <div class="col-md-6 col-xs-12 col-sm-12">
            <label for="volume" class="form-label">ML</label>
            <input type="text" disabled class="form-control" id="volume" th:field="${medicine.volume}"/>
        </div>

        <div class="col-md-6 col-xs-12 col-sm-12">
            <label for="purchaseDate" class="form-label">Date Purchased</label>
            <input type="text" disabled class="form-control" id="purchaseDate" th:field="${medicine.purchaseDate}"/>
        </div>
        <!--<div class="col-md-6 col-xs-12 col-sm-12">
            <label for="boxNo" class="form-label">Box Number</label>
            <input type="text" class="form-control" id="boxNo" th:field="${medicine.boxNumber}"/>
        </div>-->
        <!-- Hidden input to get the value of medicineId from Medicine object -->
        <input id="00-1-id-src" type="hidden" th:value="${medicine.medicineId}"/>
        <!-- Hidden input to set the medicineId on MedicineOrder object  -->
        <input id="00-1-id-dest" type="hidden" th:field="*{medicineId}" />
        <table class="table table-bordered">
            <tr class="table-primary">
                <td>Box Number</td>
                <td>Medicine Count</td>
                <td>Sell Count</td>
            </tr>
            <tr class="box-stock-details" th:each="medicineBox : ${medicine.medicineBoxes}">
                <td class="text-center">
                    <input hidden th:field="*{boxes[__${medicineBoxStat.index}__].boxNumber}" />
                    <input disabled class="form-control" type="text" th:value="${medicineBox.box.number}" />
                </td>
                <td class="text-center" th:text="${medicineBox.medicineCount}"></td>
                <td><input type="number" th:field="*{boxes[__${medicineBoxStat.index}__].medicineCount}" class="form-control" /></td>
            </tr>
        </table>
        <button class="btn btn-primary" type="submit" onclick="return function__01__box_traverse()">Sell</button>
    </form>
</div>
</body>
<script>
    function function__02__number__assignment(_element){
        var __element = _element.children[0];
        var __tElement1 = __element.children[0];
        var __tElement2 = __element.children[1];
        // Copy value from 2 to 1
        __tElement1.value = __tElement2.value;
    }
    function function__01__box_traverse(){
        var rootElement = document.getElementsByClassName('box-stock-details');
        for(var __i=0 ; __i < rootElement.length ; __i++) {
            function__02__number__assignment(rootElement[__i]);
        }
        function_01_01_medicineId();
        return true;
    }
    function function_01_01_medicineId(){
        var _00_1_id_src = document.getElementById('00-1-id-src');
        var _00_1_id_dest = document.getElementById('00-1-id-dest');
        _00_1_id_dest.value = _00_1_id_src.value;
    }
</script>
</html>
Advertisement