Create a fragment for a select multiple element in thymeleaf - java

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.)

Related

Transform WSDLtoJava in Spring boot and JSP

I have a JSP page and a Spring boot controller, in the jsp i have a form with a select and options when i choose the option i need to pass that value to a java code to transform WSDL to java classes. How can i do it?
<form id="form" action="genclasses" method="post">
<select name="WSDLcat" class="custom-select ml-2" id="inputGroupSelect04">
<%
ServiceClass[] services = (ServiceClass[]) request.getAttribute("services");
%>
<c:forEach items="${services}" var="service">
<option id="WSDL" value="${service.getWsdl()}">
${service.getNombre()}</option>
</c:forEach>
</select>
<input class="btn btn-outline-secondary align-right" id="genclases" type="submit" onclick="generarClases()" value="Generar Clases">
</form>
String[] params= {"-d","./src/main/resources/generatedFiles","HERE I NEED THE VALUE OF THE OPTION"};
WSDLToJava.main(params);
ZipUtil.pack(new File("./src/main/resources/generatedFiles"), new File("./src/main/resources/generated.zip"));
I cannot do it in java inserted in jsp becasuse i need to use different libraries and i do not know how to pass it to the controller or do it in the same page. Any help?

Accesssing model attribute in JPA doesn't work

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]}.

Passing value from controller to html in spring

Hello I have a simple web page where I have a button and a text near to button. I need to change text when button clicked and get the new text from code.
This is controller class from where I need to pass response:
#GetMapping("/stream")
public String openStream(Model model) {
String response = service.openStream();
model.addAttribute("stream", response);
return "mainpage";
}
And here my html page, the value from controller must be instead of question marks:
<div id="container">
<button class="button"
onclick="window.location.href = '/stream';">Stream</button>
<p align="center">?????</p>
</div>
Thanks in advance for your help.
Edit:
I tried ${stream}
but getting it as text not value, please see screenshot:
Edit 2:
I need pass String from the text area to doc variable in the controller. Please help.
HTML:
<div>
<textarea rows="10" cols="100" name="description"></textarea>
button class="button" onclick="window.location.href ='/send';">Send</button>
</div>
Controller:
#GetMapping("/send")
public String send(String doc) {
service.sendDoc(doc);
return "mainpage";
}
Change
<p align="center">?????</p>
To
<p align="center">${stream}</p> OR <p th:text="${stream}"></p>
How it is working?
You can access variables value by ${key}.
Example
model.addAttribute("key", value);
Get value by ${key} in HTML
In Thymeleaf, these model attributes (or context variables in
Thymeleaf jargon) can be accessed with the following syntax:
${attributeName}, where attributeName in our case is stream. This
is a Spring EL expression. In short, Spring EL (Spring Expression
Language) is a language that supports querying and manipulating an
object graph at runtime.
UPDATE
The th:field attribute can be used on input, select, or, textarea.
Replace <p align="center">?????</p> with
<input type="text" id="stream" name="stream" th:value="${stream}" />
OR
<input type="text" th:field="*{stream}" />`
OR
<input type="text" id="stream" name="stream" th:field="*{stream}" th:value="${stream}" />
Also try <p th:inline="text">[[${stream}]]</p>; <p data-th-text="${stream}" />
Thymeleaf Document Thymeleaf Document Inputs
UPDATE 2
Get value from Thymeleaf to Spring Boot
<form th:action="#{/send}" method="get">
<textarea th:name="doc" rows="10" cols="100" name="doc"></textarea>
<button type="submit">Send</button>
</form>
#GetMapping("/send")
public String send(#RequestParam(name="doc", required = false) String doc) {
//change required = false as per requirement
System.out.println("Doc: "+doc);
return "textarea-input";
}
Note: use "th:field" for Entity/Model
Thank you for your help. Below shown line helped:
<p th:inline="text">[[${stream}]]</p>
Try these : <p align="center">${stream}</p> or <p th:text="${stream}"></p>
This tag may be causing a problem :
<button class="button"
onclick="window.location.href = '/stream';">Stream</button>
Please check it by removing this.
So i solve it like that :
let said i want to pass int ValueIwantToPass=5
in my controller i put
#GetMapping("/tasks")
public String listTasks(Model model) {
model.addAttribute("value", ValueIwantToPass);
}
and in my HTML file it look
<h1>i wanted to pass [[${value}]]</h1>

How i can get tuple value (querydsl) since thymeleaf?

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>

Spring MVC 3 form binding

I have a simple HTML form:
<form id="marketplaceForm" enctype="multipart/form-data" method="post">
<select name="category">
<option selected ></option>
<option value="Sales">Sales</option>
<option value="Marketing" >Marketing</option>
</select>
<textarea type="text" id="marketplaceDesc" name="description" value="" class="creattbleArea"></textarea>
<input type="text" id="marketplaceName" name="templateName" >
<input type="file" id="marketplaceLogo" name="logo">
<input type="submit" value="Save" id="update" />
<input type="text" id="marketplacePrice" name="price">
</form>
I need to auto bind this form when I submit it. This works fine:
#RequestMapping(value = "/.....", method = RequestMethod.POST)
public String PublishForm() {
But this throws the following error:
HTTP Status 400 -
The request sent by the client was syntactically incorrect
#RequestMapping(value = "/PublishApplication.htm", method = RequestMethod.POST)
public String PublishForm(#RequestParam("templateName") String templateName,
#RequestParam("category") String category,
#RequestParam("price") String price,
#RequestParam("description") String description
) {
Can any one help me?
Update: I have found that if I remove enctype="multipart/form-data" from the HTML form, it works. Now my question is how to make it work with enctype="multipart/form-data".
I think you may be missing the Multipart resolver from your configuration.
do you have something like this in your configuration?
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="250000"/>
</bean>
see here for the offical spring documentation on the matter.
First of all, make sure the binding to PublishApplication.htm really works. You are using this mapping in your controller, but you haven't specified it in action param of <form> tag. So you may end up with posting the form to some different controller, and server rejects your request. Of course this will not happen if you are using the same controller for both - displaying form and submiting it, and you have aplied RequestMapping annotation at class level.
There is another issue with your controller though. You are not specifying logo as #RequestParam in PublishForm method. I'm not sure if this is not messing up form autobinding. If I recall correctly, those params are required by default.

Categories