pagination in spring boot whit a form parameter - spring-boot

I'm using spring boot and thymeleaf.
I have a page with a form that search by a specific param then submits the data as POST request.
The page shows the result in a table and works fine. The table shows the correct pagination options and result,
Problem: When I click the button to show results on page 2 o laters, then the POST data from the previous search is lost.
Question: How can I retain the POSTed data during pagination?
CONTROLLER:
#RequestMapping(value = "/list",method = {RequestMethod.POST, RequestMethod.GET})
public String list(#RequestParam(name = "page", defaultValue = "0") int page,
#RequestParam(name = "name", defaultValue = "") String name,
#RequestParam(name = "lastname", defaultValue = "") String lastname,
Pageable pageable,
Model model) {
Pageable pageRequest = new PageRequest(page, 4);
Cliente cliente = new Cliente();
Page<Cliente> clientes;
if (name.equals("") && lastname.equals("")) {
clientes = clienteService.findAll(pageRequest);
}else {
clientes = clienteService.findMatch(name, lastname, pageRequest);
}
PageRender<Cliente> pageRender = new PageRender<Cliente>("/listar", clientes);
model.addAttribute("titulo", "Listado de clientes");
model.addAttribute("clientes", clientes);
model.addAttribute("cliente", cliente);
model.addAttribute("page", pageRender);
return "listar";
}
HTML:
<form th:action="#{/listar}" th:object="${cliente}" method="post">
<div class="form-group row">
<label for="nombre" class="col-sm-2 col-form-label">Nombre</label>
<div class="col-sm-6">
<input type="text" th:field="*{nombre}" class="form-control"
th:errorclass="'form-control alert-danger'" /> <small
class="form-text text-danger"
th:if="${#fields.hasErrors('nombre')}" th:errors="*{nombre}"></small>
</div>
</div>
<div class="form-group row">
<label for="nombre" class="col-sm-2 col-form-label">Apellido</label>
<div class="col-sm-6">
<input type="text" th:field="*{apellido}" class="form-control"
th:errorclass="'form-control alert-danger'" /> <small
class="form-text text-danger"
th:if="${#fields.hasErrors('apellido')}" th:errors="*{apellido}"></small>
</div>
</div>
<div class="form-group row">
<div class="col-sm-6">
<input type="submit" th:value="'Buscar'"
class="btn btn-secondary" />
</div>
</div>
</form>
Pagination:
<nav th:fragment="paginator">
<ul class="pagination">
<li class="page-item"
th:class="${page.first? 'page-item disabled': 'page-item'}"><span
class="page-link" th:if="${page.first}">Primera</span> <a
class="page-link" th:if="${not page.first}"
th:href="#{${page.url}(page=0)}">Primera</a></li>
<li class="page-item"
th:class="${not page.hasPrevious? 'page-item disabled': 'page-item'}">
<span class="page-link" th:if="${not page.hasPrevious}">«</span>
<a class="page-link" th:if="${page.hasPrevious}"
th:href="#{${page.url}(page=${page.paginaActual-2})}">«</a>
</li>
<li class="page-item" th:each="item : ${page.paginas}"
th:class="${item.actual? 'page-item active': 'page-item'}"><span
class="page-link" th:if="${item.actual}" th:text="${item.numero}"></span>
<a class="page-link" th:if="${not item.actual}"
th:href="#{${page.url}(page=${item.numero-1})}"
th:text="${item.numero}"></a></li>
<li class="page-item"
th:class="${not page.hasNext? 'page-item disabled': 'page-item'}">
<span class="page-link" th:if="${not page.hasNext}">»</span> <a
class="page-link" th:if="${page.hasNext}"
th:href="#{${page.url}(page=${page.paginaActual})}">»</a>
</li>
<li class="page-item"
th:class="${page.last? 'page-item disabled': 'page-item'}"><span
class="page-link" th:if="${page.last}">Última</span> <a
class="page-link" th:if="${not page.last}"
th:href="#{${page.url}(page=${page.totalPaginas-1})}">Última</a>
</li>
</ul>
</nav>

I had a similar situation where I used the request parameter. So the trick is to capture the request parameter based on what we perform the search. Then afterwards you can get that parameter (from URL) and use it in the links you are building for pagination.
For example, say, your post/get URL looks like this:
http://localhost:8080/listByName?name=earth
Then get the vale of "name" parameter and use it while building your pagination url (links) in your html table/list like this:
th:href="#{/listByName/(name=${#request.getParameter('name')},pageSize=${selectedPageSize}, page=${page})}"
for me it working perfectly. This way you wont have to go for additional code using flashAttributes or mucking with JavaScript.

Related

Spring boot and thymeleaf pagination and sorting

I am studying spring boot and making pet project and now I need do pagination and sorting. I am using thymeleaf in html page and I have some problem with Pageable and Sort field.
I have controller
#GetMapping
public String showAllClassrooms(Model model, Pageable page) {
Page<Classroom> classroomPage = classroomService.getAndSort(page);
model.addAttribute("classroomPage", classroomPage);
return "classrooms-page";
}
and Service method
#Transactional
public Page<Classroom> getAndSort(Pageable paging) {
long totalElement = count();
List<Classroom> classrooms = new ArrayList<>();
if (paging.getSort().toString().contains("Address")) {
classrooms = getAndSortByAddress(paging.getPageSize(), (int) paging.getOffset());
} else {
classrooms = getAndSortByCapacity(paging.getPageSize(), (int) paging.getOffset());
}
return new PageImpl<Classroom>(classrooms, paging, totalElement);
}
and naviagion in page
<nav aria-label="..." th:object="${classroomPage}">
<ul class="pagination justify-content-center">
<li class="page-item" th:classappend="*{(getNumber == 0 ? 'disabled' : '' )}">
<a class="page-link" th:href="#{/classrooms/(page=*{getNumber-1}, size = *{size}, sort=*{sort})}">«</a></li>
<li class="page-item" th:classappend="*{(getNumber == getNumber ? 'active' : '' )}">
<a class="page-link" th:text="*{getNumber} + 1" th:href="#{/classrooms/(page=*{getNumber}, sort=*{sort})}" ></a></li>
<li class="page-item" th:classappend="(*{getNumber} == *{getTotalPages}-1 ? 'disabled' : '' )">
<a class="page-link" th:href="#{/classrooms/(page=*{getNumber+1} , size = *{size} , sort=*{sort})}">»</a>
</li>
<li class="page-item">
<form action="#" method="get" th:action="#{/classrooms/}"
>
<div class="input-group">
<input class="w-25 p-1" type="text" name="page" th:value="${classroomPage.getNumber+1}">
<input type="hidden" name="size" th:value="${classroomPage.size}">
<input type="hidden" name="sort" th:value="${classroomPage.getSort}">
<span class="input-group-text" th:utext="${classroomPage.getNumber + 1}" ></span>
</div>
</form>
</li>
</ul>
</nav>
everything is working alright, but I have double direction in address field of browser, like this
http://localhost:8080/classrooms/?page=2&size=5&sort=Capacity:%20ASC:%20ASC:%20ASC:%20ASC:%20ASC:%20ASC:%20ASC:%20ASC
Thank you for you time, and sorry for my bad english :)

Laravel submit form from a tab and return to same tab in view

I have a view with multiple tabs. Each having different forms. When I submit a form from one tab, it returns to same page but primary tab. How could I get to return to same tab from which I was working.
Controller
public function recieve(Request $request)
{
$item = Item::find($request->input('item'));
$item->recieved_at = now();
$item->recieved_status = "1";
$item -> save();
return redirect('/files/'.$item->file)->with('success','Item Recieved Confirmed');
}
view - tabs
<ul class="nav nav-tabs" id="fileTab" role="tablist">
<li class="nav-item">
<a class="nav-link active" id="profile-tab" data-toggle="tab" href="#profile" role="tab"
aria-controls="profile" aria-selected="true">Profile</a>
</li>
<li class="nav-item">
<a class="nav-link" id="job-tab" data-toggle="tab" href="#job" role="tab" aria-controls="job"
aria-selected="false">Job</a>
</li>
<li class="nav-item">
<a class="nav-link" id="items-tab" data-toggle="tab" href="#items" role="tab" aria-controls="items"
aria-selected="false">Items</a>
</li>
<li class="nav-item"><a class="nav-link" id="mechanic-tab" data-toggle="tab" href="#mechanic" role="tab"
aria-controls="mechanic" aria-selected="false">Labour Hours</a>
</li>
<li class="nav-item">
<a class="nav-link" id="accounts-tab" data-toggle="tab" href="#accounts" role="tab"
aria-controls="accounts" aria-selected="false">Accounts</a>
</li>
<li class="nav-item">
<a class="nav-link" id="accounts-tab" data-toggle="tab" href="#preview" role="tab"
aria-controls="accounts" aria-selected="false">Print Preview</a>
</li>
</ul>
Form
#if($file->job_status == "Closed")#else
{!! Form::open(['action' => 'FilesController#item','method' => 'POST']) !!}
<div class="row pt-3 pb-1">
<div class="form-group col-xs-12 col-sm-12 col-md-2">
{{Form::text('part_number','',['class'=>'form-control','placeholder'=>'Part Number'])}}
</div>
<div class="form-group col-xs-12 col-sm-12 col-md-6">
{{Form::text('description','',['class'=>'form-control','placeholder'=>'Part Name'])}}
</div>
<div class="form-group col-xs-12 col-sm-12 col-md-2">
{{Form::text('qty','',['class'=>'form-control','placeholder'=>'Qty'])}}
</div>
<div class="form-group col-xs-12 col-sm-12 col-md-2">
{{Form::select('recieved_by',$users,null,['class'=>'form-control'])}}
</div>
</div>
{{Form::hidden('file',$file->id)}}
{{Form::submit('Release Item',['class'=>'form-control btn-danger btn btn-sm'])}}
{!! Form::close() !!}
#endif
I tried using hashtag tab name in return redirect statement,
return redirect('/files/'.$item->file."#items-tab")->with('success','Item Recieved Confirmed');
it would simply highlight the name but would not select. How could I achieve it?
your tab navigation,
<ul class="nav nav-tabs" id="tabMenu" role="tablist">
<li><i class="fa fa-camera" aria-hidden="true"></i> Galleries</li>
</ul>
hidden input field for tab
<input type="hidden" name="tab" value="Galleries">
RedirectRoute
$tab = $request->get('tab');
return back()->withInput(['tab'=>$tab]);
Javascript,
<script>
//redirect to specific tab
$(document).ready(function () {
$('#tabMenu a[href="#{{ old('tab') }}"]').tab('show')
});
</script>
If you want to do it in laravel than all you can do is,
-Give an id to each tab and an write an active class.
-Put a hidden input with value of the parent tab id.
-So, laravel will receive the tab id in the request object.
-Now, you can do whatever and return the tab id with to the view.
-Give a if condition to each tab item and check if matches the id from laravel response.
The match the id set the active class to it.
example
<ul>
<li id='tab1 {{ session()->get('tabId') === 'tab1' ? 'active' : '' }}'></li>
<li id='tab2 {{ session()->get('tabId') === 'tab2' ? 'active' : '' }}'></li>
</ul>
// tab1 body
<form>
<input type="hidden" name="tabId" value="tab1">
...
</form>
// tab2 body
<form>
<input type="hidden" name="tabId" value="tab2">
...
</form>
// controller
public funciton(Request $request) {
//tabId
$tabId = $request->input('tabId')
....
....
return redirect()->back()->with('tabId' => $tabId);
}
You can do this:
Controller:
public function tab() {
$active_tab = "tab2";
return view('tabs.index', compact('active_tab'));
}
View:
<ul class="nav nav-tabs">
<li class="#if($active_tab=="tab1") active #endif"><a data-toggle="tab" href="#home">Home</a></li>
<li class="#if($active_tab=="tab2") active #endif"><a data-toggle="tab" href="#menu1">Menu 1</a></li>
<li class="#if($active_tab=="tab3") active #endif"><a data-toggle="tab" href="#menu2">Menu 2</a></li>
</ul>
<div class="tab-content">
<div id="home" class="tab-pane fade #if($active_tab=="tab1") in active #endif">
<h3>HOME</h3>
<p>Some content.</p>
</div>
<div id="menu1" class="tab-pane fade #if($active_tab=="tab2") in active #endif">
<h3>Menu 1</h3>
<p>Some content in menu 1.</p>
</div>
<div id="menu2" class="tab-pane fade #if($active_tab=="tab3") in active #endif">
<h3>Menu 2</h3>
<p>Some content in menu 2.</p>
</div>
</div>
You can show a specific tab with this code:
function showTab(tab){
$('.nav-tabs a[href="#' + tab + '"]').tab('show');
};
// Verify location.hash
if (window.location.hash !== ''){
showTab(window.location.hash);
}
But I would pass a query string in the return, just to make sure there will be no collision with other eventual hashes. Something like:
return redirect('/files/'.$item->file."?openTab=your-tab-id")->with('success','Item Recieved Confirmed');
Of course, you would change the "location.hash" verification to a query string verification. Example: https://davidwalsh.name/query-string-javascript

Spring controller null object ID

When the user goes to recipe/new it sends a RecipeCommand object, then after the user sets the information and Recipe Ingredients and Directions, RecipeCommand objects gets send to recipe/new/ingredients. I convert it to a recipe object then save it and return it. Then I send an Ingredients Wrapper which has N RecipeCommands (depends the number the user set at Recipe Ingredients) and the RecipeCommand again and return to recipe/recipe_add_ingredients. This leads to recipe/new/{recipeId}/ingredients/directions. Then I take the IngredientsWrapper and add every IngredientCommand object to the RecipeCommand. The problem is that the object has a null ID even though I've added it into the database and it shows that it has the ID of 2. Here is the code:
add_recipe
<form th:object="${recipe}" th:action="#{/recipe/new/ingredients}" enctype="multipart/form-data">
<input type="hidden" th:field="*{id}">
<div class="add-recipe-container">
<div class="add-recipe-inputs-container">
<div class="add-recipe-inputs">
<ul class="add-recipe-inputs-list">
<li>
<label for="recipeName">Recipe Name </label>
<input id="recipeName" name="recipeName" th:field="*{recipeName}" type="text">
</li>
<li>
<label for="cookTime">Cook Time</label>
<input th:field="*{recipeCookTime}" placeholder="Without minutes" type="number">
</li>
<li>
<label for="prepTime">Prep Time</label>
<input th:field="*{recipePrepTime}" placeholder="Without minutes" type="number">
</li>
<li>
<label for="servings">Servings</label>
<input th:field="*{recipeServings}" type="number">
</li>
</ul>
</div>
</div>
<div class="add-recipe-options-container">
<div class="add-recipe-options">
<ul class="add-recipe-options-list">
<li>
<label>Difficulty</label>
<select th:field="*{difficulty}" id="difficulty.id">
<option th:each="difficultyEach : ${T(com.vio.spring5.domain.Difficulty).values()}"
th:value="${difficultyEach.id}"
th:text="${difficultyEach.name}">
</option>
</select>
</li>
<li>
<label>Category</label>
<select th:field="*{recipeCategory}" id="recipeCategory.id">
<option th:each="category : ${T(com.vio.spring5.domain.RecipeCategory).values()}"
th:value="${category.id}"
th:text="${category.name}">
</option>
</select>
</li>
<li>
<label for="ingredientsAmount">Ingredients</label>
<input th:field="*{recipeIngredientsAmount}" type="number">
</li>
<li>
<label for="directionsAmount">Directions</label>
<input th:field="*{recipeDirectionsAmount}" type="number">
</li>
<li>
<label for="">Image</label>
<input th:field="*{image}" id="imagefile" name="imagefile" type="file" class="file">
</li>
</ul>
</div>
</div>
</div>
<button type="submit" class="next-page-button">Next</button>
</form>
add_ingredient
<form th:object="${ingredientsWrapper}" th:action="#{'/recipe/new/' + ${recipe.getId()} + '/ingredients/directions'}" method="get">
<div class="add-recipe-container">
<ul class="recipe-many">
<li th:each="ingredientInputs, iter : ${ingredientsWrapper.ingredientsWrapperSet}">
<ul class="add-recipe-ingredients-list">
<li>
<label for="">Amount</label>
<input th:field="*{ingredientsWrapper[__${iter.index}__].amount}" type="number">
</li>
<li>
<label for="">Unit</label>
<select th:field="*{ingredientsWrapper[__${iter.index}__].unitOfMeasure}">
<option th:each="unit : ${unitOfMeasure}"
th:value="${unit.id}"
th:text="${unit.unitName}">Test</option>
</select>
</li>
<li>
<label for="">Ingredient Name</label>
<input th:field="*{ingredientsWrapper[__${iter.index}__].ingredientName}" type="text">
</li>
</ul>
</li>
</ul>
</div>
<button type="submit" class="add-recipe">Add Recipe</button>
</form>
add_directions
<form th:object="${directionsWrapper}" th:action="#{'/recipe/new/' + ${recipe.id} + '/ingredients/directions'}" method="post">
<div class="add-directions-container">
<ul class="directions-many">
<li th:each="directions, iter : ${directionsWrapper.directionsWrapperList}">
<label>Step: </label>
<textarea th:field="*{directionsWrapper[__${iter.index}__].directions}" cols="40" rows="3"></textarea>
</li>
</ul>
</div>
<button type="submit" class="add-recipe">Add Recipe</button>
</form>
Controllers
/*
* Send a RecipeCommand object to front
*/
#GetMapping(value = "/recipe/new")
public String newRecipe(Model model) {
model.addAttribute("recipe", new RecipeCommand());
return "recipe/recipe_add";
}
/*
* Send the recipe wrapper
* To do: throw exception and validation
*
*/
#GetMapping(value = "/recipe/new/ingredients")
public String addIngredients(#ModelAttribute("recipe") RecipeCommand recipe, BindingResult bidingResult, Model model) {
recipeService.saveRecipeCommand(recipe);
IngredientsWrapper wrapper = new IngredientsWrapper();
addIngredientsCommandObjects(wrapper, recipe.getRecipeIngredientsAmount());
model.addAttribute("unitOfMeasureSet", uomService.findAll());
model.addAttribute("ingredientsWrapper", wrapper);
model.addAttribute("recipe", recipe);
return "recipe/recipe_add_ingredients";
}
/*
* to do: validate
*/
#GetMapping(value = "/recipe/new/{recipeId}/ingredients/directions")
public String addDirections (#PathVariable String recipeId,
#ModelAttribute("ingredientsWrapper") IngredientsWrapper wrapper, Model model) {
RecipeCommand recipe = recipeService.findRecipeCommandById(Long.valueOf(recipeId));
wrapper.ingredientsWrapperSet
.iterator()
.forEachRemaining(ingredient -> recipe.addIngredient(ingredient));
recipeService.updateRecipeCommandIngredients(recipe);
DirectionsWrapper directionsWrapper = new DirectionsWrapper();
addDirectionsCommandObjects(directionsWrapper, recipe.getRecipeDirectionsAmount());
model.addAttribute("directionsWrapper", directionsWrapper);
model.addAttribute("recipe", recipe);
return "recipe/recipe_add_directions";
}
/*
* to do: validate
*/
#PostMapping(value = "/recipe/new/{recipeId}/ingredients/directions/")
public String addRecipe(#PathVariable String recipeId,
#ModelAttribute("directionsWrapper") DirectionsWrapper wrapper) {
RecipeCommand recipe = recipeService.findRecipeCommandById(Long.valueOf(recipeId));
wrapper.directionsWrapperList
.iterator()
.forEachRemaining(directions -> recipe.addDirections(directions));
recipeService.updateRecipeCommandDirections(recipe);
return "redirect:/browse";
}

Submitting a POST object

I spent the whole weekend searching the net on my problem. It seems like I am missing something really silly, but I failed to pick it up.
Here's the problem. I sent an object to a JSP and on the JSP I could see its content. I them I submitted the form. Back in the controller, it shows the object is overwritten/recreated. I can't seem to understand. I checked the logs on my Tomcat but I do not see any error...
On my Controller:
#RequestMapping(value = {"/", "/home"}, method = RequestMethod.GET)
public String homePage(ModelMap model) {
model.addAttribute("user", getPrincipal());
Catalog catalog = catalogService.getCatalogByCategory(Catalog.CatalogCategory.ALL);
model.addAttribute("catalog", catalog);
model.addAttribute("numberOfItemsAdded", "500");
return "welcome";
}`
and in my JSP I have the following:
<form:form method="POST" modelAttribute="catalog">
<form:hidden path="id"/>
<div id="products" class="row list-group">
<c:forEach var="orderItem" items="${catalog.orderItems}">
<div class="item col-xs-4 col-lg-4">
<div class="thumbnail">
<img class="group list-group-image" src="http://placehold.it/400x250/000/fff" alt=""/>
<div class="caption">
<h4 class="group inner list-group-item-heading">
${orderItem.name}</h4>
<p class="group inner list-group-item-text">
${orderItem.description}
</p>
<div class="row">
<div class="col-xs-12 col-md-6">
<p class="lead">
R ${orderItem.price}</p>
</div>
<div class="col-xs-12 col-md-6">
<label for="${orderItem.id}" class="btn btn-primary">Add to Cart <input
type="checkbox" id="${orderItem.id}" name="orderItem.addedToCart"
class="badgebox"><span class="badge">&check;</span></label>
</div>
</div>
</div>
</div>
</div>
</c:forEach>
</div>
<div class="row">
<div class="form-group">
<div class="col-sm-12 pull-right">
</div>
<div class="col-sm-2 pull-right">
<input type="submit"
class="btn btn-default btn-block btn-primary"
value="Next" name="action" formmethod="POST"
formaction="confirmList"/>
</div>
</div>
</div>
</form:form>`
After pressing "Next", which submits the form data to a controller:
#RequestMapping(value = "/confirmList", method = RequestMethod.POST)
public String confirmList(#ModelAttribute Catalog catalog, #ModelAttribute String numberOfItemsAdded) {
System.out.println("\n\n------>catalog = " + catalog);
System.out.println("\n\n------>numberOfItemsAdded = " + numberOfItemsAdded);
List<OrderItem> selectedItems = new ArrayList<OrderItem>();
for (OrderItem orderItem : catalog.getOrderItems()) {
if (orderItem.isAddedToCart()) {
selectedItems.add(orderItem);
}
}
//model.addAttribute("numberOfItemsAdded", selectedItems.size());
return "welcome";
}
`
The System.out.println(...) output the following:
------>catalog = Catalog{id=1, name='null', category='null', orderItems=null}
------>numberOfItemsAdded =
Those are empty outputs.... :'(
I have no idea what I am doing wrong here.....
This was answered in a comment line by George. All I had to do is hide/bind those null fields.
It is very concerning that we use the term 'hidden' to also mean 'ignore' or 'leave as is'. But anyway, the solution above did exactly what I was looking for.
Thanks to the Community

how to turn this spring boot thyme-leaf code into Ajax

I Have a comment and post system and I want To turn it into ajax without using thymeleaf fragmentation. How to do it i cannot figure out I do not want to refresh the page each time i make a post or comment .
Controller :
#Controller
public class DashboardController {
private Post post;
private User user;
#Autowired
private PostRepository postRepository;
#Autowired
private UserRepository userRepository;
#Autowired
CommentRepository commentRepository;
#RequestMapping(value = "/dashboard", method = RequestMethod.GET)
public String returnPosts(Model model) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
String currentPrincipalName = authentication.getName(); //holding login user details
model.addAttribute("firstName", userRepository.findByEmail(currentPrincipalName).getFirstName());
model.addAttribute("newPost", new Post());
model.addAttribute("newComment", new Comment());
model.addAttribute("posts", postRepository.findAllByOrderByDateDesc());
model.addAttribute("comments", commentRepository.findAll());
return "main";
}
#RequestMapping(value = "/dashboard/posts", method = RequestMethod.POST)
public String addPost(Model model, #ModelAttribute Post post, #ModelAttribute User user) {
model.addAttribute("newPost", post);
creatPost(post);
System.out.println(post.getId());
return "redirect:/dashboard";
}
#RequestMapping(value = "/dashboard/comments", method = RequestMethod.POST)
public String addComment( Model model, #ModelAttribute Comment comment,
#ModelAttribute User user) {
model.addAttribute("newComment", comment);
// model.addAttribute("posts", post);
creatComment(comment.getPostId(), comment);
System.out.println(comment.toString());
//System.out.println(post.getId());
// System.out.println(comment.getPostId());
return "redirect:/dashboard";
}
private Comment creatComment(String id, Comment comment) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
String currentPrincipalName = authentication.getName();
comment.setDate(new Date());
comment.setAuthor(userRepository.findByEmail(currentPrincipalName).getFirstName()
+ " " + userRepository.findByEmail(currentPrincipalName).getLastName());
comment.setPostId(id);
return commentRepository.save(comment);
}
private Post creatPost(Post post) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
String currentPrincipalName = authentication.getName(); //holding login user details
post.setAuthor(userRepository.findByEmail(currentPrincipalName).getFirstName()
+ " " + userRepository.findByEmail(currentPrincipalName).getLastName());
post.setDate(new Date());
return postRepository.save(post);
}
}
Thymeleaf forms :
<div id="content" class="yellow col-xs-12">
<form class="col-xs-12" role="form" action="/dashboard/posts"
th:action="#{/dashboard/posts}" th:object="${newPost}" method="post">
<div class="form-group col-xs-12">
<textarea class="form col-xs-6" rows="2" id="full" placeholder="share anything....."
th:field="*{content}" style="font-size: 20px;" required="required"></textarea>
<div class="menu1 col-xs-12">
<hr/>
<ul class="text-center col-xs-12">
<a href="#">
<li>
<button type="submit" class="sendpost btn btn-success">Send</button>
</li>
<li class="xs-12 "><i class="fa fa-flash fa-lg"></i>Tasks</li>
<li class="xs-12"><i class="fa fa-paperclip fa-lg"></i>files</li>
<li class="xs-12"><i class="fa fa-calendar fa-lg"></i> calendar</li>
<li class="xs-12"><i class="fa fa-search fa-lg"></i>stying</li>
</a>
</ul>
</div>
</div>
</form>
<div>
<div th:each="post : ${posts}" style="border:2px solid #CCCCCC ; margin-bottom: 50px" id="post-div"
class="post-group col-xs-12">
<div class="imag col-xs-2">
<!--<input type="hidden" th:field="*{post.id}" disabled="disabled"/>-->
<img style="width: 50px;" src="images/1.png" class="img-circle img-responsive" alt=""/>
</div>
<div class=" col-xs-10">
<h4 style="line-height: .4;"><p class="name" th:text="*{post.author}">
</p>
<small style="color: #337ab7" th:text="*{post.date}"></small>
</h4>
<br/>
<p style="font-size: 20px" id="post-p" class="desc" th:text="*{post.content}"></p><br/>
<div class="footer ignore-zoom">
<a class="comment" onclick="showDiv1()"><i class="aa fa fa-comment"></i>
<span class="lin">0</span></a>
<a onclick="showDiv2()" href="#">
<i id="like" class="aa fa fa-heart active"></i>
<span style="display:none;" id="like-1" class="lin">1</span></a>
<a class="aa dropdown-toggle" data-toggle="dropdown" href="#" aria-expanded="false"><i
class="fa fa-pencil"></i> </a>
</div>
<div th:each="comment : ${comments}" id="my-comment">
<div th:if="${post.id == comment.postId}">
<hr/>
<br/>
<img class="img-circle img-responsive" src="images/1.png"
style="margin-right:5%; width: 50px; display: inline-flex; color:#080602;"/>
<div style="line-height:.8">
<label th:text="*{comment.author}"> </label><br/>
<small th:text="*{comment.date}" style=" color: #337ab7 ; margin-left:16%;">time of
comment
</small>
</div>
<br/>
<p style="font-size: 16px;" id="-comment" th:text="*{comment.comment}"></p>
<div class="footer footer1 ignore-zoom">
<a onclick="showDiv4()" href="#">
<i id="like1" class="aa fa fa-heart active"></i>
<span style="display:none;" id="like-2" class="lin">1</span></a>
<a class="aa dropdown-toggle" data-toggle="dropdown" href="#" aria-expanded="false"><i
class="fa fa-pencil"></i> </a>
</div>
</div>
</div>
<form role="form" action="/dashboard/comments"
th:action="#{/dashboard/comments}" th:object="${newComment}" method="post">
<input type="hidden" name="postId" th:value="${post.id}"/>
<div id="comment-div" class="form-group col-xs-12">
<textarea th:field="*{comment}" class="form col-xs-6" rows="2" id="full2"
placeholder="Your Comment....." required="required"></textarea>
<div class="menu1 col-xs-12">
<hr/>
<ul class="text-center col-xs-12">
<a href="#">
<li onclick="showDiv()">
<button type="submit" class="btn btn-info">Send</button>
</li>
<li class="xs-12 "><i class="fa fa-flash fa-lg"></i></li>
<li class="xs-12"><i class="fa fa-paperclip fa-lg"></i></li>
<li class="xs-12"><i class="fa fa-calendar fa-lg"></i></li>
<li class="xs-12"><i class="fa fa-search fa-lg"></i></li>
</a>
</ul>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
You can have a look at the tutorial http://www.thymeleaf.org/doc/tutorials/2.1/thymeleafspring.html#ajax-fragments
And the content is as below:
Ajax fragments
WebFlow allows the specification of fragments to be rendered via AJAX with tags, like this:
<view-state id="detail" view="bookingDetail">
<transition on="updateData">
<render fragments="hoteldata"/>
</transition>
</view-state>
These fragments (hoteldata, in this case) can be a comma-separated list of fragments specified at the markup with th:fragment :
<div id="data" th:fragment="hoteldata">
This is a content to be changed
</div>
Always remember that the specified fragments must have an id attribute, so that the Spring JavaScript libraries running on the browser are capable of substituting the markup.
tags can also be specified using DOM selectors:
<view-state id="detail" view="bookingDetail">
<transition on="updateData">
<render fragments="[//div[#id='data']]"/>
</transition>
</view-state>
...and this will mean no th:fragment is needed:
<div id="data">
This is a content to be changed
</div>
As for the code that triggers the updateData transition, it looks like:
<script type="text/javascript" th:src="#{/resources/dojo/dojo.js}"></script>
<script type="text/javascript" th:src="#{/resources/spring/Spring.js}"></script>
<script type="text/javascript" th:src="#{/resources/spring/Spring-Dojo.js}"></script>
...
<form id="triggerform" method="post" action="">
<input type="submit" id="doUpdate" name="_eventId_updateData" value="Update now!" />
</form>
<script type="text/javascript">
Spring.addDecoration(
new Spring.AjaxEventDecoration({formId:'triggerform',elementId:'doUpdate',event:'onclick'}));
</script>

Resources