この質問の一部が回答されたため、私はこの質問を完全に変更します ここ Avnishの多大な支援により!トムは私を正しい方向に導いてくれたので、ありがとうトム!
私の問題は、編集時にオブジェクト要素を事前選択するようにThymeleafに指示する方法がわからないことです。
披露させて:
このソリューションは機能します:
<select class="form-control" id="parts" name="parts" multiple="multiple">
<option th:each="part : ${partsAtribute}"
th:selected="${servisAttribute.parts.contains(part)}"
th:value="${part.id}"
th:text="${part.name}">Part name</option>
</select>
私はこれを試しました:
<select class="form-control" th:field="*{parts}" multiple="multiple">
<option th:each="part : ${partsAtribute}"
th:field="*{parts}"
th:value="${part.id}"
th:text="${part.name}">Part name</option>
</select>
動作しませんでした。私もこれを試しました:
<select class="form-control" th:field="*{{parts}}" multiple="multiple">
<option th:each="part : ${partsAtribute}"
th:field="*{parts}"
th:value="${part.id}"
th:text="${part.name}">Part name</option>
</select>
どちらも機能しませんでした。同じ結果で、オプションタグからth:field="*{parts}"
を削除してみました。
th:value
を${part}
に変更すると機能しますが、[2,4,5,6、...]などのIDの文字列は返されず、Part
インスタンスが返されます[Part @ 43b45j、Part @ we43y7、...]のように...
[〜#〜] update [〜#〜]:1つのパーツのみが選択されている場合、これが機能することに気づきました:
<select class="form-control" th:field="*{parts}" multiple="multiple">
<option th:each="part : ${partsAtribute}"
th:field="*{parts}"
th:value="${part.id}"
th:text="${part.name}">Part name</option>
</select>
複数のパーツが選択されている場合、機能しません...
Thymeleafフォーラムでの議論の後、私は https://github.com/jmiguelsamper/thymeleafexamples-selectmultiple で完全に機能する例を実装しました
最終コードの唯一の問題は、conversionServiceを呼び出すために二重ブラケット構文を使用する必要があることだと思います:
th:value="${{part}}"
適切な比較を保証するために、Partクラスに適切なequals()およびhashcode()メソッドを実装することも重要です。
私の例が将来同様の問題を持つ他のユーザーを助けることを願っています。
th:selected
を通常使用する場合、th:field
は必要ありません。 Thymeleafは、multiple
であっても、<option>
の各<select>
の値を自動的にチェックします
問題は価値にあります。 parts
を反復処理していますが、各オプションの値はpart.id
です。したがって、あなたはpartのインスタンスをpartのidと比較しています(私が見る限り)。
ただし、ThymeleafはPropertyEditor
のインスタンスも考慮に入れます(org.springframework.web.servlet.tags.form.SelectedValueComparator
を再利用します)。
これは、オブジェクトをオプションの値と比較するときに使用されます。オブジェクトをテキスト値(ID)に変換し、これを値と比較します。
<select class="form-control" th:field="*{parts}" multiple="multiple" >
<option th:each="part : ${partsAttribute}"
<!--
Enable the SpringOptionFieldAttrProcessor .
th:field value of option must be equal to that of the select tag
-->
th:field="*{parts}"
th:value="${part.id}"
th:text="${part.name} + ${part.serial}">Part name and serial No.
</option>
</select>
プロパティエディター
パーツのPropertyEditor
を定義します。値を比較するとき、およびパーツをフォームにバインドするときに、PropertyEditorが呼び出されます。
@Controller
public class PartsController {
@Autowired
private VehicleService vehicleService;
@InitBinder(value="parts")
protected void initBinder(final WebDataBinder binder) {
binder.registerCustomEditor(Part.class, new PartPropertyEditor ());
}
private static class PartPropertyEditor extends PropertyEditorSupport {
@Override
public void setAsText(String partId) {
final Part part = ...; // Get part based on the id
setValue(part);
}
/**
* This is called when checking if an option is selected
*/
@Override
public String getAsText() {
return ((Part)getValue()).getId(); // don't forget null checking
}
}
}
ConvertingPropertyEditorAdapter
もご覧ください。 Converter
に登録されているconversionService
インスタンスは、最近のSpringでより好まれています。
これは私にとってはうまくいきます:
獣医には多くの専門があります。
コントローラ:
_@RequestMapping(value = "/vets/{vetId}/edit", method = RequestMethod.GET)
public ModelAndView editVet(@PathVariable("vetId") int ownerId/*, Model model*/) {
ModelAndView mav = new ModelAndView("vets/vetEdit");
mav.addObject("vet", this.vets.findById(ownerId));
mav.addObject("allSpecialties", this.specialities.findAll());
return mav;
}
_
表示(th:selectedを使用):
_<select id="specialities" class="form-control" multiple>
<option th:each="s : ${allSpecialties}"
th:value="${s.id}"
th:text="${s.name}"
th:selected="${vet.specialties.contains(s)}">
</option>
</select>
_
表示(th:fieldを使用):
_<form th:object="${vet}" class="form-horizontal" id="add-vet-form" method="post">
<div class="form-group has-feedback">
<select th:field="*{specialties}" class="form-control" multiple>
<option th:each="s : ${allSpecialties}"
th:value="${s.id}"
th:text="${s.name}"
>
</option>
</select>
</div>
_
そして、SpecialtyRepositoryでSpecialty findOne(@Param("id") Integer id) throws DataAccessException;
を定義する必要があります。そうしないと、次の例外がスローされます:「Java.lang.IllegalStateException:リポジトリでfind-one-methodが宣言されていません!」
_package org.springframework.samples.petclinic.vet;
import Java.util.Collection;
import org.springframework.dao.DataAccessException;
import org.springframework.data.repository.Repository;
import org.springframework.data.repository.query.Param;
import org.springframework.transaction.annotation.Transactional;
public interface SpecialtyRepository extends Repository<Specialty, Integer> {
@Transactional(readOnly = true)
Collection<Specialty> findAll() throws DataAccessException;
Specialty findOne(@Param("id") Integer id) throws DataAccessException;
}
_
<select id="produtos" name="selectedItens" style="width: 100%;" multiple="multiple" required="">
<option th:value="${p.id}" th:text="${p}" th:each="p : ${slideShowForm.itens}" th:selected="${#lists.contains(slideShowForm.selectedItens,p)}"></option>
</select>
ここに私がそれをした方法があります:
<select th:field="*{influenceIds}" ID="txtCategoryName" class="m-wrap large" multiple="multiple">
<option th:each="influence : ${influences}" th:value="${influence.get('id')}" th:text="${influence.get('influence')}" ></option>
</select>
私のDTOに含まれるもの:
private List<String> influenceIds;