I need to send the data which is present in a list from my spring controller to thymeleaf (html) how can I send the data? after receiving how can I iterate the data in thymeleaf
Put your list inside your ModelMap or ModelAndView object then traverse it using th:each within your thymeleaf page.
From Java side:
modelMap.addAttribute("list", myListOfThings);
From Thymeleaf side:
<ul>
<li th:each="item : ${list}">
<span th:text="${item}">Default</span>
</li>
</ul>
Related
I have an html page to edit a list of persons.
When the page is opened the controller gets the list of persons from the db and binds to the view.
That works fine.
Then the user edits the data and clicks save.
Now I need to submit the edited data of each person to the controller so that the controller can save the edits.
I'm trying to do that using #ModelAttribute ArrayList<Person> as shown below but it's not working.
The arraylist comes empty.
How do I do for the arraylist to come filled with all of the persons objects from the form?
View
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<form action="editperson" method="post">
<th:block th:each="person : ${personBind}">
Name:
<input type="text" th:value="${person.name}" />
</br></br>
Age:
<input type="text" th:value="${person.age}" />
</br></br>
</th:block>
</br></br>
<input type="submit" name="btnSaveEdit" value="Save"/>
</form>
Controller
#RequestMapping(value = "/editperson", params = "btnSaveEdit", method = RequestMethod.POST)
public String saveEditPerson(#ModelAttribute ArrayList<Person> personsList){
//save edit code here
return "editperson";
}
Spring MVC with Thymeleaf does indeed use model attributes to store data for the Thymeleaf pages. This guide shows how to load data from a form into the application. Try wrapping the ArrayList inside of a custom object and access the list via that object as a ModelAttribute rather than working with an ArrayList directly.
The saveEditPerson method should probably be named "saveEditPersons" since you are parsing a list of persons rather than just one.
so here's my problem.
I'm trying to have dynamic data in my header. It's supposed to represent the number of items a user has in his cart.
So here's my header (the header is a fragment that I included in the layout.html) and the data is in the last li
<nav >
<ul>
<li><a th:href="#{/index}" class="">Home</a></li>
<li><a th:href="#{/products/list}" class="">Products</a></li>
<li><a th:href="#{/admin/index}" class="">Admin</a></li>
<li>Account</li>
<li>Contacts</li>
<li><a th:href="#{/login}" class="">Login</a></li>
<li><a th:href="#{/user-page}" class="">User</a></li>
<li>
<p th:text="${cart.id}"></p>
</li>
</ul>
</nav>
But since the header is available on every page of the web app, what should I do (in the controllers) to get this data?
I tried to put the cart data in the IndexController but it doesn't work. I'm not comfortable with Spring and Thymeleaf so I might be doing something wrong or maybe I missed something on data binding. I only have once constraint, I don't want to use Ajax or Jquery. Unless I have no choice but I doubt that. Here's what I tried in the IndexController
#GetMapping({"/", "/index", "/home"})
public String getIndex(Model model) {
this.userCart.setId(5);
this.userCart.setNumberItems(11);
model.addAttribute("cart", userCart);
model.addAttribute("phrase", "Oui oui si si 92izi");
model.addAttribute("nbItems", "10");
return "index";
}
I also tried to make another method mapped to "/" but it causes an error since I can't have to methods mapped to the same url. So what am I supposed to do ?
If you need a model attribute application wide, then you can use an #ControllerAdvice annotated class:
#ControllerAdvice
public class GlobalControllerAdvice {
#ModelAttribute("numberOfItemsInCart")
public int getNumberOfItemsInCart() {
// get the cart and return the number of items
}
}
And use this attribute in your template:
<p th:text="${numberOfItemsInCart}"></p>
The method that is annotated with #ModelAttribute can also declare HttpServletRequest request as a parameter if needed (See https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#mvc-ann-arguments for all possible arguments for the method).
See https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#mvc-ann-controller-advice for more details about #ControllerAdvice.
I am implementing Role based spring security
In this example they have used thymeleaf for frontend purpose, but I am using angular9 with html.
they are using sec:authorize="hasRole('ROLE_ADMIN')" to provide access to the admin,in the same way if I want to provide the same thing in html, for that I have used the following code,
<li *ngFor="let user of users">
{{user.username}} ({{user.firstName}} {{user.lastName}})
- <a sec:authorize="hasRole('ROLE_ADMIN')" (click)="deleteUser(user.userid)" class="text-danger">Delete</a>
</li>
The person logged in is Role_user, eventhough the delete link is visible to the user.
How can I restrict.
Thanks in advance.
use *ngIf directive to show and hide the anchor tag
<li *ngFor="let user of users">
{{user.username}} ({{user.firstName}} {{user.lastName}})
- <a *ngIf="hasRole('ROLE_ADMIN')" (click)="deleteUser(user.userid)" class="text-danger">Delete</a>
</li>
but the hasRole() must return boolean. because *ngIf accepts the boolean
I have a thymeleaf fragment called nav which I include in all front-end pages, it goes like so:
<nav class="navbar navbar-expand-md navbar-dark bg-dark" th:fragment="nav">
<div class="collapse navbar-collapse" id="navbarsExampleDefault">
<ul class="navbar-nav mr-auto">
<li class="nav-item active">
<a class="nav-link" href="#">Home <span class="sr-only">(current)</span></a>
</li>
How to get Java data here ?
</ul>
</div>
</nav>
But what I want to do now is get some data from the database and have that data available in this fragment, which in turn will appear on every page that includes this fragment.
If I want to pass data to a view regularly from a controller, I would use Model and model.addAttribute and return the appropriate view which would contain the relevant model data, but how can I pass data to this fragment?
You can create an interceptor and add model attribute on the postHandle method (which allows you access to the ModelAndView object. The interceptor will have to be on all the controllers that have this fragment.
You can add the relevant model attributes to the session and access them via ${session.attribute}.
Use the #ControllerAdvice annotation in combination with #ModelAttribute to add a model attribute to all controllers.
I am trying to code an HTML form that sends data to a RESTful web service (managed with Spring) using select HTML element.
The REST has to create an object Event on my database.
The problem I find is that the #RequestParam in the REST comes empty even if my options' values are present.
This is my HTML form.
<form name="editForm" role="form" novalidate ng-submit="vm.save()">
<!-- other fields that works correct -->
<div class="form-group">
<label class="control-label" data-translate="businessRequestApp.event.participantsAdd" for="field_attendees">Attendees</label>
<select style="height: 300px;" multiple class="form-control" id="field_attendees" ng-model="vm.event.usersOnIt" ng-options="customUser as customUser.username for customUser in vm.customusers | orderBy:'id' track by customUser.id">
<option value="{{customUser.username}}" name="attendeesToParse"></option>
</select>
</div>
</form>
This is my REST.
#PostMapping("/events")
#Timed
public ResponseEntity<Event> createEvent(#RequestBody Event event, #RequestParam(value="attendeesToParse") List<String> participants) throws URISyntaxException {
//Some code that creates an object "Event" on my database
}
I am trying to fill a field List of String. Due to my business logic I can't insert it into Event's class, so I have to threat it separately.
Note that #RequestBody works correctly, the issue is only with #RequestParam that does not receive anything.
Thanks in advice for your time.
Options elements are never sent. Select's value is sent. Try to move the name="attendeesToParse" to the select itself.
If you need multiple values create a hidden input and store selected options into the field. Use the hidden input name to get values in the controller.