我試圖創建一個html「編輯/新建」頁面來編輯或添加新的發佈者。其中一個細節將是subPublishers的ArrayList。儘管如果發佈者沒有subPublishers,或者如果我添加新的發佈者,ArrayList可能是空的。Thymeleaf:空列表不顯示輸入字段
我的問題是與輸入字段。我試圖顯示的ArrayList如下...
<form id="publisherForm" th:object="${publisherForm}" th:action="@{/publishers/publishers-edit/}" method="post" class="form-horizontal">
<input type="hidden" th:field="*{id}" />
<div class="row">
<div class="col-sm-6 b-r">
<div class="form-group">
<label class="col-sm-3 control-label">Publisher name: </label>
<div class="col-sm-9">
<input th:field="*{publisherName}" type="text" class="form-control" th:maxlength="45"/>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">Description: </label>
<div class="col-sm-9">
<input th:field="*{description}" type="text" class="form-control" th:maxlength="200"/>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">Enabled: </label>
<div class="col-sm-9">
<input th:field="*{status}" value="ENABLED" type="checkbox"/>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">Website URL: </label>
<div class="col-sm-9">
<input th:field="*{websiteURL}" type="text" class="form-control" th:maxlength="50"/>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">Subpublishers: </label>
<div class="col-sm-9">
<div class="table-responsive">
<table class="table table-bordered table-striped">
<thead>
<th>
<button class="btn btn-white" type="submit" name="addRow">+</button>
</th>
</thead>
<tbody>
<tr th:each="subPublisher,stat : *{subPublishers}">
<td>
<input type="text" class="form-control" th:field="*{subPublishers[__${stat.index}__].name}" />
</td>
<td>
<button class="btn btn-white" type="submit" name="removeRow" th:value="${stat.index}">-</button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-6">
<div class="form-group">
<div class="col-sm-9 col-sm-offset-3">
<button class="btn btn-primary" type="submit">Save</button>
<a class="btn btn-white" th:href="@{/publishers}">Cancel</a>
</div>
</div>
</div>
</div>
</form>
控制器
@MenuController(value = "/publisher", item = Item.Publishers)
public class PublisherController {
private PublisherService publisherService;
private PublisherConverter publisherConverter;
private SubPublisherConverter subPublisherConverter;
public PublisherController(PublisherService publisherService, PublisherConverter publisherConverter, SubPublisherConverter subPublisherConverter) {
this.publisherService = publisherService;
this.publisherConverter = publisherConverter;
this.subPublisherConverter = subPublisherConverter;
}
@GetMapping
public String newPublisher(Model model) {
PublisherResource publisher = new PublisherResource();
publisher.setStatus(true);
publisher.setSubPublishers(new ArrayList<SubPublisherResource>());
return showPage(publisher, model);
}
protected String showPage(PublisherResource publisher, Model model) {
model.addAttribute("publisherForm", publisher);
return "publishers/publishers-edit";
}
@PostMapping
public String createPublisher(@ModelAttribute("publisherForm") @Validated PublisherResource resource, BindingResult result, Model model) {
if (result.hasErrors()) {
return showPage(resource, model);
}
return savePublisher(0, resource);
}
@GetMapping("/{publisherId}")
public String editPublisher(@PathVariable int publisherId, Model model) {
Publisher publisher = publisherService.getPublisher(publisherId);
PublisherResource res = publisherConverter.convert(publisher);
res.setSubPublishers(publisherService.getSubPublishers(publisher).stream()
.map(s -> subPublisherConverter.convert(s))
.collect(Collectors.toList())
);
return showPage(res, model);
}
@PostMapping("/{publisherId}")
public String updatePublisher(@PathVariable int publisherId, @ModelAttribute("publisherForm") @Validated PublisherResource resource, BindingResult result, Model model) {
if (result.hasErrors()) {
return showPage(resource, model);
}
return savePublisher(publisherId, resource);
}
protected String savePublisher(int publisherId, PublisherResource resource) {
Publisher publisher = populatePublisher(publisherId, resource);
List<SubPublisher> subPublishers = populateSubPublishers(resource);
if (publisherId == 0) {
publisherService.createPublisher(publisher, subPublishers);
} else {
publisherService.updatePublisher(publisher, subPublishers);
}
return "redirect:/publishers";
}
protected Publisher populatePublisher(int publisherId, PublisherResource resource) {
Publisher publisher = null;
if (publisherId == 0) {
publisher = new Publisher();
publisher.setTimeAdded(new Date());
} else {
publisher = publisherService.getPublisher(publisherId);
}
publisher.setPublisherName(resource.getPublisherName());
publisher.setDescription(resource.getDescription());
publisher.setStatus(resource.isStatus());
publisher.setWebsiteURL(resource.getWebsiteURL());
return publisher;
}
protected List<SubPublisher> populateSubPublishers(PublisherResource resource){
if(resource.getSubPublishers() != null){
return resource.getSubPublishers().stream()
.map(s -> {
SubPublisher subPublisher = new SubPublisher();
subPublisher.setName(s.getName());
return subPublisher;
})
.collect(Collectors.toList());
}
return Collections.emptyList();
}
@PostMapping(params={"addRow"})
public String addRow(final PublisherResource publisher, final BindingResult bindingResult, Model model) {
publisher.getSubPublishers().add(new SubPublisherResource());
return showPage(publisher, model);
}
@PostMapping(params={"removeRow"})
public String removeRow(final PublisherResource publisher, final BindingResult bindingResult,
final HttpServletRequest req, Model model) {
final Integer rowId = Integer.valueOf(req.getParameter("removeRow"));
publisher.getSubPublishers().remove(rowId.intValue());
return showPage(publisher, model);
}
}
PublisherResource
public class PublisherResource {
private int id;
private String publisherName;
private String description;
private boolean status;
private String websiteURL;
private List<SubPublisherResource> subPublishers = new ArrayList<>();
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getPublisherName() {
return publisherName;
}
public void setPublisherName(String publisherName) {
this.publisherName = publisherName;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public boolean isStatus() {
return status;
}
public void setStatus(boolean status) {
this.status = status;
}
public String getWebsiteURL() {
return websiteURL;
}
public void setWebsiteURL(String websiteURL) {
this.websiteURL = websiteURL;
}
public List<SubPublisherResource> getSubPublishers() {
return subPublishers;
}
public void setSubPublishers(List<SubPublisherResource> subPublishers) {
this.subPublishers = subPublishers;
}
}
我用exampel從thymeleaf文檔http://www.thymeleaf.org/doc/tutorials/2.1/thymeleafspring.html#dynamic-fields
問題是,當ArrayList爲空時,輸入字段不會顯示在頁面上!此外,當編輯發佈商擁有子發佈商時,如果我將其全部刪除,則會丟失輸入字段,並且我無法添加任何其他子發佈商。這幾乎無法添加子發佈者。
這是如何處理與Thymeleaf?
更新控制器
@MenuController(value = "/publisher", item = Item.Publishers)
public class PublisherController {
private PublisherResource publisherResource;
private PublisherService publisherService;
private PublisherConverter publisherConverter;
private SubPublisherConverter subPublisherConverter;
public PublisherController(PublisherResource publisherResource, PublisherService publisherService,
PublisherConverter publisherConverter, SubPublisherConverter subPublisherConverter) {
this.publisherResource = publisherResource;
this.publisherService = publisherService;
this.publisherConverter = publisherConverter;
this.subPublisherConverter = subPublisherConverter;
}
@GetMapping
public String newPublisher(Model model) {
PublisherResource publisher = new PublisherResource();
publisher.setStatus(true);
publisher.setSubPublishers(new ArrayList<SubPublisherResource>());
return showPage(publisher, model);
}
protected String showPage(PublisherResource publisher, Model model) {
model.addAttribute("publisherForm", publisher);
return "publishers/publishers-edit";
}
@PostMapping
public String createPublisher(@ModelAttribute("publisherForm") @Validated PublisherResource resource, BindingResult result, Model model) {
if (result.hasErrors()) {
return showPage(resource, model);
}
return savePublisher(0, resource);
}
@GetMapping
public String editPublisher(Model model) {
Publisher publisher = publisherService.getPublisher(publisherResource.getId());
PublisherResource res = publisherConverter.convert(publisher);
res.setSubPublishers(publisherService.getSubPublishers(publisher).stream()
.map(s -> subPublisherConverter.convert(s))
.collect(Collectors.toList())
);
return showPage(res, model);
}
@PostMapping
public String updatePublisher(@ModelAttribute("publisherForm") @Validated PublisherResource resource, BindingResult result, Model model) {
if (result.hasErrors()) {
return showPage(resource, model);
}
return savePublisher(publisherResource.getId(), resource);
}
protected String savePublisher(int publisherId, PublisherResource resource) {
Publisher publisher = populatePublisher(publisherId, resource);
List<SubPublisher> subPublishers = populateSubPublishers(resource);
if (publisherId == 0) {
publisherService.createPublisher(publisher, subPublishers);
} else {
publisherService.updatePublisher(publisher, subPublishers);
}
return "redirect:/publishers";
}
protected Publisher populatePublisher(int publisherId, PublisherResource resource) {
Publisher publisher = null;
if (publisherId == 0) {
publisher = new Publisher();
publisher.setTimeAdded(new Date());
} else {
publisher = publisherService.getPublisher(publisherId);
}
publisher.setPublisherName(resource.getPublisherName());
publisher.setDescription(resource.getDescription());
publisher.setStatus(resource.isStatus());
publisher.setWebsiteURL(resource.getWebsiteURL());
return publisher;
}
protected List<SubPublisher> populateSubPublishers(PublisherResource resource){
if(resource.getSubPublishers() != null){
return resource.getSubPublishers().stream()
.map(s -> {
SubPublisher subPublisher = new SubPublisher();
subPublisher.setName(s.getName());
return subPublisher;
})
.collect(Collectors.toList());
}
return Collections.emptyList();
}
@PostMapping(params={"addRow"})
public String addRow(final PublisherResource publisher, final BindingResult bindingResult, Model model) {
publisher.getSubPublishers().add(new SubPublisherResource());
return showPage(publisher, model);
}
@PostMapping(params={"removeRow"})
public String removeRow(final PublisherResource publisher, final BindingResult bindingResult,
final HttpServletRequest req, Model model) {
final Integer rowId = Integer.valueOf(req.getParameter("removeRow"));
publisher.getSubPublishers().remove(rowId.intValue());
return showPage(publisher, model);
}
}
更新2 - 所有代碼:
實體出版商和SubPublisher:
@Entity
@Table(name = "publisher")
public class Publisher {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private int id;
@Column(name = "name")
private String publisherName;
@Column(name = "description")
private String description;
@Column(name = "status")
private boolean status;
@Column(name = "website_url")
private String websiteURL;
@Column(name = "time_added")
private Date timeAdded;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getPublisherName() {
return publisherName;
}
public void setPublisherName(String publisherName) {
this.publisherName = publisherName;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public boolean isStatus() {
return status;
}
public void setStatus(boolean status) {
this.status = status;
}
public String getWebsiteURL() {
return websiteURL;
}
public void setWebsiteURL(String websiteURL) {
this.websiteURL = websiteURL;
}
public Date getTimeAdded() {
return timeAdded;
}
public void setTimeAdded(Date timeAdded) {
this.timeAdded = timeAdded;
}
}
@Entity
@Table(name = "sub_publisher")
public class SubPublisher {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private int id;
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "publisher_id")
private Publisher publisher;
@Column(name = "name")
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Publisher getPublisher() {
return publisher;
}
public void setPublisher(Publisher publisher) {
this.publisher = publisher;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
庫
public interface PublisherRepository extends JpaDataTableRepository<Publisher, Integer> {
public Publisher findById(int id);
}
public interface SubPublisherRepository extends JpaRepository<SubPublisher, Integer> {
List<SubPublisher> findByPublisher(Publisher publisher);
void deleteByPublisher(Publisher publisher);
}
PublisherResource
public class PublisherResource {
private int id;
private String publisherName;
private String description;
private boolean status;
private String websiteURL;
private List<SubPublisherResource> subPublishers = new ArrayList<>();
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getPublisherName() {
return publisherName;
}
public void setPublisherName(String publisherName) {
this.publisherName = publisherName;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public boolean isStatus() {
return status;
}
public void setStatus(boolean status) {
this.status = status;
}
public String getWebsiteURL() {
return websiteURL;
}
public void setWebsiteURL(String websiteURL) {
this.websiteURL = websiteURL;
}
public List<SubPublisherResource> getSubPublishers() {
return subPublishers;
}
public void setSubPublishers(List<SubPublisherResource> subPublishers) {
this.subPublishers = subPublishers;
}
}
SubPublisherResource
public class SubPublisherResource {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
PublisherController
@Controller
@RequestMapping("/publisher")
public class PublisherController {
private PublisherService publisherService;
private PublisherConverter publisherConverter;
private SubPublisherConverter subPublisherConverter;
@Autowired
public PublisherController(PublisherService publisherService, PublisherConverter publisherConverter, SubPublisherConverter subPublisherConverter) {
this.publisherService = publisherService;
this.publisherConverter = publisherConverter;
this.subPublisherConverter = subPublisherConverter;
}
@GetMapping
public String newPublisher(Model model) {
PublisherResource publisher = new PublisherResource();
publisher.setStatus(true);
return showPage(publisher, model);
}
protected String showPage(PublisherResource publisher, Model model) {
model.addAttribute("publisherForm", publisher);
return "/publishers/publishers-edit";
}
@PostMapping
public String createPublisher(@ModelAttribute("publisherForm") @Validated PublisherResource resource, BindingResult result, Model model) {
if(result.hasErrors()) {
return showPage(resource, model);
}
return savePublisher(resource);
}
@GetMapping("/{id}")
public String editPublisher(@PathVariable("id") Integer id, Model model) {
Publisher publisher = publisherService.getPublisher(id);
PublisherResource res = publisherConverter.convert(publisher);
res.setSubPublishers(publisherService.getSubPublishers(publisher).stream().map(s->subPublisherConverter.convert(s)).collect(Collectors.toList()));
return showPage(res, model);
}
protected String savePublisher(PublisherResource resource) {
Publisher publisher = populatePublisher(resource);
List<SubPublisher> subPublishers = populateSubPublishers(resource);
if(resource.getId() == 0) {
publisherService.createPublisher(publisher, subPublishers);
} else {
publisherService.updatePublisher(publisher, subPublishers);
}
return "redirect:/publishers";
}
protected Publisher populatePublisher(PublisherResource resource) {
Publisher publisher;
if(resource.getId() == 0) {
publisher = new Publisher();
publisher.setTimeAdded(new Date());
} else {
publisher = publisherService.getPublisher(resource.getId());
}
publisher.setPublisherName(resource.getPublisherName());
publisher.setDescription(resource.getDescription());
publisher.setStatus(resource.isStatus());
publisher.setWebsiteURL(resource.getWebsiteURL());
return publisher;
}
protected List<SubPublisher> populateSubPublishers(PublisherResource resource) {
if(resource.getSubPublishers() != null) {
return resource.getSubPublishers().stream().map(s->{
SubPublisher subPublisher = new SubPublisher();
subPublisher.setName(s.getName());
return subPublisher;
}).collect(Collectors.toList());
}
return Collections.emptyList();
}
@PostMapping(params = { "addRow" })
public String addRow(final PublisherResource publisher, Model model) {
publisher.getSubPublishers().add(new SubPublisher());
return showPage(publisher, model);
}
@PostMapping(params = { "removeRow" })
public String removeRow(final PublisherResource publisher, final HttpServletRequest req, Model model) {
final Integer rowId = Integer.valueOf(req.getParameter("removeRow"));
publisher.getSubPublishers().remove(rowId.intValue());
return showPage(publisher, model);
}
}
PublishersController
@MenuController(value = "/publishers", item = Item.Publishers)
public class PublishersController {
private PublisherService publisherService;
private PublisherConverter publisherConverter;
public PublishersController(PublisherService publisherService, PublisherConverter publisherConverter) {
this.publisherService = publisherService;
this.publisherConverter = publisherConverter;
}
@GetMapping
public String showPage() {
return "publishers/publishers";
}
@PostMapping("/data")
public @ResponseBody DataTableResponse<PublisherResource> getPublishers(@RequestBody DataTableRequest request) {
return publisherConverter.convertResponse(publisherService.getPublishers(request));
}
@DeleteMapping("/{publisherIds}")
@ResponseStatus(HttpStatus.NO_CONTENT)
public void deletePublishers(@PathVariable Integer[] publisherIds) {
for (Integer publisherId: publisherIds) {
publisherService.deletePublisher(publisherId);
}
}
@PutMapping("/{publisherIds}/disable")
@ResponseStatus(HttpStatus.ACCEPTED)
public void disablePublishers(@PathVariable Integer[] publisherIds) {
changeStatus(publisherIds);
}
@PutMapping("/{publisherIds}/enable")
@ResponseStatus(HttpStatus.ACCEPTED)
public void enablePublishers(@PathVariable Integer[] publisherIds) {
changeStatus(publisherIds);
}
protected void changeStatus(Integer[] publisherIds) {
for (Integer publisherId: publisherIds) {
publisherService.updateStatus(publisherId);
}
}
}
PublisherConverter
@Component
public class PublisherConverter implements ResourceConverter<Publisher, PublisherResource> {
public PublisherResource convert(Publisher publisher) {
PublisherResource resource = new PublisherResource();
resource.setId(publisher.getId());
resource.setPublisherName(publisher.getPublisherName());
resource.setDescription(publisher.getDescription());
resource.setStatus(publisher.isStatus());
resource.setWebsiteURL(publisher.getWebsiteURL());
return resource;
}
}
PublisherService
@Service
public class PublisherService {
private PublisherRepository publisherRepository;
private SubPublisherRepository subPublisherRepository;
public PublisherService(PublisherRepository publisherRepository, SubPublisherRepository subPublisherRepository) {
this.publisherRepository = publisherRepository;
this.subPublisherRepository = subPublisherRepository;
}
public DataTableResponse<Publisher> getPublishers(DataTableRequest request) {
return publisherRepository.findAll(request);
}
@Transactional
public Publisher getPublisher(int publisherId) {
Publisher publisher = publisherRepository.findById(publisherId);
if(publisher != null){
List<SubPublisher> subPublishers = subPublisherRepository.findByPublisher(publisher);
//populateSubPublishers(subPublishers);
subPublishers.stream().forEach(s -> {
if(s.getId() == 0){
s.setPublisher(publisher);
subPublisherRepository.save(s);
}
});
}
if(publisher == null) {
throw new NotFoundException("Publisher " + publisherId + " not found.");
}
return publisher;
}
private void populateSubPublishers(List<SubPublisher> subPublishers) {
for(SubPublisher subPublisher : subPublishers){
subPublishers.add(subPublisher);
System.out.println(subPublisher.getName());
}
}
@Transactional
public Publisher createPublisher(Publisher publisher, List<SubPublisher> subPublishers) {
publisher = publisherRepository.save(publisher);
createSubPublisher(publisher, subPublishers);
return publisher;
}
private void createSubPublisher(Publisher publisher, List<SubPublisher> subPublishers) {
populateSubPublishers(subPublishers);
for(SubPublisher subPublisher : subPublishers){
subPublisher.setPublisher(publisher);
subPublisher.setName(subPublisher.getName());
}
}
@Transactional
public Publisher updatePublisher(Publisher publisher, List<SubPublisher> subPublishers) {
publisher = publisherRepository.save(publisher);
createSubPublishers(publisher, subPublishers);
return publisher;
}
private void createSubPublishers(Publisher publisher, List<SubPublisher> subPublishers) {
subPublisherRepository.deleteByPublisher(publisher);
for (SubPublisher sp : subPublishers) {
sp.setPublisher(publisher);
sp = subPublisherRepository.save(sp);
}
}
@Transactional
public void updateStatus(int publisherId) {
Publisher publisher = publisherRepository.findOne(publisherId);
if(publisher != null && publisher.isStatus() != false){
publisher.setStatus(false);
publisherRepository.save(publisher);
}
else if(publisher != null && publisher.isStatus() != true){
publisher.setStatus(true);
publisherRepository.save(publisher);
}
}
@Transactional
public void deletePublisher(int publisherId) {
Publisher publisher = publisherRepository.findOne(publisherId);
if (publisher != null) {
publisherRepository.delete(publisher);
}
}
public List<SubPublisher> getSubPublishers(Publisher publisher){
return subPublisherRepository.findByPublisher(publisher);
}
}
SubPublisherConverter
@Component
public class SubPublisherConverter implements ResourceConverter<SubPublisher, SubPublisherResource> {
@Override
public SubPublisherResource convert(SubPublisher subPublisher) {
SubPublisherResource resource = new SubPublisherResource();
resource.setName(subPublisher.getName());
return resource;
}
}
錯誤
java.util.ConcurrentModificationException: null
at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
at java.util.ArrayList$Itr.next(Unknown Source)
at publishers.PublisherService.populateSubPublishers(PublisherService.java:58)
at publishers.PublisherService.createSubPublisher(PublisherService.java:74)
at publishers.PublisherService.createPublisher(PublisherService.java:68)
如果數組列表是空的沒有輸入,將產生由於'個:each'不執行0次(意味着從不)。所以'th:each'循環中的所有內容都不會被包含在內。你只需要將''移出'th:each'。每個就像一個java foreach循環。如果你用foreach循環一個空集合,循環也不會被執行。 –
@TommySchmidt Thx爲您的回覆,我試着移動出來的每一個,當我去添加新的發佈者它顯示我+按鈕,但當我點擊它,它反應像保存按鈕和保存表格,而不添加字段爲子公司 – alonso05
從你張貼我不知道爲什麼。請在你的問題中加入你的'