2010-11-11 7 views
17

Dosyć powszechny przypadek użycia występuje w przypadku, gdy znajduje się lista obiektów Java, z których selekcje można wybierać w formularzu internetowym - zazwyczaj używa się klucza podstawowego obiekt jako wartość, aby kontroler mógł wykonać wyszukiwanie lub po prostu powiązać klucz z dowolnym obiektem, który został utworzony/zaktualizowany.Spring MVC - Wybór opuszczonego obiektu - Brak podstawowego identyfikatora

Mój problem polega na tym, że lista do wyboru nie jest trwałymi, kluczowanymi obiektami, są to modele biznesowe z usługi, która nie ma rozsądnego sposobu na ich odzyskanie w oparciu o zawarte w nich dane. Poniżej znajduje się kod psuedo, gdzie lista Foo jest podana do strony, i możemy łatwo przekazać kontrolerowi na Submit nazwę Foo, ale co, jeśli są inne pola Foo, które należy złożyć?

kontroler:

referenceData() { 
    ... 
    List foos = fooService.getFoosForBar(bar) 
    return { 'foos', foos } 
} 

jsp:

<form> 
    ... 
<spring:bind path="formData.foo"> 
    <select name="<c:out value="${status.expression}" />"> 
     <c:forEach items="${foos}" var="foo"> 
      <option value="<c:out value="${foo.name}"/>"> 
       <c:out value="${foo.name}"/> 
      </option> 
     </c:forEach> 
    </select> 
</spring:bind> 
    ... 
</form> 

Niektóre przykładowe rozwiązania byłoby użyć ukrytych pól do przedstawienia innych właściwości Foo i zachować je w synchronizacji jak wybór zmienia się, ale wolę nie używać JavaScriptu w takiej sytuacji, w której najprawdopodobniej spowoduje to zamieszanie. Z pewnością są na to inne sposoby.

Moje pytanie brzmi: czy istnieje jakaś standardowa praktyka do osiągnięcia tego? Czy powinienem po prostu wymyślić własny sposób? Wolałbym nie wymyślać kół, jeśli to możliwe, a to jest na pozór tak powszechne, że po prostu nie jest to najlepsze podejście.

Odpowiedz

7

Na podstawie swoich ograniczeń należy zakodować pozostałe elementy danych o foos jako wartość opcji.
<option label="${foo.name}" value="${foo.encodedValues}"/>
Sposób encodedValues może wyglądać tak:

 

    private String SEPARATOR = ","; 

    public String getEncodedValues() 
    { 
     final StringBuffer returnValue = new StringBuffer(); 

     returnValue.append(field1); 
     returnValue.append(SEPARATOR); 
     returnValue.append(field2); 
     returnValue.append(SEPARATOR); 
     returnValue.append(field3); 

     return returnValue.toString(); 
    } 
 

Jeśli masz liczbę wybiera, które muszą być zakodowane wartości, można utworzyć klasy, które wykonuje kodowanie i dekodowanie tych wartości, aby scentralizować kod.

+0

Użyłem tego podejścia, rejestrując niestandardowy spinacz w kontrolerze, aby przejść od napisu do reprezentatywnego obiektu (to jest scentralizowane kod, który sugeruje dwb). – Nate

3

Możesz użyć indeksu elementu na liście, aby odzyskać go w żądaniu POST.

<spring:bind path="formData.fooIndex"> 
    <select name="<c:out value="${status.expression}" />"> 
    <c:forEach items="${foos}" var="foo" varStatus="i"> 
     <option value="<c:out value="${i.index}"/>"> 
      <c:out value="${foo.name}"/> 
     </option> 
    </c:forEach> 
    </select> 
</spring:bind> 

W swojej obsługi POST, należy foos.get(formData.getFooIndex()) Jeśli foos może zmieniać żądania POST i GET, trzeba umieścić foos w sesji, dzięki czemu zdecydowanie odwołać się do tego samego obiektu w swojej obsługi POST, jak miało to miejsce w Obsługa GET.

+0

Nie mogę ponownie uzyskać listy i oczekiwać, że jest ona taka sama, umieszczenie jej w sesji nie jest idealne - jeśli formularz nie został wysłany, a nawet gdyby był, to możliwe, że lista pozostanie sesja do zakończenia sesji. Co jeszcze mogę zrobić, aby umożliwić właścicielowi postów mieć listę? Żądanie jest zbyt krótkie, ale sesja jest zbyt długotrwała. – walnutmon

+0

Następnie możesz ustawić swój obiekt w wartości