【问题标题】:How can I do calculation based on other fields in thymeleaf?如何根据 thymeleaf 中的其他字段进行计算?
【发布时间】:2017-10-04 04:03:16
【问题描述】:

我正在使用 Spring boot、Spring-data、ThymeLeaf。我有一些领域。 "Passenger Name", "Age", "Source", "Destination", "No of tickets", "Ticket Price", "Discount"

以下html代码:

<div class="form-group has-error has-feedback" data-z="1b5278b0" id="passengerName1" data-th-classappend="${#fields.hasErrors('passengerName')}? 'has-error has-feedback'" data-th-class="form-group">
    <label for="passengerName" class="col-md-3 control-label" data-th-text="#{label_ticketbooking_passengerName}">passengerName</label>
    <div class="col-md-3">
        <input id="passengerName" name="passengerName" data-th-value="*{{passengerName}}" type="text" class="form-control inputmask" placeholder="passengerName" data-th-placeholder="#{label_ticketbooking_passengerName}" data-toggle="tooltip" />
    </div>
</div>
<div class="form-group has-error has-feedback" data-z="1b5278b0" id="age-field" data-th-classappend="${#fields.hasErrors('age')}? 'has-error has-feedback'" data-th-class="form-group">
    <label for="age" class="col-md-3 control-label" data-th-text="#{label_ticketbooking_age}">age</label>
    <div class="col-md-3">
        <input id="age" name="age" data-th-value="*{{age}}" type="text" class="form-control inputmask" placeholder="age" data-th-placeholder="#{label_ticketbooking_age}" data-toggle="tooltip" data-inputmask-alias="numeric" data-inputmask-digits="0" min="1" />
    </div>
</div>
<div class="form-group has-error has-feedback" data-z="1b5278b0" id="source1" data-th-classappend="${#fields.hasErrors('source')}? 'has-error has-feedback'" data-th-class="form-group">
    <label for="source" class="col-md-3 control-label" data-th-text="#{label_ticketbooking_source}">source</label>
    <div class="col-md-3">
        <input id="source" name="source" data-th-value="*{{source}}" type="text" class="form-control inputmask" placeholder="source" data-th-placeholder="#{label_ticketbooking_source}" data-toggle="tooltip"  />
    </div>
</div>
<div class="form-group has-error has-feedback" data-z="1b5278b0" id="destination1" data-th-classappend="${#fields.hasErrors('destination')}? 'has-error has-feedback'" data-th-class="form-group">
    <label for="destination" class="col-md-3 control-label" data-th-text="#{label_ticketbooking_destination}">destination</label>
    <div class="col-md-3">
        <input id="destination" name="destination" data-th-value="*{{destination}}" type="text" class="form-control inputmask" placeholder="destination" data-th-placeholder="#{label_ticketbooking_destination}"  />
    </div>
</div>
<div class="form-group has-error has-feedback" data-z="1b5278b0" id="noOfTickets-field" data-th-classappend="${#fields.hasErrors('noOfTickets')}? 'has-error has-feedback'" data-th-class="form-group">
    <label for="noOfTickets" class="col-md-3 control-label" data-th-text="#{label_ticketbooking_noOfTickets}">noOfTickets</label>
    <div class="col-md-3">
        <input id="noOfTickets" name="noOfTickets" data-th-value="*{{noOfTickets}}" type="text" class="form-control inputmask" placeholder="noOfTickets" data-th-placeholder="#{label_ticketbooking_noOfTickets}" data-toggle="tooltip" aria-describedby="noOfTicketsStatus" data-inputmask-alias="numeric" data-inputmask-digits="0" min="1" />
    </div>
</div>
<div class="form-group has-error has-feedback" data-z="ed99c550" id="ticketPrice-field" data-th-classappend="${#fields.hasErrors('ticketPrice')}? 'has-error has-feedback'" data-th-class="form-group">
    <label for="ticketPrice" class="col-md-3 control-label" data-th-text="#{label_ticketbooking_ticketPrice}">ticketPrice</label>
    <div class="col-md-3">
        <input id="ticketPrice" name="ticketPrice" data-th-value="*{{ticketPrice}}" type="text" class="form-control inputmask" placeholder="ticketPrice" data-th-placeholder="#{label_ticketbooking_ticketPrice}" data-toggle="tooltip" />
    </div>
</div>
<div class="form-group has-error has-feedback" data-z="d1a1d590" id="ticketdiscount-field" data-th-classappend="${#fields.hasErrors('ticketDiscount')}? 'has-error has-feedback'" data-th-class="form-group">
    <label for="ticketDiscount" class="col-md-3 control-label" data-th-text="#{label_ticketbooking_ticketdiscount}">ticketDiscount</label>
    <div class="col-md-3">
        <input id="ticketDiscount" name="ticketDiscount" data-th-value="*{{ticketDiscount}}" type="text" class="form-control inputmask" placeholder="ticketDiscount" data-th-placeholder="#{label_ticketbooking_ticketdiscount}" data-toggle="tooltip" data-inputmask-alias="numeric" data-inputmask-digits="0" />
    </div>
</div>
<div class="form-group has-error has-feedback" data-z="ed99c550" id="totalPrice-field" data-th-classappend="${#fields.hasErrors('totalPrice')}? 'has-error has-feedback'" data-th-class="form-group">
    <label for="totalPrice" class="col-md-3 control-label" data-th-text="#{label_ticketbooking_totalPrice}">totalPrice</label>
    <div class="col-md-3">
        <input id="totalPrice" name="totalPrice" data-th-value="*{{totalPrice}}" type="text" class="form-control inputmask" placeholder="totalPrice" data-th-placeholder="#{label_ticketbooking_totalPrice}" data-toggle="tooltip" />
    </div>
</div>

这里totalPrice应该是根据totalPrice = (noOfTickets * ticketPrice ) - ticketDiscount计算的

注意:ticketDiscount 可能适用或不适用。如果适用需要减去,否则不需要减去。

我怎样才能做到这一点?

【问题讨论】:

  • 向模型对象getTotalPrice()添加一个方法:该方法具有计算值的数据,以便它属于它。

标签: spring spring-boot spring-data thymeleaf


【解决方案1】:

试试这个计算:

<div th: "${ticketDiscount !=null} ? result=${noOfTickets * totalPrice - ticketDiscount } : result=${noOfTickets * totalPrice}">
  <span th:text="${result}"></span>
</div>

这里我正在检查ticketdiscount的值是否为空。

【讨论】:

  • 获取异常:org.thymeleaf.exceptions.TemplateProcessingException:无法解析为表达式:“${ticketDiscount !=null} ? result=${noOfTickets * totalPrice - ticketDiscount } : result=${noOfTickets * totalPrice}”(模板:“ticketbookings/create” - 第 71 行,第 10 列)
  • 试过这个:
【解决方案2】:

在 Spring 中,您可以使用 service.Example 代码来做到这一点:

服务类:

@Component("calculateService")
public class CalculateService {

public Integer calculateTotalPrice(Integer noOfTickets ,Integer ticketPrice, Integer ticketDiscount ){

   return (noOfTickets * ticketPrice ) - ticketDiscount;

} 

}

HTML 文件:

<span th:text="${@calculateService.calculateTotalPrice(noOfTickets ,ticketPrice ,ticketDiscount)}"></span> 

【讨论】:

  • 获取异常:org.thymeleaf.exceptions.TemplateProcessingException:评估 SpringEL 表达式的异常:“@calculateService.calculateTotalPrice(*{noOfTickets },*{ticketPrice },*{ticketDiscount})”(模板:“票务预订/创建” - 第 74 行,第 8 列)
  • 试过这个:
  • 尝试了更新的答案,但我在 calculateService 中得到的所有值都为空
  • 您应该在控制器中添加模型属性的参数(noOfTickets ,ticketPrice ,ticketDiscount)。
【解决方案3】:

您应该考虑几件事情以及可以使用的几种方法。让我们稍微简化一下,假设你有

表单 DTO

@Data
public class TestDto {
    private int ticketPrice;
    private int noOfTickets;
    private int ticketDiscount;
}

和控制器

@Controller
public class TestController {

    @RequestMapping(name = "/", method = RequestMethod.GET)
    public ModelAndView get()  {
        TestDto dto = new TestDto();
        dto.setNoOfTickets(10);
        dto.setTicketPrice(12);
        return new ModelAndView("main", "dto", dto);
    }

    @RequestMapping(name = "/", method = RequestMethod.POST)
    public String post(@ModelAttribute("dto") TestDto dto) {
        System.out.println(dto);// can process input values
        return "main";
    }
}

重要。我假设您的表单中有th:object="${dto}"。如果你不这样做,那么只需使用 dto.fieldName 而不是 fieldName 就像 dto.ticketPrice 而不是 ticketPrice$ 而不是 *


选项 1. 使用 Thymeleaf 语法​​。 totalPrice 将在每次提交表单(POST 请求)后更改

<form action="/" th:object="${dto}" method="post">
    <input type="number" th:id="ticketPrice" th:field="*{ticketPrice}"/>
    <input type="number" th:id="noOfTickets" th:field="*{noOfTickets}"/>
    <input type="number" th:id="ticketDiscount" th:field="*{ticketDiscount}"/>

    <span th:text="*{noOfTickets * ticketPrice - (ticketDiscount != 0 ? ticketDiscount: 0)}"
      th:id="totalPrice"/>

    <input type="submit" value="Subscribe!"/>
</form>

选项 2. 在 java 代码中计算值 还需要对服务器进行 POST 更改以更新总值。简单案例可以只使用方法与 DTO 中的所有计算。仅当您在此 DTO 中拥有所有计算信息时,此选项才有效

public class TestDto {
    // ... same code as before
    public int getTotalPrice() {
        return noOfTickets * ticketPrice - (ticketDiscount != 0 ? ticketDiscount: 0);
    }
}

这很容易使用,就像您的 dto 中的任何其他字段一样

<span th:text="*{totalPrice}"></span>
<span th:text="${dto.totalPrice}"></span>
<span th:text="*{getTotalPrice()}"></span>

如果您需要一些额外信息来进行计算,您可能可以使用@mrtasln 建议的服务。对于我们的简单案例,它可能如下所示:

@Service("myService")
public class MyServices {

    // Option 1
    public int calculateTotal(MyDto dto){
        return dto.getNoOfTickets() * dto.getTicketPrice() - (dto.getTicketDiscount() != 0 ? dto.getTicketDiscount(): 0);
    }
    // Option 2
    public int calculateTotal2(int noOfTickets, int ticketPrice, int ticketDiscount){
        return noOfTickets * ticketPrice - (ticketDiscount != 0 ? ticketDiscount: 0);
    }
}

xml 部分可以是以下之一:

<span th:id="totalPriceFromService" 
      th:text="${@myService.calculateTotal(dto)}"></span>

<span th:id="totalPriceFromService2" 
      th:text="*{@myService.calculateTotal2(ticketPrice, noOfTickets, ticketDiscount)}"></span>

<span th:id="totalPriceFromService2" 
      th:with="tp=*{ticketPrice},nt=*{noOfTickets},td=*{ticketDiscount}"
      th:text="${@myService.calculateTotal2(tp, nt, td)}"></span>

选项 3。Javascript 方式是计算变化的唯一动态选项。无需执行 POST 即可更新总值。 您可以使用一些库来帮助您,但应该使用简单的案例

  1. 定义一些 JavaScript 函数,例如 calculateTotal()
  2. oninput="calculateTotal()" 属性放在您要收听的每个输入字段中

类似这样的:

<form action="/" th:object="${dto}" method="post">
    <input type="number" th:id="ticketPrice" th:field="*{ticketPrice}" oninput="calculateTotal()"/>
    <input type="number" th:id="noOfTickets" th:field="*{noOfTickets}" oninput="calculateTotal()"/>
    <input type="number" th:id="ticketDiscount" th:field="*{ticketDiscount}" disabled="disabled"/>
    <span th:id="totalPriceJS"></span>
    <input type="submit" value="Subscribe!"/>
</form>

<script type="text/javascript">
    function calculateTotal() {
        var price = document.getElementById("ticketPrice").value;
        var quantity = document.getElementById("noOfTickets").value;
        var discount = document.getElementById("ticketDiscount").value;
        var totalInput = document.getElementById("totalPriceJS");

        //do all the calculations here
        var total = price * quantity
        if (discount) total -= discount;

        totalInput.innerHTML = total
    }
    calculateTotal(); // don't forget to call this function on the first run
</script>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多