【jQuery】JSONデータをフィルタリングして指定のフォームに項目として表示させる方法
2018/10/03
PHP経由で取得したデータベースのレコードをJOSN形式に変換し、さらに条件に則ってフィルタして指定のセレクトフォーム(multiple)に選択肢として表示させたくなったので、試行錯誤しながら作ってみました。
これは個人的に使えるスクリプトとなった気がするぞ…!?
フォームに収めるデータをJSONに変換してフィルタする方法
元々、下の画像のようなメッセージの送信先(社員名)を選択する画面がありました。
『属性』欄にあるセレクトフォーム(1)で「性別指定」や「支社指定」といった大項目を選択、セレクトフォーム(2)にて選択した内容の詳細である「女」や「東京」といった内容を選択し、ボタン(3)のクリックで社員名リストを生成、宛先フォーム(4)に結果の社員名リストを表示させるという動作でした。
宛先フォーム(5)に対象の社員名を移動させたあとに、再度、属性フォーム(1)(2)を操作、ボタン(3)を押すとPOST通信されてページがリフレッシュされ、宛先フォーム(5)がクリアされてしまうという仕様だったので、クリアしないようにするのが今回のミッション。
ということで思いついたのが、画面を表示したときにデータベースから社員データを取得し、PHPでJSONデータを作成、Javascriptで(POST通信せずに)セレクトフォームを操作したときにリアルタイムで社員リストを作成(フィルタ)すれば良いのでは、という案。
書いていることは若干ややこしいですが、JSONデータを作成し、フィルタリングするだけで出来そうな予感。
デモはこちら
まずはデモを御覧ください。上でややこしく書いているいますが、単純にこういうことがしたかったってのがよく分かると思います。
『属性』の(A)で
- 社員指定
- 性別指定
- 支社指定
- 部署指定
- 課指定
を選択、『属性』の(B)で
- 性別 ⇒ 男 / 女
- 支社 ⇒ 札幌 / 仙台 / 東京 / 大阪 / 広島 / 福岡 / 沖縄
- 部署 ⇒ 営業部 / 商品部 /総務部
- 課 ⇒ 営業 / 生産 / 物流 / マーケティング / 総務 / 経理 / システム
のように詳細選択し、『宛先』フォーム(右)へ、対象となる社員名を表示させるという流れとなります。
なお、属性(A)(B)は、以前作成した『連動プルダウン』プラグインを使用します。
【jQuery】連動プルダウン用プラグイン『jquery.tgHierSelect』をより簡単に設置できるようバージョンアップ
支社、性別、部署、課の各マスタは以下とします。
社員マスタは『ダミー個人情報サイト』さんを使い、適当に作成しました。
JSONデータ作成
下記のような手順でJSONデータを作成します。
(1)SQL発行
以下のようなSQLでレコードを取得します。
このあたりは使っているPHPフレームワーク等に依存するところでしょうか。
1 2 3 4 5 6 7 8 9 10 11 |
SELECT id, gender_id, blanch_id, department_id, section_id, name FROM employees WHERE is_delete = 0; |
(2)取得したDBレコードをPHPでJSONにコンバート
取得した結果を、PHP上でJOSN形式にコンバートして、ビューに渡します。
1 |
json_employee_list = json_encode($employee_list); |
json_encodeの仕様は下記を確認してください。
今回は特に何も指定せずコンバートしました。
ビューに渡す方法は各PHPフレームワークによって異なると思うので割愛します。
ちなみにCakePHP ですと、$this->set() あたりでビューに放り込めるはずです。
出来上がったJSONデータ
1 2 3 4 |
{"id":"1","gender_id":"1","blanch_id":"1","department_id":"1","section_id":"1","name":"志賀貞一"}, {"id":"1","gender_id":"2","blanch_id":"2","department_id":"1","section_id":"1","name":"安田志歩"}, {"id":"1","gender_id":"1","blanch_id":"3","department_id":"1","section_id":"1","name":"村岡総一朗"}, -- 以下略 -- |
プルダウンなど、コード一式
Javascript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 |
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script> <script src="./jquery.tgHierSelectV2/jquery.tgHierSelectV2.js"></script> <script> $(document).ready(function(){ // 連動プルダウンオプション $(this).tgHierSelectV2({ group: 'group1', maxLevel: '2', defaultSelect: '選択してください', }); // 処理対象のオブジェクト配列 var employees = [ {"id":"1","gender_id":"1","blanch_id":"1","department_id":"1","section_id":"1","name":"志賀貞一"}, {"id":"1","gender_id":"2","blanch_id":"2","department_id":"1","section_id":"1","name":"安田志歩"}, {"id":"1","gender_id":"1","blanch_id":"3","department_id":"1","section_id":"1","name":"村岡総一朗"}, {"id":"1","gender_id":"2","blanch_id":"4","department_id":"1","section_id":"1","name":"宇野直美"}, {"id":"1","gender_id":"2","blanch_id":"5","department_id":"1","section_id":"1","name":"亀田遥華"}, {"id":"1","gender_id":"1","blanch_id":"6","department_id":"1","section_id":"1","name":"庄司照雄"}, {"id":"1","gender_id":"1","blanch_id":"7","department_id":"1","section_id":"1","name":"小谷光信"}, {"id":"1","gender_id":"1","blanch_id":"1","department_id":"2","section_id":"2","name":"松木博道"}, {"id":"1","gender_id":"2","blanch_id":"2","department_id":"2","section_id":"2","name":"小久保雪絵"}, {"id":"1","gender_id":"2","blanch_id":"3","department_id":"2","section_id":"3","name":"矢野風花"}, {"id":"1","gender_id":"1","blanch_id":"4","department_id":"2","section_id":"3","name":"塚本長太郎"}, {"id":"1","gender_id":"1","blanch_id":"5","department_id":"2","section_id":"2","name":"田渕勝巳"}, {"id":"1","gender_id":"1","blanch_id":"6","department_id":"2","section_id":"2","name":"島津一憲"}, {"id":"1","gender_id":"2","blanch_id":"7","department_id":"2","section_id":"3","name":"河井澪"}, {"id":"1","gender_id":"1","blanch_id":"1","department_id":"1","section_id":"1","name":"森口明仁"}, {"id":"1","gender_id":"1","blanch_id":"2","department_id":"1","section_id":"1","name":"西口裕史"}, {"id":"1","gender_id":"2","blanch_id":"3","department_id":"1","section_id":"4","name":"三上美智子"}, {"id":"1","gender_id":"2","blanch_id":"4","department_id":"1","section_id":"4","name":"塚田順子"}, {"id":"1","gender_id":"1","blanch_id":"5","department_id":"1","section_id":"1","name":"小平兼吉"}, {"id":"1","gender_id":"2","blanch_id":"6","department_id":"1","section_id":"1","name":"石沢里歌"}, {"id":"1","gender_id":"1","blanch_id":"7","department_id":"1","section_id":"1","name":"片野哲史"}, {"id":"1","gender_id":"1","blanch_id":"3","department_id":"3","section_id":"5","name":"岡村肇"}, {"id":"1","gender_id":"1","blanch_id":"3","department_id":"3","section_id":"5","name":"新田一寿"}, {"id":"1","gender_id":"2","blanch_id":"3","department_id":"3","section_id":"6","name":"本田茉央"}, {"id":"1","gender_id":"1","blanch_id":"4","department_id":"3","section_id":"5","name":"唐沢信長"}, {"id":"1","gender_id":"1","blanch_id":"4","department_id":"3","section_id":"6","name":"柏木勇"}, {"id":"1","gender_id":"1","blanch_id":"4","department_id":"3","section_id":"6","name":"亀田裕次郎"}, {"id":"1","gender_id":"2","blanch_id":"3","department_id":"3","section_id":"7","name":"竹本早紀"}, {"id":"1","gender_id":"1","blanch_id":"3","department_id":"3","section_id":"7","name":"吉村正"}, {"id":"1","gender_id":"1","blanch_id":"3","department_id":"3","section_id":"7","name":"碓井恒雄"}]; pd1Val = 0; pd2Val = 0; // $('#lv1, #lv2').change(function() { // プルダウン選択値 pd1Val = $('#lv1').val(); pd2Val = $('#lv2').val(); if (pd1Val != 0 && pd2Val != 0) { $("#list2").html(""); // 社員指定→全て if (pd1Val == 1 && pd2Val == 1) { // <option value>作成 for (var i=0; i<employees.length; i++) { $("#list2").append("<option value="+employees[i].id+">"+employees[i].name+"</option>"); } } else { // 社員指定以外 if (pd1Val != 0) { // フィルタ var filtered = $.grep(employees, function(elem, index) { if (pd1Val == 2) { // gender_idプロパティの値でフィルター return (elem.gender_id == pd2Val); } else if (pd1Val == 3) { // blanch_idプロパティの値でフィルター return (elem.blanch_id == pd2Val); } else if (pd1Val == 4) { // department_idプロパティの値でフィルター return (elem.department_id == pd2Val); } else if (pd1Val == 5) { // section_idプロパティの値でフィルター return (elem.section_id == pd2Val); } } ); // <option value>作成 for (var i=0; i<filtered.length; i++) { $("#list2").append("<option value="+filtered[i].id+">"+filtered[i].name+"</option>"); } } } } else { if (pd1Val == 0) { $('#lv2').attr("disabled", "disabled"); // (B)をdisabledにする } $("#list2").html(""); // 宛先(右)をクリア } }); // 左右フォーム $('input[name=add]').on('click', function() { move('list2', 'list1'); }); $('input[name=del]').on('click', function() { move('list1', 'list2'); }); var move = function(_this, target) { $('select[name=' + _this + '] option:selected').each(function() { $('select[name=' + target + ']').append($(this).clone()); $(this).remove(); }); }; }); </script> |
↑ マークしている部分が、JSONデータのフィルタを実際に行っているところです。
フィルタの仕様は以下のような形です。
gender_id のような、プロパティに対して判定を行っているだけの、単純なスクリプトです。
1 2 3 4 5 |
var filtered = $.grep(employees, function(elem, index) { return (elem.gender_id == 2); } ); |
HTML
以下からは、フォーム部分のHTML。(A)(B)部分は私の作成した多段連動プルダウンのスクリプトに則っています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
<form action="#"> <table> <tr> <th>属性</th> <td>(A) <select name="sel1-1" id="lv1" class="group1"> <option value="">選択してください</option> <option value="1">社員指定</option> <option value="2">性別指定</option> <option value="3">支社指定</option> <option value="4">部署指定</option> <option value="5">課指定</option> </select> (B)<select name="sel1-2" id="lv2" class="group1" disabled="disabled"> <option value="0" selected="selected">選択してください</option> <option value="1" class="p1">全て</option> <option value="1" class="p2">男</option> <option value="2" class="p2">女</option> <option value="1" class="p3">札幌</option> <option value="2" class="p3">仙台</option> <option value="3" class="p3">東京</option> <option value="4" class="p3">大阪</option> <option value="5" class="p3">広島</option> <option value="6" class="p3">福岡</option> <option value="7" class="p3">沖縄</option> <option value="1" class="p4">営業部</option> <option value="2" class="p4">商品部</option> <option value="3" class="p4">総務部</option> <option value="1" class="p5">営業</option> <option value="2" class="p5">生産</option> <option value="3" class="p5">物流</option> <option value="4" class="p5">マーケティング</option> <option value="5" class="p5">総務</option> <option value="6" class="p5">経理</option> <option value="7" class="p5">システム</option> </select> </td> </tr> <tr> <th>宛先</th> <td> <table class="crossselect"> <tr> <td> <select name="list1" id="list1" size="10" class="addForm" multiple="multiple"> </select> </td> <td width="16%"> <input type="button" value="←追加" name="add" onClick="addList();" class="addButton" /><br /> <input type="button" value="削除→" name="del" onClick="deleteList();" class="delButton" /> </td> <td> <select name="list2" id="list2" size="10" class="deleteForm" multiple="multiple"> </select> </td> </tr> </table> </td> </tr> </table> </form> |
デモはこちら
まとめ
POST通信させずにフォームデータを操作したいということでJSONを使用しフィルタさせましたが、これはなにかと他でも色々と使えそうな技な予感がします。
見ている人何かの足しになれば幸いです。