Esta es una clase Java simple que tiene una lista de cadenas, por ejemplo:
public class Apple { private List<String> listOfStrings; // getters setters }html con hoja de tomillo:
<form method="post" th:object="${apple}"> // apple is set through Model.addAttribute(.., ..) in Controller <input type="text" th:each="str, iter : *{listOfStrings} th:field="*{listOfStrings[__${iter.index}__]}"> <button id="add" type="button" onclick="add()>Add</button> <button id="remove" type="button" onclick="remove()">Remove</button> <input type="submit" value="Save"> <form>javascript agregar y eliminar nueva entrada:
const newInputTextString="<input type=\"text\" th:field="?">" // th:field won't be evaluated/bound to apples listOfStrings index function add() { const xhttp = new XMLHttpRequest(); xhttp.onload = function() { document.getElementById("add").insertAdjacentHTML("beforebegin", newInputTextString); } xhttp.open("GET", window.location.href); xhttp.send(); } function remove() { // TODO }Hasta ahora, solo estoy agregando html a través de javascript, pero no puedo incluir th: etiquetas allí, ya que estas etiquetas no se evaluarán ni se vincularán a objetos o campos específicos.
Funcionalidad esperada:
En otras palabras, quiero que el usuario pueda eliminar y agregar cadenas en listOfStrings de ese objeto Apple con botones html.
Siéntete libre de corregir mi inglés.
th:field esencialmente solo le da una ID y un atributo NAME en un elemento. No puede agregar un campo th: a través de JS, pero puede emular su comportamiento agregando manualmente los atributos de ID y NOMBRE apropiados. Dicho esto, debe hacer algunos cambios leves en su código HTML y JS.
Siempre debe tener un registro del número total actual de cadenas para que pueda ajustar su índice de cadenas. Para eso, he creado un contenedor div alrededor de todas las entradas de cadena para que podamos acceder a él en JS. Luego, solo leemos la cantidad de elementos dentro de él y creamos un nuevo índice a partir de él.
Puede ver la implementación a continuación:
function createInput(index) { var input = document.createElement('input'); input.setAttribute('type', 'text'); input.setAttribute('id', `listOfStrings[${index}]`); input.setAttribute('name', `listOfStrings[${index}]`); input.setAttribute('placeholder', `listOfStrings[${index}]`); input.setAttribute('data-index', index); input.setAttribute('data-input', ''); return input; } function addString() { var inputsWrapper = document.querySelector('[data-inputs]'); var inputs = inputsWrapper.querySelectorAll('[data-input]'); var newIndex = inputs.length; var newInput = createInput(newIndex); inputsWrapper.append(newInput); } <form method="post" th:object="${apple}"> <div style="display: flex; flex-direction: column; max-width: 300px" data-inputs> <input type="text" placeholder="listOfStrings[0]" th:placeholder="${'listOfStrings[__${iter.index}__]'}" th:each="str, iter : *{listOfStrings}" th:attr="data-index=${__${iter.index}__}" th:field="*{listOfStrings[__${iter.index}__]}" data-input /> </div> <button id="add" type="button" onclick="addString()">Add</button> <button id="remove" type="button" onclick="remove()">Remove</button> <input type="submit" value="Save"> <form>