I have a simple CRUD thymeleaf based html page, where I have a list of workers and worker details. Now I want to create, edit or delete a worker. For this actions I use a twitter bootstrap modal dialog.
This works fine, but I have a lot of duplication there, so I want to create a th:fragment which contains the form fields which are the same in details view, create view and edit view. Just the spring model attribute is different.
<div th:fragment="workerForm(formId, formAction, worker)">
<form th:id="${formId}" th:action="${formAction}" class="form-horizontal" method="post" role="form">
<div class="form-group">
<label for="inputGivenName" class="col-sm-2 control-label">Givenname</label>
<div class="col-sm-10">
<input id="inputGivenName" type="text" class="form-control" th:field="${worker.givenName}"/>
</div>
</div>
<div class="form-group">
<label for="inputName" class="col-sm-2 control-label">Name</label>
<div class="col-sm-10">
<input id="inputName" type="text" class="form-control" th:field="${worker.name}"/>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="checkbox">
<label>
<input type="checkbox" th:field="${worker.active}"/> Active
</label>
</div>
</div>
</div>
</form>
</div>
Now I want to include this fragment in the modal dialog ...
<div class="modal-body">
<div th:include="workerFragments :: workerForm(newWorkerForm, @{/worker/new}, ${newWorker})"></div>
</div>
Is it possible to pass in the model attribute newWorker as a paramter into the fragment and thymeleaf will use this instead of the ${worker}?
NewWorker is set in the spring action as:
....
model.addAttribute("newWorker", new WorkerDTO());
....
It is not possible with the above code. Here thymeleaf wants to resolve worker instead of the passed in newWorker. Should the parameter be in another format, or is it not possible for thymeleaf fragments to resolve this?
There are three basic ways to include content from a fragment: insert – inserts content inside the tag. replace – replaces the current tag with the tag defining the fragment. include – this is deprecated but it may still appear in a legacy code.
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 messages . This is a Spring EL expression.
Creating a layout You can also notice, that header and footer are included using Standard Thymeleaf Layout System. Content of this task/list view will be decorated by the elements of task/layout view. Please note layout:decorate="~{task/layout}" attribute in <html> element.
I resolved a similar issue by passing the name of the field into the fragment instead of passing the attribute itself. So from your include, you would write something like:
<div class="modal-body">
<div th:include="workerFragments :: workerForm(newWorkerForm, @{/worker/new}, 'newWorker')"></div>
</div>
And then with your fragment, you would have the same "worker" fragment variable, but you would have to use the preprocessor to evaluate the variable in the fragment and then you can use the form-backing syntax to use th:field. Your references in your fragment change from ${worker} to *{__${worker}__}
<div th:fragment="workerForm(formId, formAction, worker)">
<form th:id="${formId}" th:action="${formAction}" class="form-horizontal" method="post" role="form">
<div class="form-group">
<label for="inputGivenName" class="col-sm-2 control-label">Givenname</label>
<div class="col-sm-10">
<input id="inputGivenName" type="text" class="form-control" th:field="*{__${worker}__.givenName}"/>
</div>
</div>
<div class="form-group">
<label for="inputName" class="col-sm-2 control-label">Name</label>
<div class="col-sm-10">
<input id="inputName" type="text" class="form-control" th:field="*{__${worker}__.name}"/>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="checkbox">
<label>
<input type="checkbox" th:field="*{__${worker}__.active}"/> Active
</label>
</div>
</div>
</div>
</form>
</div>
There is a with
attribute where you can pass in parameters into your view so you're not dependent on the parent. For example,
If you are calling workerForm
and you wanted to pass in a parameter called newWorker
with the value of newWorkerValue
, then you would do the following:
<div class="modal-body">
<div th:include="workerFragments :: workerForm" th:with="newWorker=${newWorkerValue}"></div>
</div>
So within your workerForm template, you can reference newWorker
. For additional information, check out 8.2 Parameterizable fragment signatures
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With