Reputation: 1442
thymeleaf index.xhtml
-
EL1012E: Cannot index into a null value
<div class="mylist" th:each="row,rowStat : *{dataList}">
Folder: <span th:text="*{dataList[__${rowStat.index}__].folderName}" />
<div class="invalid-feedback"
th:if="${dataList[__${rowStat.index}__].folderName == appFolderName}">
Folder already exists. Please choose different folder name.
</div>
</div>
It is displaying the folderName but not validating th:if
and appFolderName
is a model attribute [dynamic value].
Upvotes: 0
Views: 919
Reputation: 21900
For the th:each="row,rowStat : *{dataList}"
iterator, I would simplify that code to this:
th:each="row : ${dataList}"
You can think of this as being broadly equivalent to the following Java for-loop:
List<DataItem> dataList = ...; // assume this is populated with DataItems
for (DataItem dataItem : dataList) {
System.out.println(dataItem.getFolderName());
}
In the above for-loop, we do not need to access the list by index - and the same is also true for the Thymeleaf syntax.
Thymeleaf lets you access fields in an object without needing to refer to the getter method.
So, now that we have our row
variable from th:each="row : ${dataList}"
, we can do this:
<div class="mylist" th:each="row,rowStat : *{dataList}">
Folder: <span th:text="${row.folderName}" />
<div class="invalid-feedback"
th:if="${row.folderName == appFolderName}">
Folder already exists. Please choose different folder name.
</div>
</div>
In the above code, you can see ${row.folderName}
- which means Thymeleaf will invoke the getFolderName()
method on the row
object. This relies on your object using JavaBean naming standards for your getters.
You can enhance the Thymeleaf th:each
processor by adding a second variable - which is what you do in your question: rowStat
:
th:each="row,rowStat : ${dataList}"
This gives you access to extra information about the status of the Thymeleaf iterator - you can see a list of all these extra data values here.
These extra values are no needed in your case. But they can be useful in other situations - for example if you want to identify the first
or last
record in the list, or all even
records, and so on.
Your example in the question uses the __${...}__
preprocessing syntax - which is very powerful and can be extremely useful. But again, it is not needed for your basic functionality.
Your example uses both ${...}
and *{...}
syntaxes to create Thymeleaf variables. It's important to understand the basic differences between them.
The difference is covered in the documentation describing the asterisk syntax:
the asterisk syntax evaluates expressions on selected objects rather than on the whole context. That is, as long as there is no selected object, the dollar and the asterisk syntaxes do exactly the same. And what is a selected object? The result of an expression using the th:object attribute.
The documentation has examples.
Finally, because you are using Spring (as per the tag in your question), then you are actually using Spring's dialect of Thymeleaf and SpEL - the Spring Expression Language.
This is broadly similar to the standard (OGNL) expression language used by the standard (non-Spring) Thymeleaf dialect - but it has several very useful enhancements.
One such enhancement is the safe navigation operator I mentioned in my comment:
${row?.folderName}
Here, the ?
will immediately return null
if row
is null
. Without this, you would get a null pointer exception when Thymeleaf attempted to invoke the getFolderName()
method on a null row
object.
Upvotes: 1