Thymeleaf:如何动态获取 <input> 的值,然后使用它来过滤列表?

Thymeleaf: How to get the value of an <input> dynamically and then use it to filter a list?

我有一个 clientlist.html 页面,其定义如下:

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Clienti</title>
        <link rel="stylesheet" href="/webjars/bootstrap/4.5.0/css/bootstrap.min.css" />
    </head>
    <body>
        <a class="button" th:href="@{/clients/form}">Adauga un client nou</a>
        <label th:for="txtFilter">Nume</label>
        <input th:id="txtFilter" type="text" class="form-control form-control-sm" />
        <a th:href="@{/clients/getClientByLastName/{lastName}(lastName=${???})}">Cauta un client dupa nume</a>

        <div>
            <h2>Lista clienti</h2>
            <table>
                <thead>
                    <tr>
                        <th>ID</th>
                        <th>Prenume</th>
                        <th>Nume</th>
                    </tr>
                </thead>
                <tbody>
                    <tr th:each="client : ${clients}">
                        <td th:text="${client.getClientID()}"></td>
                        <td th:text="${client.getLastName()}"></td>
                        <td th:text="${client.getFirstName()}"></td>
                        <td><a th:href="@{/clients/form/{id}(id=${client.getClientID()})}">Editeaza</a></td>
                        <td><a th:href="@{/clients/delete/{id}(id=${client.getClientID()})}">Sterge</a></td>
                    </tr>
                </tbody>
            </table>
        </div>
    </body>
</html>

我有一个带有 th:href 的标签,它引用了我的 ClientController 中的方法,其定义如下:

import com.gestiunezboruri.demo.model.Client;
import com.gestiunezboruri.demo.service.ClientService;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.List;

@Slf4j
@Controller
public class ClientController {
    @Autowired
    ClientService clientService;

    Logger logger = LoggerFactory.getLogger(ClientController.class);

    @ModelAttribute("clients")
    public List<Client> populateClientList() {
        return clientService.findAll();
    }

    @RequestMapping("/clients/getAll")
    public String renderClientList() {
        return "clientlist";
    }

    @RequestMapping(value = "/clients/form")
    public String renderClientForm(Model model) {
        model.addAttribute("client", new Client());

        return "clientform";
    }

    @GetMapping("/clients/form/{id}")
    public String getClientById(@PathVariable Long id, Model model) {
        model.addAttribute("client", clientService.findById(id));

        return "clientform";
    }

    @GetMapping("/clients/getClientByLastName/{lastName}")
    public String getClientByLastName(@PathVariable String lastName, Model model) {
        model.addAttribute("clients", clientService.findByLastNameLike(lastName));
        for(Client c : clientService.findByLastNameLike(lastName)) {
            log.info(c.toString());
        }

        return "clientform";
    }

    //TODO: @GetMapping("clients/resetFilters")

    @PostMapping("/clients/save")
    public String saveClient(@Valid Client client, BindingResult bindingResult) {
        if (bindingResult.hasErrors()){
            return "clientform";
        }

        clientService.save(client);

        log.info("A fost adaugat clientul cu urmatoarele date: ID = " + client.getClientID() + "; Nume = " + client.getLastName() + "; Prenume = " + client.getFirstName());

        return "redirect:/clients/getAll";
    }

    @RequestMapping("/clients/delete/{id}")
    public String deleteClient(@PathVariable Long id) {
        Client clientSters = clientService.findById(id);

        clientService.deleteById(id);

        log.info("A fost sters clientul cu urmatoarele date: ID = " + clientSters.getClientID() + "; Nume = " + clientSters.getLastName() + "; Prenume = " + clientSters.getFirstName());

        return "redirect:/clients/getAll";
    }
}

在 table 标记中定义了数据库中所有客户端的列表。

然后是

<input th:id="txtFilter" type="text" class="form-control form-control-sm" />

用户应该使用此输入按他输入的值过滤列表。

我的问题是,如何将 txtFilter 输入的值作为 PathVariable 传递给 <a th:href="@{/clients/getClientByLastName/{lastName}(lastName=${???})}">? (即在 (lastName=${???}) 部分)

到目前为止我尝试的是通过 JavaScript 获取输入值,如下所示:

  var btnFilterList = document.getElementById("btnFilterList");
  var txtFilter = document.getElementById("txtFilter");
  console.log(txtFilter.getAttribute("value"));
        
  btnFilterList.setAttribute("href", "@{/clients/getClientByLastName/{lastName}(lastName=${" + txtFilter.value + "})}")

还有:

  var btnFilterList = document.getElementById("btnFilterList");
  var txtFilter = document.getElementById("txtFilter");
  console.log(txtFilter.getAttribute("value"));
        
  btnFilterList.setAttribute("th:href", "@{/clients/getClientByLastName/{lastName}(lastName=${" + txtFilter.value + "})}")

但是 none 似乎有效。

你想做的事情没有多大意义。 Thymeleaf 是一个服务器端渲染模板引擎。它采用您的模板,使用模型填充变量并输出发送到浏览器的静态 HTML。一旦进入浏览器,Thymeleaf 就不再“活跃”。因此,如果您想更改内容,您所能做的就是使用 JavaScript,或者对控制器方法执行新的 HTTP 请求。

因此,如果您不想进入 JavaScript,请将标签替换为位于表单内的按钮:

<form th:action="@{/clients/searchByLastName}" method="post" th:object="${searchFormData}">
  <input type="text" th:value="${searchText}">
  <button type="submit">Search</button>
</form>

在您的控制器中,您可以执行以下操作:

@PostMapping("/clients/searchByLastName")
public String searchByLastName(ModelAttribute("searchFormData") SearchFormData formData, Model model) {
  String text = formData.getSearchText();
  // Use text to search
  ...

  // Fill in the found clients into the Model
  ...

  //return the template you want to use here
  return "...";
}

使用此对象在表单和控制器之间传输 searchText:

public class SearchFormData {
  private String searchText;

  // getter and setter here
}

如果你确实想使用 JavaScript,那么你不应该在那里使用任何与 Thymeleaf 相关的东西,那是行不通的。