Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Thymeleaf list within list input

I have a data structure like this :-

WorkHistory{
    List<Jobs> jobs;
}
Jobs{
   List<String> workDoneSentences;
}

Basically, I am trying to collect all past jobs where a person has worked and the work that he hsa done there. So it is a list of list structure. I would like to know how can we handle this in UI for Thymeleaf/Spring mvc.

I am trying to create UI as shown in the images. There is a table to enter data. To enter workDoneSentence i would like to open another modal. And the list of sentences should be bound to correct job index. enter image description here

enter image description here

Work Done opens the modal to take input the list of work done sentences.

The html code that I have for this as follows :-

                                            <tbody>
                                            <tr id='addr_work0' th:each="workRow, rowStat : *{workHistoryDetails.allWorkHistoryData}">
                                                <td th:text="${rowStat.index + 1}"></td>
                                                <td><input type="text" name='work_name0'
                                                    placeholder='Company Name'  class="form-control" th:field="*{workHistoryDetails.allWorkHistoryData[__${rowStat.index}__].companyName}"/></td>
                                                <td><input type="text" name='work_city0'
                                                    placeholder='Company city' class="form-control" th:field="*{workHistoryDetails.allWorkHistoryData[__${rowStat.index}__].city}"/></td>
                                                <td><input type="text" name='work_title0'
                                                    placeholder='Job Title' class="form-control" th:field="*{workHistoryDetails.allWorkHistoryData[__${rowStat.index}__].jobTitle}"/></td>
                                                <td><input name="is_current0" type="checkbox"
                                                    value="" class="form-control" style="text-align: center;" th:field="*{workHistoryDetails.allWorkHistoryData[__${rowStat.index}__].currentJob}">
                                                </td>
                                                <td><input type="text" name='work_start0'
                                                    placeholder='Start Date' class="form-control" th:field="*{workHistoryDetails.allWorkHistoryData[__${rowStat.index}__].startDate}"/></td>
                                                <td><input type="text" name='work_end0'
                                                    placeholder='End Date' class="form-control" th:field="*{workHistoryDetails.allWorkHistoryData[__${rowStat.index}__].endDate}"/></td>
                                                <td><a class="btn btn-primary btn-md" id="work_done0"
                                                    name="work_done0">Work done</a></td>


                                            </tr>
                                            <tr id='addr_work1'></tr>
                                        </tbody>

I am not sure how I can link the workDone input. Please suggest. Thanks!

like image 200
jetty Avatar asked Jan 29 '18 11:01

jetty


2 Answers

I've tried as follows and it works properly.

Template: Create unique "modal" for each job. (work-list.html)

<form method="post" action="#" th:action="@{/work-list}" th:object="${workHistoryDetails}">
 <table>
  <thead>
   <tr>
    <th>
      <button type="submit" name="addRow" th:text="'Add Row'">Add row</button>
    </th>
   </tr>
  </thead>
  <tbody>
   <tr id='addr_work0' th:each="workRow, rowStat : *{jobs}">
    <td th:text="${rowStat.index + 1}"></td>
      <td><input type="text" 
                placeholder='Company Name'  class="form-control" th:field="*{jobs[__${rowStat.index}__].companyName}"/></td>
      <td><input type="text" 
                placeholder='Company city' class="form-control" th:field="*{jobs[__${rowStat.index}__].city}"/></td>


      <td><button type="button" class="btn btn-primary" data-toggle="modal" th:attr="data-target='#myModal'+${rowStat.index}" >Open modal</button></td>

      <!-- The Modal -->
      <div class="modal fade" th:id="'myModal'+${rowStat.index}">
       <div class="modal-dialog">
        <div class="modal-content">

         <!-- Modal Header -->
         <div class="modal-header">
           <h4 class="modal-title">Modal Heading</h4>
           <button type="button" class="close" data-dismiss="modal">&times;</button>
         </div>

         <!-- Modal body -->
         <div class="modal-body">
           <input type="text"
                placeholder='Company Name'  class="form-control" th:field="*{jobs[__${rowStat.index}__].workDoneSentences[0]}"/>
           <input type="text" 
                placeholder='Company city' class="form-control" th:field="*{jobs[__${rowStat.index}__].workDoneSentences[1]}"/>
         </div>

         <!-- Modal footer -->
         <div class="modal-footer">
           <button type="button" class="btn btn-danger" data-dismiss="modal">Close</button>
         </div>

        </div>
       </div>
      </div>
    </tr>
   </tbody>
  </table>
 <input type="submit" name="submit" value="Add" class="btn btn-danger" />
</form> 

Controller:

@ModelAttribute("workHistoryDetails")
public WorkHistory populateWorkHistories() {
    return this.workHistory.getAllHistoryDetail();
}

@Autowired
WorkHistoryService workHistory;

@GetMapping("/work-list")
public String greeting(final WorkHistory workHistoryDetails) {
    return "work-list";
}

@RequestMapping(value="/work-list",method=RequestMethod.POST)
public String create(final WorkHistory workHistoryDetails) {

   this.workHistory.setJobs(workHistoryDetails);
   return "work-list";
}

// for adding new row job to jobs list
@RequestMapping(value="/work-list", params={"addRow"})
public String addRow(final WorkHistory workHistoryDetails, Model model) {

    Jobs jobRow = new Jobs("","",new ArrayList<>());
    workHistoryDetails.getJobs().add(jobRow);
    model.addAttribute("workHistoryDetails", workHistoryDetails);
    return "work-list";
}

Service: Just for the sake of testing:

@Service
public class WorkHistoryService {

    static WorkHistory workHistoryDetails =new WorkHistory();
    static{
        List<String> workDones = new ArrayList<>();
        workDones.add("angular");
        workDones.add("description");
        List<String> workDones1 = new ArrayList<>();
        workDones1.add("java,c++");
        workDones1.add("description also");

        Jobs job1 = new Jobs("Twitter", "USA",workDones); 
        Jobs job2 = new Jobs("Microsoft", "USA",workDones1);
        List<Jobs> jobList = new ArrayList<>();
        jobList.add(job1);
        jobList.add(job2);
        workHistoryDetails.setJobs(jobList);
    }

    public WorkHistory getAllHistoryDetail(){

        return workHistoryDetails;
    }

    public void setJobs(WorkHistory workHistory){
        workHistoryDetails.getJobs().clear();
        List<Jobs> jobs = workHistory.getJobs();
        for (Jobs job : jobs) {
            workHistoryDetails.getJobs().add(job);
        }
    }
}

Jobs domain:

public class Jobs {
   private String companyName;
   private String city;
   private List<String> workDoneSentences;
    //default constructor important!   
    public Jobs() {
    super();
    }
   //setter getter
}

I hope it helps you.

like image 178
Gurkan Yesilyurt Avatar answered Oct 20 '22 00:10

Gurkan Yesilyurt


<td><a class="btn btn-primary btn-md" id="work_done0" name="work_done0"  th:href="Modal">Work done</a></td>

The Modal part should be configured per your own demand

like image 42
Berhanu Tarekegn Avatar answered Oct 19 '22 23:10

Berhanu Tarekegn