Thymeleaf and th:if not skipping text when null - spring-boot

I understand that you should be able to "skip" text printing if Object is null, in thymeleaf, using th:if.
However my page throws Null error at line 23. (second div)
<div th:if="${Brackets}">
<th:block th:each="brackets : ${Brackets}">
<div th:if="${brackets.brackets}">
<tr th:each="bracket : ${brackets.brackets}">
<td th:text="${bracket.lower}"></td>
<td th:text="${bracket.higher}"></td>
<td th:text="${bracket.prc}"></td>
</tr>
</div>
</th:block>
</div>
What am i missing here?
Solved with "?"
Many thanks to Patrick!
<div th:if="${Brackets} != null">
<th:block th:each="brackets : ${Brackets}">
<div th:if="${brackets?.brackets} != null">
<tr th:each="bracket : ${brackets?.brackets}">
<td th:text="${bracket.lower}"></td>
<td th:text="${bracket.higher}"></td>
<td th:text="${bracket.prc}"></td>
</tr>
</div>
</th:block>
</div>

Its strange that the null check does not work. It could be that the naming has some issues. Anyway, a short way to use null objects savely is to use save navigation. You use it with the ? operator:
<div th:if="${brackets?.brackets} != null">

Related

Laravel 9 404 Error on GET Request updating database when clicking button

I was having another laravel question here. I was facing 404 error when clicking the button
Confirm Registration on the purpose of changing its database based on the item id on the view. Logically, I think my code should have work on this part.
Confirm Registration
However, it comes up 404 Error. Herby I include all the related code in the section.
Error
Frontend (To prove that the data passing is successful in the view)
web.php
Route::controller(ResidenceController::class)->group(function(){
Route::get('/residence/register', 'registration')->name('residence.register');
Route::get('/residence/search', 'SearchProperty')->name('residence.search');
Route::get('/registration/confirmation/{$uniquecode}', 'ConfirmRegistration')->name('registration.confirm');
});
The focus is on:
Route::get('/registration/confirmation/{$uniquecode}',
'ConfirmRegistration')->name('registration.confirm');
Controller
public function ConfirmRegistration($uniquecode){
$confirm = Properties::where('uniquecode', $uniquecode)->update(['status'=>'pending', 'tenant_id'=>Auth::user()->id]);
if($confirm){
session()->flash('alert-success','Successfully Applied');
}
else{
session()->flash('alert-warning','Error Occured');
}
}
register.blade.php
#foreach ($toSearch as $key=>$view)
<div class="card" style="width: 50rem;">
<div class="card-body">
<div class="container">
<div class="row">
<div class="col-md-3">
<img src="{{ (!empty($tenant->unit_image))? url('uploads/properties/'.$tenant->unit_image):url('uploads/properties/default.jpg') }}" class="img-fluid" alt="unit image" >
</div>
<div class="col-md-9">
<table>
<tr>
<td style="width: 20%">Property</td>
<td style="width:10%; text-align: center">:</td>
<td>{{$view->name}}</td>
</tr>
<tr>
<td>Address</td>
<td style="text-align: center">:</td>
<td>{{$view->address1}},{{$view->address2}},{{$view->city}}</td>
</tr>
<tr>
<td>Landlord</td>
<td style="text-align: center">:</td>
<td>{{$view->landlord->name}}</td>
</tr>
<tr>
<td>Contact No</td>
<td style="text-align: center">:</td>
<td>{{$view->landlord->phone_number}}</td>
</tr>
<tr>
<td>Status</td>
<td style="text-align: center">:</td>
<td>{{$view->status}}</td>
</tr>
</table>
</div>
</div>
</div>
</div>
<br>
<!--To confirm registration-->
#if( $view->status != 'approved')
Confirm Registration
#endif
</div>
#endforeach
The focus is on:
#if( $view->status != 'approved')
uniquecode) }}" class="btn btn-primary">Confirm
Registration
#endif
Database:
you need to use post method for inserting data (register),
anyway, change your route parameter $uniquecode to uniquecode.
and when you use route second argument is a compact, use
route('registration.confirm',['uniquecode' => $view->uniquecode]);

Thymeleaf error : An error happened during template parsing

I don't know what is wrong with my view but it is impossible for it to work, the view always gives an error even if idStudent is set correctly.I don't know if there is also another way to do it, but thymeleaf always fail
here is the error - > Exception evaluating SpringEL expression: "student.id == {idStudent}" (template: "/content/course/list-course-student" - line 55, col 24)
here is my controller
#GetMapping("/list-courses-student")
public String listCoursesByUser(#RequestParam(required = false) int page,Model model) {
User currentUser = userService.findByName(this.currentUser.getUsername());
int numberPages = coursesService.getNumberPages();
List<Course> courses = coursesService.findAllCourses(page,true);
model.addAttribute("coursesDisponibles",courses);
model.addAttribute("numberPages",numberPages);
model.addAttribute("currentPage",page);
model.addAttribute("idStudent",currentUser.getStudent().getId());
return "/content/course/list-course-student";
}
My view
<div class="card-body table-responsive p-0">
<table class="table table-hover text-nowrap">
<thead>
<tr>
<th>Profesor</th>
<th>Nombre</th>
<th>Description</th>
<th>Code</th>
<th>Inicio</th>
<th>Final</th>
<th>Acciones</th>
</tr>
</thead>
<tbody>
<th:block th:each="course : ${coursesDisponibles}">
<tr>
<td
th:text="${course.teacher == null} ? 'No Asignado' : ${course.teacher.nombre}"></td>
<td th:text="${course.nombre}"></td>
<td th:text="${course.descripcion}"></td>
<td th:text="${course.code}"></td>
<td
th:text="${#temporals.format(course.inicioDate, 'dd/MM/yyyy')}"></td>
<td
th:text="${#temporals.format(course.finalDate, 'dd/MM/yyyy')}"></td>
<td>
<th:block th:each="student : course.Estudiantes">
<th:block th:if="${student != null}">
<th:block th:if="${student.id == {idStudent}}">
<a class="btn btn-success btn-sm" href="">Añadido</a>
<a class="fas fa-inbox ml-3"
th:href="${'/tareas/list-tareas-student?page=1&course=' + {course.id}}"></a>
</th:block>
</th:block>
<th:block th:unless="${student == null}">
<a
th:classappend="${course.teacher == null} ? 'btn btn-primary btn-sm disabled':'btn btn-primary btn-sm' "
th:href="${'/courses/add?idCourse=' + {course.id} + '&idStudent=' + {idStudent}}">Añadir</a>
</th:block>
</th:block>
</td>
</th:block>
</tr>
</tbody>
</table>
</div>
The exception you're most likely experience is NullPointerException, because I think you have a wrong th:each declaration:
<th:block th:each="student : course.Estudiantes">
instead of
<th:block th:each="student : ${course.Estudiantes}">
Thus, expression th:if=${student.id == idStudent} throws NullPointerException as it tries to access the id property on a null student object.
Also note that in order to preventer other NPE's you can use a ? operator in your expressions, like this: ${student?.id}.

Perform conditions in ThymeLeaf in Spring Boot project

I am using Spring Boot Thymeleaf and wanted to take conditional based decision. If condition matches, then whole row should be green else red
<body>
<div class="container my-2">
<h1>Active Workflow Details</h1>
<div class="card">
<div class="card-body">
<div th:switch="${mdsAcives}" class="container my-5">
<div class="col-md-10">
<h2 th:case="null">No record found !!</h2>
<div th:case="*">
<table border="1" class="table table-striped table-responsive-md">
<thead>
<tr>
<th>Mapping Name</th>
<th>Type of Mappings</th>
<th>Table Names</th>
<th>System 1 Count </th>
<th>System 2 Count </th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr th:each="m : ${mdsAcives}">
<td th:text="${m.mappingName}"></td>
<td th:text="${m.type}"></td>
<td th:text="${m.tableName}"></td>
<td th:text="${m.system1Cnt}"></td>
<td th:text="${m.system2Cnt}"></td>
<td th:style="${m.system1Cnt} eq ${m.system2Cnt} ? 'color: red;' : 'color: green;'}}" th:text="TRUE or FALSE"></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
You can do something like this:
<tr th:class="${your condition}? 'green' : 'red'">
I assume you have defined two CSS classes to make the row green or red.

How to remove tag span, space, new line character in Thymeleaf conditional code block?

I am using Spring Boot 2.1.5.RELEASE, Thymeleaf 3.0.11.RELEASE (thymeleaf-3.0.11.RELEASE.jar), Thymeleaf Spring 3.0.11.RELEASE (thymeleaf-spring5-3.0.11.RELEASE.jar)
code snippet
<tr th:each="employee : ${employeeList}">
<td th:text="${employee.order}"></td>
<td th:text="${employee.age}"></td>
<td th:switch="${employee.level}">
<span th:case="0">Junior</span>
<span th:case="1">Senior</span>
<span th:case="2">Expert</span>
</td>
<td th:text="${employee.activeStatus}"></td>
</tr>
For sorting in data-grid by JavaScript, I need remove <span></span> tag pairs. For example, if an employee has level = 2. This time, Thymeleaf will render
<td><span>Expert<span></td>
I hope it become to
<td>Expert</td>
(without <span> tag). How to to this?
I also try
<tr th:each="employee : ${employeeList}">
<td th:text="${employee.order}"></td>
<td th:text="${employee.age}"></td>
<td th:switch="${employee.level}">
<th:block th:case="'0'">Junior</th:block>
<th:block th:case="'1'">Senior</th:block>
<th:block th:case="'2'">Expert</th:block>
</td>
<td th:text="${employee.activeStatus}"></td>
</tr>
But It generate unwanted character
<td>
Expert
</td>
(Has new line or space before text, It is not wanted result)
The answer is, you shouldn't care about the extra spaces & newlines. HTML ignores those spaces when rendering, and so it shouldn't matter to you -- and there is no way to get rid of them short of formatting hacks.
If you really want to get rid of the spaces you could:
Put the switch on one line.
<tr th:each="employee : ${employeeList}">
<td th:text="${employee.order}"></td>
<td th:text="${employee.age}"></td>
<td th:switch="${employee.level}"><th:block th:case="'0'">Junior</th:block><th:block th:case="'1'">Senior</th:block><th:block th:case="'2'">Expert</th:block></td>
<td th:text="${employee.activeStatus}"></td>
</tr>
Create a Map<String, String> levelToDescription, put it on the model, and use that instead of a switch statement.
<tr th:each="employee : ${employeeList}">
<td th:text="${employee.order}" />
<td th:text="${employee.age}" />
<td th:text="${levelToDescription[employee.level]}" />
<td th:text="${employee.activeStatus}" />
</tr>
Etc...
Replace
<td th:switch="${employee.level}">
<th:block th:case="'0'">Junior</th:block>
<th:block th:case="'1'">Senior</th:block>
<th:block th:case="'2'">Expert</th:block>
</td>
by
<th:block th:if="${employee.level} eq '0'"><td>Junior</td></th:block>
<th:block th:if="${employee.level} eq '1'"><td>Senior</td></th:block>
<th:block th:if="${employee.level} eq '2'"><td>Expert</td></th:block>

Locating using id fails but using link it succeeds to click

For the following link,
<td style="padding-top:3px" align="center">
GNWL200/WL102
<br/>
<a id="17235-SL-GN-0" href="javascript:jpBook($('#17235-SL-GN-0'),'17235','HSRA','SRT','22-9-2017','SL','GN',3,false,0,0,'S');" tabindex="1">Book Now</a>
</td>
If I uses the link as shown below, it succeeds to click
browser.element(link: "Book Now").click
But if I uses the id as shown below it says element is not visible(not present). May I know why?
browser.link(:id, "17235-SL-GN-0").click
Error
Uncaught exception: element located, but timed out after 30 seconds, waiting for #<Watir::Anchor: located: true; {:id=>"17235-SL-GN-0", :tag_name=>"a"}> to be present
C:/Ruby23/lib/ruby/gems/2.3.0/gems/watir-6.8.4/lib/watir/elements/element.rb:633:in `raise_present'
C:/Ruby23/lib/ruby/gems/2.3.0/gems/watir-6.8.4/lib/watir/elements/element.rb:672:in `rescue in element_call'
C:/Ruby23/lib/ruby/gems/2.3.0/gems/watir-6.8.4/lib/watir/elements/element.rb:684:in `element_call'
C:/Ruby23/lib/ruby/gems/2.3.0/gems/watir-6.8.4/lib/watir/elements/element.rb:136:in `click'
C:/Users/rajagopalan.m/RubymineProjects/SeleniumLearning/Rest/TrainTicketBooking.rb:18:in `<top (required)>'
If link is not visible for regular Click() use jsClick:
"arguments[0].click();"
I'm not sure how it looks like in Ruby, but C#, Java looks simillar to:
JavascriptExecutor executor = (JavaScriptExecutor) driver;
executor.executeScript("arguments[0].click();", element);
I found the solution to my question from #yong comment
Actually there are two element present in the page with same id and the first one is invisible and the second one is actual element which I wanted to click, that's what it's throwing the error.
Here is the html file
<td style="padding-top:3px" align="center">
GNWL203/WL105
<br/>
**<a id="17235-SL-GN-0" href="javascript:jpBook($('#17235-SL-GN-0'),'17235','HSRA','SRT','22-9-2017','SL','GN',3,false,0,0,'S');" tabindex="1">Book Now</a>**
</td>
<td style="padding-top:3px" align="center">
<td style="padding-top:3px" align="center">
<td style="padding-top:3px" align="center">
<td style="padding-top:3px" align="center">
<td style="padding-top:3px" align="center">
</tr>
</tbody>
</table>
<span style="font:11px arial;color:red;float:right">* CURR_AVBL : Current Booking Available | RAC : Reservation Against Cancellation | WL # : Wait List | REGRET/WL : No more booking allowed | AVAILABLE : Available | NOT AVAILABLE : Not Available</span>
<br/>
</div>
</div>
<div id="j_idt413" class="rf-p ">
<div id="enqpanelid1" class="rf-p ">
</div>
</span>
<form id="avlAndFareForm" name="avlAndFareForm" method="post" action="/eticketing/trainbetweenstns.jsf" enctype="application/x-www-form-urlencoded">
<input name="avlAndFareForm" value="avlAndFareForm" type="hidden"/>
<div id="avlAndFareForm:trainSchedPanel" style="visibility: hidden;">
<div id="avlAndFareForm:j_idt480" class="rf-p " style="min-height:383px;width:99%;">
<div id="avlAndFareForm:j_idt480_body" class="rf-p-b ">
<ul id="tabul">
<div id="tabcontent">
<div id="c1" class="container-div">
<div id="j_idt382" class="rf-p ">
<div id="j_idt382_header" class="rf-p-hdr ">
<div id="j_idt382_body" class="rf-p-b ">
<table class="t1" cellspacing="0" cellpadding="4px">
<tbody>
<tr>
<tr>
<td style="text-align: left;padding-left: 1em;">
<td style="padding-top:3px" align="center">
GNWL203/WL105
<br/>
**<a id="17235-SL-GN-0" href="javascript:jpBook($('#17235-SL-GN-0'),'17235','HSRA','SRT','22-9-2017','SL','GN',3,false,0,0,'S');" tabindex="1">Book Now</a>**
</td>

Resources