Is there any reference available for DOJO UI with Spring MVC for CRUD operations
DOJO form submit yields ResponseMethod.POST not supported when using RequestMapping annotation on Spring Controller?
Providing partial snippet for better understanding
Annotated Spring Controller code(partial):
#RequestMapping(
value = "/create",
headers="Accept=application/json",
method=RequestMethod.POST)
public #ResponseBody Map<String, ? extends Object> create(#RequestParam() Object data)
throws Exception {
//Request processing
}
Dojo Code(partial):
dojo.rawXhrPost({
postData: dojo.formToJson("contactFormDialog"),
handleAs: 'json',
headers: { "Content-Type": "application/json"},
load:testLoadfunction,
error:testError
});
Form code:
<form id="contactFormDialog" action="create.action" method="post">
<table>
<tr>
<td><label for="loc">Name: </label></td>
<td><input dojotype="dijit.form.TextBox" type="text"
name="name" id="name"></td>
</tr>
<tr>
<td><label for="date">Phone: </label></td>
<td><input dojotype="dijit.form.NumberTextBox" type="text"
name="phone" id="phone"></td>
</tr>
</table>
<div class="dijitDialogPaneActionBar">
<button dojotype="dijit.form.Button" id="submit" type="submit"
label="Submit" onClick="testFormAction"></button>
<button dojotype="dijit.form.Button" id="cancel" type="button"
onClick="alert('no');">Cancel
</button>
</div>
</form>
Related
I have 2 entities - Invoice and InvoiceProduct. Invoice class has a field List of InvoiceProduct because Invoice has #OneToMany mapping on InvoiceProduct.
I want to send the List of InvoiceProduct to Thymeleaf with with editable fields with a Submit button. When I click on Submit button, the new edited List should be returned to the controller. However, I am able to send the list to the view, but when I send the edited list to controller, it is being passed as 'null'.
update-invoice.html:
<form action="#" th:action="#{/api/invoice/saveInvoice}" th:object="${invoice}" method="POST">
<table class="table table-bordered table-striped">
<thead class="thead-dark">
<tr>
<th>PID</th>
<th>Quantity</th>
<th>Unit Price</th>
</tr>
</thead>
<tbody>
<tr th:each="temp : ${invoice?.invoiceProducts}" >
<td><input name="invoiceProducts[${tempStat.index}].productId" th:value="${temp.productId}"/></td>
<td><input name="invoiceProducts[${tempStat.index}].quantity" th:value="${temp.quantity}"/></td>
<td><input name="invoiceProducts[${tempStat.index}].price" th:value="${temp.price}"/></td>
</tr>
</tbody>
</table>
<button type="submit" class="btn btn-info col-2">Submit</button>
</form>
InvoiceController:
#PostMapping("/saveInvoice")
public String postInvoice(#ModelAttribute("invoice") Invoice invoice) {
logger.info("invoice products " + invoice.getInvoiceProducts());
return "dummy";
}
What else do I need to add so that my update-invoice.html passes the list to my controller ?
You can try something like below as an example for thymleaf:-
<form method="post" th:action="#{/users/}" th:object="${userInfo}" class="col card p-3 mb-5">
<div class="form-group">
<label for="firstName">First Name</label>
<input id="firstName" placeholder="Enter First Name" required type="text" th:field="*{firstName}"
class="form-control"/>
</div>
<div class="form-group">
<label for="lastName">Last Name</label>
<input id="lastName" placeholder="Enter Last Name" required type="text" th:field="*{lastName}"
class="form-control"/>
</div>
<div class="form-group">
<label for="role">Role</label>
<select id="role" required th:field="*{role}" class="form-control ">
<option value="" hidden>Select a role</option>
<option th:each="role : ${T(com.springhow.examples.springboot.thymeleaf.domain.entities.Role).values()}"
th:value="${role}"
th:text="${role}">
</option>
</select>
</div>
<input type="submit" class="btn btn-primary" value="Create User">
</form>
and into Controller:-
#RequestMapping(value = "/", method = RequestMethod.POST)
public String createUser(Model model, #ModelAttribute UserInfo userInfo) {
UserInfo user = userService.createUser(userInfo);
return "redirect:/users/";
}
I have a template which represents a list of notes that are retrieved from a database
<tr th:unless="${#lists.isEmpty(allNotes)}"
th:each="note : ${allNotes}">
<td>
<form action="#" method="POST" th:action="#{/home/editNote}"
th:object="${note}">
<input type="hidden" id="noteId" name="noteId" th:value="*{noteId}">
<button type="button" class="btn btn-success"
onclick="editNoteModal('updateNote', this.getAttribute('data-noteId'),
this.getAttribute('data-noteTitle'),
this.getAttribute('data-noteDescription'))">Edit
</button>
</form>
<form action="#" method="POST" th:action="#{/home/deleteNote}">
<input type="hidden" name="noteId" th:value="*{note.noteId}">
<a class="btn btn-danger">Delete</a>
</form>
</td>
<th scope="row" th:text="${note.noteTitle}">Example Note Title</th>
<td th:text="${note.noteDescription}">Example Note Description</td>
</form>
</tr>
</tbody>
In the GUI It looks like this
This is my modal code which should open after I click on the edit button:
<div class="modal fade" id="editNoteModal" tabindex="-1" role="dialog" aria-labelledby="noteModalLabel"
aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="editnoteModalLabel">Note</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div class="form-group">
<label for="note-title" class="col-form-label">Title</label>
<input type="text" name="noteTitle" class="form-control" id="editNoteTitle"
maxlength="20" required>
</div>
<div class="form-group">
<label for="note-description" class="col-form-label">Description</label>
<textarea class="form-control" name="noteDescription" id="editNoteDescription"
rows="5" maxlength="1000" required></textarea>
</div>
<button id="editNoteSubmit" type="submit" class="d-none"></button>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary" onclick="$('#editNoteModal').click();">
Save
changes
</button>
</div>
</div>
</div>
</div>
</div>
In the GUI it looks like this:
I want to be able to edit given note and then send the edited id to the controller so I can update this change within the database. I have correct database logic for the update, I just don't know the way how to send the given notes id and changed information to my controller.
#PostMapping("/editNote")
public String editNote(#ModelAttribute(value = "note") Note note,
#ModelAttribute(value = "noteId") NoteIdModel noteIdModel, Model model,
Authentication authentication) {
System.out.println("noteid " + note.getNoteId());
System.out.println("noteidHidden " + noteIdModel.getNoteIdHidden());
System.out.println("notedesc" + note.getNoteDescription());
noteService.editNote(note, authentication);
return "result";
}
However, the incoming noteId is null. I have checked the database and the note with correct id is indeed in the database and is also retrieved from the database. It's just not sent to the controller.
Try this one:
HTML fragment
<tr th:unless="${#lists.isEmpty(allNotes)}"
th:each="note : ${allNotes}">
<td>
<button type="button" class="btn btn-success"
th:data-noteId="${note.noteId}"
th:data-noteTitle="${note.noteTitle}"
th:data-noteDescription="${note.noteDescription}"
onclick="editNoteModal('updateNote', this.getAttribute('data-noteId'),this.getAttribute('data-noteTitle'),this.getAttribute('data-noteDescription'))">Edit
</button><br/>
<a class="btn btn-danger">Delete</a>
</td>
<td scope="row" th:text="${note.noteTitle}"></td>
<td th:text="${note.noteDescription}"></td>
</tr>
JS fragment
/**
* Fill edit modal with current information
*/
function editNoteModal(modal, noteId, noteTitle, noteDescription) {
$('#editnoteModalLabel').text("Note " + noteId);
$('#editNoteId').val(noteId);
$('#editNoteTitle').val(noteTitle);
$('#editNoteDescription').val(noteDescription);
$('#editNoteModal').modal("show");
}
/**
* Save to backend edit information
*/
function save() {
var noteId = $('#editNoteId').val();
var noteTitle = $('#editNoteTitle').val();
var noteDescription = $('#editNoteDescription').val();
$.ajax({
url : "./editNote",
method : "POST",
headers : {
'Content-Type' : 'application/json'
},
data : JSON.stringify({
noteId : noteId,
noteTitle : noteTitle,
noteDescription : noteDescription
}),
success : function(result) {
$('#editNoteModal').modal("hide");
alert(result);
}
})
}
Backend
#PostMapping(path = "/editNote", consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<String> editNote(#RequestBody Note note) {
System.out.println("noteid " + note.getNoteId());
System.out.println("noteidTitle " + note.getNoteTitle());
System.out.println("notedesc" + note.getNoteDescription());
//Save in database
return ResponseEntity.ok("OK");
}
This is how I did while I was trying to pass the id to open a modal by finding details using that id:
<a href="#" class="btn btn-sm btn-primary"
th:data-parameter1="${user.useruuid}"
onclick="openUserModal(this.getAttribute('data-parameter1'));">Details</a>
And then somewhere in your JavaScript, you can something (similar) like this:
<script type="text/javascript" th:fragment="includeModalScript">
function openUserModal(id) {
$.ajax({
url: "/findOnebyId?id="+ id,
success: function(data){
alert(id);
.......
</script>
And my controller looked like this:
#GetMapping("/findOnebyId")
#ResponseBody
public AppUser findOneByUUID(String id) {
....
}
You can take a look here, here and here for a working demo similar to your issue/requirement.
What I want is when I click id=addUnitCharge button, id = proName and id=proAge should add in to id=property_type_tbl body. And when I click submit button all values should assign to(id=code and id=school as values and id=property_type_tbl values to unitCharge list)
This is my PlAccount class
public class PlAccount{
private String code;
private String school;
private List<UnitCharge> unitCharge;
//Getters and Setters
}
UnitCharge class
public class UnitCharge{
private String proName;
private String proAge;
//Getters and Setters
}
My Controller class
#GetMapping(path = {"/product/add")
public String index(Model model) {
model.addAttribute("type", PlAccount.builder().build());
return "/loan/product/add";
}
#PostMapping("/coopmis/waterTariff/product/add")
public String save(#Valid PlAccount plAccount, BindingResult result){
plAccountService.savePlAccount(plAccount);
}
My html
<form method="post" action="/product/add" th:object="${type}">
<input type="number" id="code" class="form-control" th:name="code">
<input type="number" id="school" class="form-control" th:name="school">
//On button click below Items should add to `property_type_tbl` table.
<input type="number" id="proName" class="form-control" th:name="proName">
<input type="number" id="proAge" class="form-control" th:name="proAge">
<button type="button" class="btn btn-success" id="addUnitCharge" onclick="addRowPropertyType()"
th:text="#{add}">Add
</button>
<div class="form-group">
<button type="submit" class="btn btn-success " th:text="#{submit}">Submit</button>
</div>
</form>
<div class="form-group">
<table class="table table-striped id="property_type_tbl">
<thead>
<tr>
<th th:text="#{proName}"></th>
<th th:text="#{proAge}"></th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
Highly appreciate your kind support.
I have a table filled with tasks:
<table class="table" id="tasksTable">
<thead class="thead-inverse">
<tr>
<th>ID</th>
<th>Title</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr data-th-each="task : ${tasks}">
<td data-th-text="${task.id}">Task ID</td>
<td data-th-text="${task.title}">Task Title</td>
<td><a th:href="#{/tasks/delete/{id}(id=${task.id})}"
class="btn btn-danger">Delete</a> -
<button class="btn btn-warning" data-toggle="modal"
data-th-id="${task.id}" data-target="#updateTaskModal">Update</button></td>
</tr>
</tbody>
</table>
The list is sent from a controller like this:
#GetMapping(path = "/")
public String getAllUsersView(Model model) {
List<User> users = new ArrayList<>();
List<Task> tasks = new ArrayList<>();
User user = new User();
Task task = new Task();
userRepository.findAll().forEach(users::add);
taskRepository.findAll().forEach(tasks::add);
model.addAttribute("users", users);
model.addAttribute("tasks", tasks);
model.addAttribute("user", user);
model.addAttribute("task", task);
return "view";
}
I would like to pick one task from the table, and send it to a modal. For instance, let's say I have 10 tasks. I want to pick task #5 and be able to update it. When I click Update, I can open a modal, but I don't know how to fill the form with the data from that specific task, it all comes blank.
This is my modal:
<div id="updateTaskModal" class="modal fade" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Update Task</h4>
</div>
<div class="modal-body">
<form id="updateNewTask" action="#" th:action="#{/tasks/update}"
th:object="${task}" method="put">
<input type="text" class="form-control" name="title" id="title"
th:field="*{title}" placeholder="Task Title" />
<hr />
<button type="button" class="btn btn-danger" data-dismiss="modal">Cancel</button>
<button type="submit" class="btn btn-success pull-right">Update</button>
</form>
</div>
</div>
</div>
</div>
What would be the best practice to achieve this? Is it possible to send the entire object thru a button? If not, how can I load my object into the modal? I can retrieve a JSON version of the object via /tasks/{taskId}, but I don't know how to call it from the modal.
You can load content into existing modal with Javascript. "Best" way to to this is by rendering your object on server into some HTML with thymleaf and then fetching this response via Ajax and injecting into your modal box into some div tag.
I have a table showing testResults using thymeleaf template -
<tr th:each="testResult,iterationStatus : ${testResults}">
<td th:text="${iterationStatus.count}">1</td>
<td th:text="${testResult.name}">DOMAIN</td>
<td th:text="${testResult.length}">PROCESS</td>
<td>
<form ACTION="#" th:action="#{/deleteName}" th:object="${testResult}" method="POST">
<input type="hidden" th:field="*{name}"/>
<input type="hidden" th:field="*{length}"/>
<button type="submit">submit</button>
</form>
</td>
</tr>
name and length are showing fine in the html, but when i submit the form, controller gets name and length as empty values.
What i am doing wrong in assigning the values....
below is controller method that gets invoked -
#RequestMapping(method= RequestMethod.POST, value = "/deleteName")
public String deleteName(#Valid #ModelAttribute("testResult") TestResult testResult, BindingResult bindingResult, Model model, HttpServletRequest request) {
System.out.println(testResult.toString());
return "/";
}
output once i submit the form -
TestResult [name=, length=, xyz=null]
I couldn't get th:field to work inside a th:object, like you're doing here. However, if I stop using th:field, and use th:value instead, the form submits successfully.
<tr th:each="testResult : ${testResults}">
<td th:text="${testResult.name}">DOMAIN</td>
<td th:text="${testResult.length}">PROCESS</td>
<td>
<form ACTION="#" th:action="#{/deleteName}" method="POST">
<input type="hidden" name="name" th:value="${testResult.name}"/>
<input type="hidden" name="length" th:value="${testResult.length}"/>
<button type="submit">submit</button>
</form>
</td>
</tr>