2

次のシナリオを検討してください。

  1. 私のフォームモデル

    public class PersonForm {
        @NotNull
        private String name;
    
        /*usual getters and setters*/
    }
    
  2. 私のコントローラー:

    @Controller
    @SessionAttribute(types={ PersonForm.class })
    public class MyController {
    
        @RequestAttribute(...)
        public String render(final ModelMap map) {
            /* get list of info and for each info 
             * create a PersonForm and put it in the modelmap
             * under key p0, p1, p2, ..., pn
             */
        }
    
        public String submit(final ModelMap map,
                             @Valid final PersonForm form,
                             final BindingResult result) {
    
            if (result.hasErrors()) {
                // return to page
            } else {
                // do necessary logic and proceed to next page
            }
        }
    }
    
  3. そして最後に私のJSPビュー

    ...
    <c:forEach ...>
        <form:form commandName="p${counter}">
            ... other form:elements and submit button goes here
        </form:form>
    </c:forEach>
    ...
    

ご覧のとおり、同じクラス タイプの複数のフォームを処理しようとしています。送信は機能します。submit(...) メソッドに問題なく到達し、検証も同様です。ただし、ページを再レンダリングしても、予想されるエラー メッセージが表示されません。

さらに悪いことに、送信ヘッダーで何が渡されているかを確認しましたが、どのフォームが送信されたかがまったく示されていないため、あるフォームと別のフォームを区別する方法はありません。これにより、同じクラスタイプの複数のフォームは不可能であると信じるようになりました...

これを行うことができる他の方法はありますか (Ajax を除く) ?

どうもありがとう。

4

2 に答える 2

2

私はなんとかこの「ハック」を機能させることができました。それは、ジェリーが勧めた通りなので、クレジットはすべて彼に行きます。

簡単に言うと、コンセプトは、従来の構成を使用してビューを事前に入力すること<c:forEach>です。トリッキーな部分は、それぞれの行の「送信」ボタンが押されたときはいつでも、すべての情報を非表示のフォームに挿入し、コントローラーに強制的に送信する必要があることです。いくつかのエラーで画面が再びレンダリングされる場合、スクリプトはエラーを含むそれぞれの行に値を注入する責任があります。


1)私のモデル

    public class PersonForm {

        private String id;

        @NotNull
        private String name;

        /*usual getters and setters*/
    }

2)私のコントローラー

    @Controller
    @SessionAttribute(/* the hidden form name, the person list */)
    public class MyController {

        @RequestAttribute(...)
        public String render(final ModelMap map) {
            /* get list of info and for each info 
             * create a PersonForm and put it in the modelmap
             * under key p0, p1, p2, ..., pn
             */
        }

        public String submit(final ModelMap map,
                             @Valid final PersonForm form,
                             final BindingResult result) {

            if (result.hasErrors()) {
                // return to page
            } else {
                // do necessary logic and proceed to next page
            }
        }
    }

3)私の見解

    ...

    <form:form commandName="personForm" cssStyle="display: none;">
        <form:hidden path="id"/>
        <form:hidden path="name" />
        <form:errors path="name" cssStyle="display: none;" />
    </form:form>

    ...

    <c:forEach var="p" items="${pList}">
        <input type="text" id="${ p.id }Name" value="${ p.name }" />
        <!-- to be filled in IF the hidden form returns an error for 'name' -->
        <span id="${ p.id }nameErrorSpan"></span>
        <button type="button" value="Submit" onclick="injectValuesAndForceSubmit('${ p.id }');" />
    </c:forEach>

    ...

    <script type="text/javascript">

    injectValuesAndForceSubmit = function(id) {

        $('#id').val( id ); // fill in the hidden form's id
        $('#name').val( $('#'+id+'name').val() ); //fill in the hidden form's name

        $('#personForm').submit(); //submit!
    }



    $(document).ready(function() {

        var id = $('#id').val();    
        if (id.trim().length == 0) {
            //Empty. Nothing to do here as this is a simple render.
        } else {

            //The page seems to be returning from some sort of error ... pre-fill the respective row!
            $('#'+id+'name').val($('#name').val());
            var hiddenNameErrorSpan = $('#name.errors');
            if (hiddenNameErrorSpan) {
                $('#'+id+'nameErrorSpan').text(hiddenNameErrorSpan.html());
            }
        } //else
    }
    </script>

ご覧のとおり、ビューには最も毛深い部分があります。(残念ながら)私のものと同じ状況に遭遇した人にとっては、それでも役立つことを願っています。乾杯!

于 2012-08-14T08:31:17.237 に答える
1

複数のフォームを持つ私見は、物事を過度に複雑にします(または少なくとも春で)。また、複数のフォームを使用していますが、送信されるのは 1 つだけです。

したがって、これを管理する最も簡単な方法は、個人のプロパティを持つ独自の非表示の外部フォームを使用することです。ボタンの 1 つが押されたら、それに応じてフォームの person プロパティを入力し、送信します。これにより、典型的な春のフォームの送信/検証を達成しています。

おそらく、このソリューションには JavaScript を少し使用する必要がありますが、複数のフォームで spring-mvc を処理する方法がわかりません。以前の試みが失敗したため、常に回避しようとしました。

于 2012-08-08T10:24:50.273 に答える