読者です 読者をやめる 読者になる 読者になる

修行@ホーチミン

ホーチミン長期出張の日記です

jinja2/Modal/JSの組み合わせで苦戦 #修正

前書き

 

jinja2/Modal/JSの組み合わせで苦戦 - 修行@ホーチミン

上記の実装方法で、アドバイスを頂きましてなんとか分かる範囲で修正を加えました。

まだ改善ポイントはあると思いますが、現状をまとめます。

 

修正内容

 

UPDATE専用Modalダイアログ修正

 

UPDATE専用Modalダイアログを作成して、idとnameをわざわざ一意のものにしてましたがその必要はなかったので、Ajaxリクエストを送信するときとjsonと同じnameを持たせるように修正。

これで後述のformの内容をjsonに変換する処理が可能になります。

そしてValidateのOptionも同じ内容をInputとUpdate用に別々で用意する必要がなくなりました。

 

<!-- Update Hotel Modal -->
<div class="modal fade bd-example-modal-lg" id="updateHotelModal" tabindex="-1" role="dialog" aria-labelledby="myLargeModalLabel" aria-hidden="true">
    <div class="modal-dialog modal-lg">
        <div class="modal-content">
            <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal">
                    <span aria-hidden="true">&times;</span>
                </button>
                <h4 class="modal-title" id="modal-label">Update Hotel</h4>
            </div>
            <div class="modal-body">

            <form id="updateHotel">
                    <input type="hidden" name="id" id="id" value="">
                <div class="form-group">
                    <label for="updName" class="form-control-label">Hotel Name:</label>
                    <input type="text" class="form-control" name="name" id="name" value="">
                </div>
                <div class="form-group">
                    <label for="updAddress" class="form-control-label">Hotel Address:</label>
                    <input type="text" class="form-control" name="address" id="address" value="">
                </div>
                <div class="form-group">
                    <label for="updCountryCode" class="form-control-label">Country Code:</label>
                    <input type="text" class="form-control" maxlength="2" name="countryCode" id="countryCode" value="">
                </div>
                <div class="form-group">
                    <label for="updCityCode" class="form-control-label">City Code:</label>
                    <input type="text" class="form-control" maxlength="3" name="cityCode" id="cityCode" value="">
                </div>
                    <div class="form-group">
                        <label for="updGrade">Hotel Grade:</label><br>
                        <select class="span1" name="grade" id="grade">
                        <option>1</option>
                        <option>2</option>
                        <option>3</option>
                        <option>4</option>
                        <option>5</option>
                        </select>
                    </div>
                <div class="form-group">
                    <label for="updFacility" class="form-control-label">Hotel Facility:</label>
                    <input type="text" class="form-control" name="facility" id="facility" value="">
                </div>
                <div class="form-group">
                    <label for="updImagePath" class="form-control-label">Image URL:</label>
                    <input type="text" class="form-control" name="imagePath" id="imagePath" value="">
                </div>
                <img class="img-responsive" id="image" >
            </form>

            </div>
            <div class="modal-footer">
                <div id="response_parameter" ></div>
                <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
                <button type="button" id="updateBtn" class="btn btn-primary">Update</button>
            </div>
        </div>
    </div>
</div>
<!-- End Update Hotel Modal -->

 

Modalダイアログ動的に変更

 

前処理でリスト表示されたhotelのうち、選択したhotelのそれぞれの値をformに持たせてから、Modalダイアログを開く点については変わりませんが、いくつか変更を加えました。

 

ボタンの修正

前回は、下記のようにJSの関数の引数としてJinja2を使ってしまっていましたが、これはやってはいけない書き方でした。

<button class="btn btn-warning" type="button" onclick="createUpdateHotelmodal( {{ hotel | to_json }} )">Update</button>

属性としてデータを持たせておき、JS側で処理をするという方法をとる必要があるため下記のように変更しました。

<button class="btn btn-success updModal" type="button" id="{{ hotel.id }}" data-hotel="{{ hotel | to_json }}" >Update</button>

 

fromのvalue埋め込みの修正
function createUpdateHotelmodal( data ){
    $('#updId').val(data.id);
    $('#updName').val(data.name);
    $('#updAddress').val(data.address);
    $('#updCountryCode').val(data.countryCode);
    $('#updCityCode').val(data.cityCode);
    $('#updGrade').val(data.grade);
    $('#updFacility').val(data.facility);
    $('#updImagePath').val(data.imagePath);
    $('#updateHotelModal').modal('show');
}

前回は上記のようにひたすら$('#id').val(data.value);のようなことをしてそれぞれ値を埋め込む。

みたいなことを繰り返していましたが、変更があるたびに修正が必要になります。

なので今回は、jsonの値をそのままformの各idのvalueに埋め込むという方法に修正しました。

    $('.updModal').click(function(){
        var targetHotel = JSON.parse($('#'+ this.id).attr('data-hotel'));
        $.each(targetHotel, function(key,value){
            $("#updateHotel").find("#"+key).val(value);
        })
        $('#updateHotelModal').modal('show');
    });
  • 先ほど修正したclass="updModal"のボタンをクリック
  • data属性であるdata-hotel="{{ hotel | to_json }}"のjson文字列の値をObjectとして取り出す
  • そのObjectのkeyとvalueから$.eachを用いてformにそれぞれ埋め込む

このような流れです。埋め込んだ後で$('#updateHotelModal').modal('show');でモーダルを開くと、inputの要素が既存のデータで埋まっている状態で開かれます。

もっとシンプルにする方法を考えましたが、いまはここで止まっています。

 

validate ⇒ Ajax通信

data: {
    "id" : $('#updId').val(),
    "name" : $('#updName').val(),
    "address" : $('#updAddress').val(),
    "countryCode" : $('#updCountryCode').val(),
    "cityCode" : $('#updCityCode').val(),
    "grade" : $('#updGrade').val(),
    "facility" : $('#updFacility').val(),
    "imagePath" : $('#updImagePath').val()
}

こちらも前回は上記の様に、POSTするjsonの内容を、"id" : $('#id').val(),のようにひたすら書いていました。

今回は、formの内容をjsonに変換してdata : form_dataのようにシンプルで変更に強くなるように修正。

$("#updateBtn").click(function(){
    $("#updateHotel").validate(hotelValid);
    if (!$("#updateHotel").valid()) {
        return false;
    };

    var form_data = {};
    $.each($("#updateHotel").serializeArray(),function(i,o){
        form_data[o.name] = o.value;
    })

    $.ajax( {
        type: "POST",
        url: "/hotel/update",
        dataType: "json",
        data: form_data // この部分
    }).done(function( response ){
        alert( "Hotel Id = " + response.data.hotel.id + " updated." );
        location.reload(true);
    }).fail(function( data ){
        alert( "faild" );
    });
});

$("#updateHotel").serializeArray()で取得したデータは、

[{"name":"id","value":"47"},{"name":"name","value":"Yaoji Hakata Hotel"},...]

のようなリストになっているので、これをまた$.eachを使って、json形式にします。

{"id":"47","name":"Yaoji Hakata Hotel",...}

作成したjsonデータをdata : form_dataとすることで、仮にformの内容に変更があってもここでの修正が不要になります。

 

 

感想

 

一番初めは、動いただけで満足してました。

でも今回でその満足は、ただの自己満でそれが障害につながることもあることを知り..

開発者としてはもっと視野を広げて、「このコードに問題はないか」とか「どうしたらもっとよくなるか」とか常に疑問を抱える必要があるということ。

よりよいコードを書くためには多くの経験が必要で技術や知識に貪欲であるべきだと感じることができました。

毎日レベルで壁にぶつかってますが、やっぱり楽しいです。

 

p.s.

ベトナム生活はというと、、

今日は何かにあたったか腹痛がとんでもないです。

最近毎日スコールです。