i don'i know how i get the tuple value of queryDSL since thymeleaf
since backEnd i send this value:
List<Tuple> products = productServiceImpl.findProductByFiltersPaginate(null, 0, 1, null);
ModelAndView view = new ModelAndView();
view.addObject("products",products);
view.setViewName(ViewConst.MAIN_LAYOUT);
view.addObject("view","catalog");
return view;
but in front (thymeleaf) i dont know how to get the values. my code is the below:
<div th:each="product :${products}">
<h2 th:text="${product}"></h2>
</div>
</div>
but i don't know what put after the name of the variable.
i already tried these ways:
${product.name}, ${product['name']}, ${product[0]}
but none of them works.
if i put only this ${product} it returns me in this format each value
[39, Moto KTM DUKE, /images/products/product39/m_39_0.jpg]
Based on what you replied with, I think these may work:
product.get(0, Product.class)
<!-- Note, you have to replace your.package.Product with the actual package -->
<div th:each="product :${products}" th:with="class=${T(your.package.Product).class}">
<h2 th:text="${product.get(0, class)}" />
</div>
product.get(qProduct.title)
<!-- For this, you need to add qProduct on the model -->
<div th:each="product :${products}">
<h2 th:text="${product.get(qProduct.title)}" />
</div>
You could also possibly use toArray() as well, though I'm not entirely sure how that would turn out:
<div th:each="product :${products}" th:with="data=${product.toArray()}">
<h2 th:text="${data[0]}" />
</div>
Related
I am having problems accessing a model attribute in my controller, using Spring.
When adding to the model, I write the status code as a key and the enumeration name as a value. The status code is e.g. AVAILABLE, NOTAVAILABLE, etc.:
String code = status.getCode();
String enumerationName = enumerationService.getEnumerationName(status, currentLocale);
model.addAttribute(code, enumerationName);
On my JPA page, I am trying to access the corresponding value using the key (status code, e.g. AVAILABLE):
<div data-availability>
<c:forEach items="${StockLevelDeliveryStatus.values()}" var="status">
<c:set var="textStyle" value="text-success" />
<c:if test="${status.code.toLowerCase() == 'notavailable'}">
<c:set var="textStyle" value="" />
</c:if>
<div class="d-none display-22 pb-2 ${textStyle}" data-availability-item data-${status.code.toLowerCase()}>
${status}
</div>
</c:forEach>
</div>
For example, the value of status is AVAILABLE and this is what is output in ${status}. However, I want the value AVAILABLE to be used as a key to return me the correct value that I set in the model above. If I change the ${status} statement to, say, ${AVAILABLE} instead, which is the concrete key, the appropriate value from the model is returned:
<div class="d-none display-22 pb-2 ${textStyle}" data-availability-item data-${status.code.toLowerCase()}>
${AVAILABLE}
</div>
If I understand it correctly, then instead of passing the enum value as a key, I need to somehow teach Spring to search in the model for the appropriate key.
As recommended in one of the replies, I also tried writing the Map<StockLevelDeliveryStatus, String> directly into the model:
Map<StockLevelDeliveryStatus, String> statusMap = new HashMap<StockLevelDeliveryStatus, String>();
for (StockLevelDeliveryStatus status : StockLevelDeliveryStatus.values()) {
statusMap.put(status, enumerationService.getEnumerationName(status, currentLocale));
}
model.addAttribute("statusMap", statusMap);
And the JSP accordingly:
<div data-availability>
<c:forEach items="${StockLevelDeliveryStatus.values()}" var="status">
<c:set var="textStyle" value="text-success" />
<c:if test="${status.code.toLowerCase() == 'notavailable'}">
<c:set var="textStyle" value="" />
</c:if>
<div class="d-none display-22 pb-2 ${textStyle}" data-availability-item data-${status.code.toLowerCase()}>
${statusMap[status]}
</div>
</c:forEach>
</div>
Here it already fails when accessing the model, because with this approach I do not get any output on the JSP.
Does anyone have any ideas on how to make this work?
Why not simply put a Map<StockLevelDeliveryStatus, String> into the model? You could then simply use ${statusMap[status]}.
I'm trying to create a fragment for the multiselect field in my webapp. But I'm running into various issues with regards to passing in the field that should be bound to the select element. I figure I have a syntax error, but I'm not sure what it is.
For selectedField in my addUser.jsp file, I've tried ${selectedAdminAccess}, *{selectedAdminAccess}, ${userForm.selectedAdminAccess}, etc.
And with those various combinations, in the forms.html file, I've tried ${selectField}, *{selectField}, and the preprocessor directive: ${__${selectField}__}. Have I just missed the correct combination?
The error I'm getting is "Neither BindingResult nor plain target object for bean name 'X' available as request attribute". Where X is (for the preprocessor attempt) the fieldname entered in the addUser.jsp page, or "selectField" when not using the preprocessor attempt.
Here's what I've got.
Controller
#GetMapping(value={"/adduser"}
public ModelAndView getAddUserPage(Model model, #RequstParam(required = false) Long selectedUserId) {
ModelAndView mav = new ModelAndView("/addUser");
UserForm userForm = new UserForm();
mav.addObject("userForm", userForm);
return mav;
}
model UserForm
public class UserForm {
private List<Office> adminAccess = new ArrayList<>();
private List<String> selectedAdminAccess = new ArrayList<>();
// Getter/Setter
...
}
addUser.jsp
<form method="post" action="#" data-th-action="#{/addUser}" data-th-object="${userForm}">
<!-- other interesting page stuff -->
<div data-th-replace="fragments/forms.html :: multi-select(
id='adminSelect',
selectClass='office-target',
selectField='*{selectedAdminAccess}',
optionList='*{adminAccess}',
optionListValue='id',
optionListText='name',
size=8)"></div>
</form>
forms.html
<div data-th-fragment="multi-select(id, selectClass, selectField, optionList, optionListValue, optionListText, size)" >
<select id="${id}" class="mdb-select colorful-select md-form ${selectClass}" size="${size}" multiple
searchable data-th-field="${__${selectField}__}">
<option data-th-each="option : ${adminAccess}"
data-th-value="${option.__${optionListValue}__}"
data-th-text="${option.__${optionListText}__}"></option>
</select>
</div>
The ultimate goal here is to have an expression data-th-field="*{selectedAdminAccess}" To accomplish this:
For selectField, you need to pass a string with value 'selectedAdminAccess'.
For th:field, use the preprocessing expression *{__${selectField}__}.
The HTML you provided looks like it has other problems... but I think your final HTML will look something like this:
<!-- page -->
<form method="post" action="#" data-th-action="#{/addUser}" data-th-object="${userForm}">
<!-- other interesting page stuff -->
<div data-th-replace="fragments/forms.html :: multi-select(
id='adminSelect',
selectClass='office-target',
selectField='selectedAdminAccess',
optionList=*{adminAccess},
optionListValue='id',
optionListText='name',
size=8
)" />
</form>
<!-- fragment -->
<div data-th-fragment="multi-select(id, selectClass, selectField, optionList, optionListValue, optionListText, size)" >
<select data-th-id="${id}"
data-th-class="|mdb-select colorful-select md-form ${selectClass}|"
data-th-size="${size}"
multiple
searchable
data-th-field="*{__${selectField}__}">
<option data-th-each="option : ${optionList}"
data-th-value="${option.optionListValue}"
data-th-text="${option.optionListText}" />
</select>
</div>
Using Metroids' answer above, here is the final solution that worked for me:
<!-- page -->
<form method="post" action="#" data-th-action="#{/addUser}" data-th-object="${userForm}">
<!-- other interesting page stuff -->
<div data-th-replace="fragments/forms.html :: multi-select(
id='adminSelect',
selectClass='office-target',
selectField='selectedAdminAccess',
optionList='adminAccess',
optionListValue='id',
optionListText='name',
size=8
)"></div>
</form>
<!-- fragment -->
<div data-th-fragment="multi-select(id, selectClass, selectField, optionList, optionListValue, optionListText, size)" >
<select data-th-id="${id}"
data-th-class="|mdb-select colorful-select md-form ${selectClass}|"
data-th-size="${size}"
multiple
searchable
data-th-field="*{__${selectField}__}">
<option data-th-each="option : ${__${optionList}__}"
data-th-value="${option.__${optionListValue}__}"
data-th-text="${option.__${optionListText}__}" />
</select>
</div>
The reason for the value and text to be the way they are is to allow a more dynamic object to be passed in. The text could be a name, description, or whatever. The value could be an id, or the text value, or whatever. That style I learned from https://www.northcoder.com/2019/11/thymeleaf-look-at-two-of-its-most.html and their github project linked on the page.
Crazy thing is, now that I see the answer, it was staring me in the face the whole time (it's how the value and text are being used.)
I'm looking for a way to include the structure of a thymeleaf fragment into a page.
What i mean by that is as follows:
The fragmend defined as follows:
<div class="container" th:fragment="container">
<div class="row">
{the content of the page continues here}
</div>
</div>
The page template:
<div th:replace="fragments/main:: container">
{I can continue here for eq, <div class="col-md-5"></div>}
</div>
I dont't know if this is possible but i'm looking for a way to do this.
Due to layout dialect of Thymeleaf, this can be done by adding
<th:block layout:fragment="content"/> to desired layout and using this as parent element in your view.
I want to insert an Attribute into the html Code.
I tried this, but it's not working:
<div id="${var}"> ... </div>
I think you know what I mean. The attribute 'var' should be the id. I didn't find a solution...
You just need to use the th:attr attribute. It is explained in the reference documentation 5.1:
5.1 Setting the value of any attribute
Enter then the th:attr attribute, and its ability to change the value
of attributes of the tags it is set in:
<form action="subscribe.html" th:attr="action=#{/subscribe}">
<fieldset>
<input type="text" name="email" />
<input type="submit" value="Subscribe!" th:attr="value=#{subscribe.submit}"/>
</fieldset>
</form>
The
concept is quite straightforward: th:attr simply takes an expression
that assigns a value to an attribute. Having created the corresponding
controller and messages files, the result of processing this file will
be:
<form action="/gtvg/subscribe">
<fieldset>
<input type="text" name="email" />
<input type="submit" value="¡Suscríbe!"/>
</fieldset>
</form>
Use this
<div th:attr="id=${var}"> ... </div>
Thymeleaf only evaluates attributes that are prefixed with th:. Here is a list of the attributes that are evaluated:
http://www.thymeleaf.org/doc/tutorials/2.1/usingthymeleaf.html#setting-value-to-specific-attributes
In your case, th:id is already built in so you can simply do <div th:id="${var}"> ... </div> and it will work. th:attr, is used to define attributes that thymeleaf doesn't normally support.
I'm trying to use thymeleaf to generate edit and delete modals for each element in the model in my ModelAndView using th:each.
The modals are indeed created and have unique ids based on the id field of the elements. The problem I have is none of the values from elements are parsed into the inputs to enable the user to see the current values.
They are obviously there because the view also has a table which displays each element's values along with the anchors which toggle the modals.
Here's some example code of how I'm doing it:
<div th:each="f : ${foos}" th:id="um- + ${f.id}" class="modal fade"
tabindex="-1" role="dialog">
...
<form role="form" th:action="#{/foo/update}" th:object="${foo}" th:method="post">
<input type="hidden" th:field="*{id}" th:value="${f.id}"/>
<fieldset class="form-group">
<label for="bar">Bar</label>
<input th:field="*{bar}" th:value="${f.bar}" class="form-control"
id="bar" type="text" placeholder="Bar"/>
</fieldset>
...
</form>
...
</div>
How to generate edit modals for each element in the model? I'm not sure why thymeleaf is unable to get the values of the fields from the model elements.
That's not a great approach actually. In addition to it not working, doing using a loop obviously creates n modals for the collection.
The solution that worked best was to provide a single modal that would be populated and submitted with Ajax calls.
This no-frills Spring Boot app has all the relavant code.