Reputation: 61
In the post method, it is returning the error: Validation failed for object.
Some info: Incident has 1 or most exhibits.
My ExhibitList class
public class ExhibitList {
private List<Exhibit> exhibits;
public List<Exhibit> getExhibits() {
return exhibits;
}
public void setExhibits(List<Exhibit> exhibits) {
this.exhibits = exhibits;
}
public void addExhibit(Exhibit exhibit) {
this.exhibits.add(exhibit);
}
}
My Incident Controller
@RequestMapping(value = "")
public String incidentRegister(Model model, Principal principal, @PathParam("id") Long id) {
Incident incident = new Incident();
model.addAttribute("incident", incident);
ExhibitList exhibitList = new ExhibitList();
model.addAttribute("exhibitList", exhibitList);
return "incidentRegister";
}
@RequestMapping(value = "/register", method = RequestMethod.POST)
public String incidentRegisterPost(@ModelAttribute("exhibitList") ExhibitList exhibitList,
@ModelAttribute("incident") Incident incident, @ModelAttribute("exhibit") Exhibit exhibit) throws Exception {
System.out.println("Size: " + exhibitList.getExhibits().size());
for (Exhibit exhibit2 : exhibitList.getExhibits()) {
System.out.println("Description: " + exhibit2.getExhibitDescription());
System.out.println("Marking: " + exhibit2.getExhibitMarking());
System.out.println("Remarks: " + exhibit2.getExhibitRemarks());
}
return "incidentDetail";
}
My view
<div class="container main">
<form th:action="@{/incidentRegister/register}" method="post"
id="formIncidentRegister" onsubmit="return confirm('Are you sure you want to register this Incident?')">
<h3>Exhibit Details</h3>
<div id="exhibitList">
<div class="form-row item"
th:each="exhibit, status : ${exhibitList.exhibits}">
<div class="form-group col-md-4">
<label for="location">Description</label> <input
th:field="*{exhibits[__${status.index}__].exhibitDescription}"
type="text" class="form-control" />
</div>
<div class="form-group col-md-4">
<label for="location">Marking</label> <input
th:field="*{exhibits[__${status.index}__].exhibitMarking}"
type="text" class="form-control" />
</div>
<div class="form-group col-md-4">
<label for="location">Remarks</label> <input
th:field="*{exhibits[__${status.index}__].exhibitRemarks}"
type="text" class="form-control" />
</div>
</div>
</div>
<div class="form-row">
<div class="col">
<button type="button" class="btn btn-primary" onclick="addRow()">Add
Exhibit</button>
</div>
</div>
</form>
</div>
<script type="text/javascript">
let addRow = function() {
let listName = 'exhibits';
let fieldsNames = [ 'exhibitDescription', 'exhibitMarking',
'exhibitRemarks' ];
let rowIndex = document.querySelectorAll('.item').length;
let row = document.createElement('div');
row.classList.add('form-row', 'item');
fieldsNames.forEach((fieldName) => {
let col = document.createElement('div');
col.classList.add('form-group', 'col-md-4');
let label = document.createElement('label');
if(fieldName === 'exhibitDescription'){
label.innerHTML = 'Description';
} else if(fieldName === 'exhibitMarking'){
label.innerHTML = 'Marking';
} else{
label.innerHTML = 'Remarks';
}
let input = document.createElement('input');
input.type = 'text';
input.classList.add('form-control');
input.setAttribute('name', listName + '[' + rowIndex + ']' + fieldName);
col.appendChild(label);
col.appendChild(input);
row.appendChild(col);
});
document.getElementById('exhibitList').appendChild(row);
};
//<![CDATA[
$(document).ready(function() {
});
//]]>
</script>
It returns an error 'Validation failed for object='exhibitList'. Error count: 3'. How do i go about retrieving the values of exhibit(s) from the list.
Thank you in advance.
Update 1
My Controller
@RequestMapping(value = "")
public String incidentRegister(Model model, Principal principal, @PathParam("id") Long id) {
...
List<Exhibit> exhibitList = new ArrayList<>();
ExhibitsCreationDto exhibitForm = new ExhibitsCreationDto(exhibitList);
exhibitForm.addExhibit(new Exhibit());
model.addAttribute("form", exhibitForm);
}
My View
<form th:action="@{/incidentRegister/register}" method="post"
th:object="${form}" id="formIncidentRegister"
onsubmit="return confirm('Are you sure you want to register this Incident?')">
<h3>Exhibit Details</h3>
<div id="exhibitList">
<div class="form-row item"
th:each="exhibit, status : ${form.exhibits}">
<div class="form-group col-md-4">
<label for="location">Description</label> <input
th:field="*{exhibits[__${status.index}__].exhibitDescription}"
type="text" class="form-control" required="required"/>
</div>
<div class="form-group col-md-4">
<label for="location">Marking</label> <input
th:field="*{exhibits[__${status.index}__].exhibitMarking}"
type="text" class="form-control" required="required"/>
</div>
<div class="form-group col-md-4">
<label for="location">Remarks</label> <input
th:field="*{exhibits[__${status.index}__].exhibitRemarks}"
type="text" class="form-control" required="required"/>
</div>
</div>
</div>
<div class="form-row">
<div class="col">
<button type="button" class="btn btn-primary" onclick="addRow()">Add
Exhibit</button>
</div>
</div>
<p></p>
<div class="form-group ">
<button type="submit"
class="btn btn-primary btn-lg btn-block login-button">Register</button>
</div>
<hr />
<div class="form-group ">
<a class="btn btn-info btn-lg btn-block login-button"
th:href="@{/incidentQuery}">Cancel</a>
</div>
</form>
<script type="text/javascript">
...
let addRow = function() {
let listName = 'exhibits';
let fieldsNames = [ 'exhibitDescription', 'exhibitMarking',
'exhibitRemarks' ];
let rowIndex = document.querySelectorAll('.item').length;
let row = document.createElement('div');
row.classList.add('form-row', 'item');
fieldsNames.forEach((fieldName) => {
let col = document.createElement('div');
col.classList.add('form-group', 'col-md-4');
let label = document.createElement('label');
if(fieldName === 'exhibitDescription'){
label.innerHTML = 'Description';
} else if(fieldName === 'exhibitMarking'){
label.innerHTML = 'Marking';
} else{
label.innerHTML = 'Remarks';
}
let input = document.createElement('input');
input.type = 'text';
input.classList.add('form-control');
input.id = listName + rowIndex + '.' + fieldName;
input.setAttribute('name', listName + '[' + rowIndex + ']' + fieldName);
col.appendChild(label);
col.appendChild(input);
row.appendChild(col);
});
document.getElementById('exhibitList').appendChild(row);
};
</script>
Upvotes: 0
Views: 757
Reputation: 874
add th:object="${exhibitList}"
in your form tag and modify your controller like this as you don't have any constructor in your class. So when you are initializing ExhibitList
class, all of its attributes are null as well as the list too. And you can't get an index of a list which is null.
ExhibitList exhibitList = new ExhibitList();
List<Exhibit> itemList= new ArrayList<>();
exhibitList.setsetExhibits(itemList);
model.addAttribute("exhibitList", exhibitList);
@RequestMapping(value = "/register", method = RequestMethod.POST)
public String incidentRegisterPost(@ModelAttribute("exhibitList") ExhibitList exhibitList,BindingResult bindingResult) throws Exception {
System.out.println("Size: " + exhibitList.getExhibits().size());
// others
return "incidentDetail";
}
Upvotes: 1