The Case: I've an Organization Object. It has a list of Department Objects, and each Department has a list of Employee Objects.
In JSP, I have a checkbox list that binds a check box to an employee object (deep down 2 hierarchies. That is Organization->Department->Employee).
<input type="checkbox" name="adminDepartmentList[${status.index}].employeeList" value="${employee.firstName}"> <c:out value="${employee.firstName}" /><br>
As you can see:
adminDepartmentList[0].employeeList --> John
adminDepartmentList[2].employeeList --> Rose
The binding is good. After form is submitted, in the controller, I can loop over admin departmentList and find all departments created and find the employees that were created due to the checkbox selection.
The Issue :( The departments are created with null names and non-null employeeList. I cannot find the names of department to which the employeeList belongs :( So how can I pass some department-name so the name gets injected to the department (as it is being created) just like how the ".employeeList" is getting injected to the department.
The Details: To give you the details of my work:
An Organization class has two lists of Departments. A Department class has a list of Employees. Employee has first and last name and hourToWork.
public class Organization{
private long id;
private String name;
private List<Department> adminDepartmentList; //n admin departments
private List<Department> employeeDepartmentList //m employee departments
// default constructor and all getters and setters
}
public class Department{
private long id;
private String name;
private List<Employee> employeeList; //k employees
//default constructor and all getters and setters
}
public class Employee{
private long id;
private String firstName;
private String lastName;
private int hoursToWork; // to be filled from Spring MVC form
//default contructor and all getters and setters
}
The list of Departments comes from an API. And all Employees of that department comes from another API.
I am writing a client that enables users to create "customized organizations" by first selecting the departments they are interested in and then for each department that was selected, the user selects a subset of employees from all employees related to that department.
So I have 3 JSP forms:
Organization form (organization.jsp): input field for the name of the organization and a check box list of all departments. User can select a set of Department for the new organization that's being created.
<form:form name='fs' action="department.htm" method='POST' commandName="organization">
Organization Name:
<input type="text" name="name" >
<!-- ============================================================== -->
Departments:<br> Select admin-departments you want.
<div class="checkbox-list">
<%-- Size :<c:out value="${organization.adminDepartmentList.size}"/> --%>
<c:forEach var="i" varStatus="status" items="${organization.adminDepartmentList}">
<input type="checkbox" name="adminDepartmentList" value="${i.name}"> <c:out value="${i.name}" /><br>
</c:forEach>
</div>
<!-- ============================================================== -->
Departments:<br> Select employee-departments you want.
<div class="checkbox-list">
<c:forEach var="i" varStatus="status" items="${organization.employeeDepartmentList}">
<input type="checkbox" name="employeeDepartmentList" value="${i.name}"> <c:out value="${i.name}" /><br>
</c:forEach>
</div>
<button type="submit" class="btn btn-lg btn-primary btn-block">Next Step</button>
</form:form>
Department form (department.jsp): For each of the departments that were selected, this show a check box list of employees to be selected for the department.
<form:form name='f' action="employee.htm" method='POST' commandName="organization">
Organization Name: <c:out value="${organization.name}" /><br>
Select Employees you want for your new Departments.
Admin Departments:<br>
<c:forEach var="department" varStatus="status" items="${organization.adminDepartmentList}">
______Dept: <c:out value="${department.name}" /><br>
<div class="checkbox-list">
<c:forEach var="employee" varStatus="status" items="${department.employeeList}">
<input type="checkbox" name="adminDepartmentList[${status.index}].employeeList" value="${employee.firstName}"> <c:out value="${employee.firstName}" /><br>
</c:forEach>
</div>
</c:forEach>
Employee Departments:<br>
<c:forEach var="department" varStatus="status" items="${organization.employeeDepartmentList}">
______Dept: <c:out value="${department.name}" /><br>
<div class="checkbox-list">
<c:forEach var="employee" varStatus="status" items="${department.employeeList}">
<input type="checkbox" name="employeeDepartmentList[${status.index}].employeeList" value="${employee.firstName}"> <c:out value="${employee.firstName}" /><br>
</c:forEach>
</div>
</c:forEach>
<button type="submit" class="btn btn-lg btn-primary btn-block">Next Step</button>
</form:form>
Employee form (employee.jsp): For each of the employee that was selected in Department Form, this shows the employee name and a field to enter the hours that will be assigned to that employee.
The Employee Controller (the one that's getting null department-name)
@RequestMapping(value = "/employee", method = RequestMethod.POST)
public String product_post(@ModelAttribute("organization") Organization organization, HttpServletRequest request,
HttpServletResponse response, BindingResult result, ModelMap model) {
System.out.println("=========== POST Employee CONTROLLER===============");
//STEP 1. show me which employees are selected for each admin department.
List<Department> adminDepartments = organization.getAdminDepartmentList();
for(Department dept: adminDepartments){
System.out.println("Admin Dept name::: " + dept.getName()); //<-----------Name Comes as null :(
List<Employee> employeeList = dept.getEmployeeList();
for(Employee emp: employeeList){
System.out.println("Employee::"+ emp.getFirstName());
}
}
//STEP 2. show me which employees are selected for each employee department.
List<Department> employeeDepartments = organization.getEmployeeDepartmentList();
for(Department dept: employeeDepartments){
System.out.println("Employee Dept name::: " + dept.getName()); //<----------Name Comes as null :(
List<Employee> employeeList = dept.getEmployeeList();
for(Employee emp: employeeList){
System.out.println("Employee::"+ emp.getFirstName());
}
}
model.addAttribute("organization", organization);
return "employee";
}
The Known: I understand why department.name is not being injected, but I'm not sure how to solve it. How do I inject the department name from the outer loop to the inner loop that runs over the employee list in the below c:foreach? Or how to somehow bind it to each employee. I'm suspecting it's here:
Admin Departments:<br>
<c:forEach var="department" varStatus="status" items="${organization.adminDepartmentList}">
______Dept: <c:out value="${department.name}" /><br>
<div class="checkbox-list">
<c:forEach var="employee" varStatus="status" items="${department.employeeList}">
<input type="checkbox" name="adminDepartmentList[${status.index}].employeeList" value="${employee.firstName}"> <c:out value="${employee.firstName}" /><br>
</c:forEach>
</div>
</c:forEach>
I tried hidden input to help create named departments but it didn't help.
The Credits:
Thanks so much for ur cooperation :)
For simplicity, assume FirstName for employee is unique. And department.name is also unique. Thanks.