jquery.dataTables.jsを使って改ページ機能を実装してみよう

### 一、DataTables.jsとは
　　HTMLのtable タグで作った表に改ページやソートや検索機能を追加するためのjQueryライブラリーの一つである。
    イメージは以下の通りです。
　　 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225740/49c700a0-3484-fb3c-3b2e-38750466526a.png)

　　今回は主に改ページや検索機能に関するの使い方を説明します。

### 二、使用準備
　　DataTables.jsを使うには、最低限のjQueryが必要です。[こちで](https://datatables.net/download/)
必要なパッケージをダウンロード可能です。

- **jquery-3.3.1.min.js**
- **datatables.min.js**
- **datatables.min.css**

### 三、HTML側の書き方
 まずは、必要なライブラリーを導入して、table タグを作ろう。

```HTML:index.html
<!doctype html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />

<!-- ライブラリーを導入 -->
<script src="js/jquery-3.3.1.min.js"></script>
<link rel="stylesheet" type="text/css" href="/DataTables/datatables.min.css">
<script type="text/javascript" charset="utf8" src="/DataTables/datatables.min.js"></script>
<!-- 自分が作ったJavaScriptファイル -->
<script type="text/javascript" charset="utf8" src="myTable.js"></script>

</head>
<body>
  <!-- tableのタブ -->
  <table id="myTable">
  </table>  
</body>
</html>
```

### 四、Java側の準備
jsonのオブジェクトとrestApiの実装を以下のようにします。ご参考お願い致します。

```java:DataTableDto.java
/** Dtoクラス. */
public class DataTableDto {

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getPosition() {
		return position;
	}

	public void setPosition(String position) {
		this.position = position;
	}

	public String getOffice() {
		return office;
	}

	public void setOffice(String office) {
		this.office = office;
	}

	public String getAge() {
		return age;
	}

	public void setAge(String age) {
		this.age = age;
	}

	public String getStartdate() {
		return startdate;
	}

	public void setStartdate(String startdate) {
		this.startdate = startdate;
	}

	private String name;

	private String position;

	private String office;

	private String age;

	private String startdate;


}

```


```java:myTable.java

    /**
	 * ページを指定し、データ一覧を取得する
	 * @param loginUser
	 * @param auth
	 * @param model
	 * @return
	 */
	@RequestMapping(value="/getTableData", method = RequestMethod.POST, consumes=MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<Map<String, Object>> getErrorWarnInfoByPage(@RequestBody InfoSelForm[] param,HttpServletRequest req){
    	try {

    		// 画面から取得したパラメータをHashMapに変換
        	Map<String,Object> paramMap = new HashMap<String,Object>();
        	Arrays.asList(param).forEach(
        		t ->
        		paramMap.put(t.getName(), t.getValue())
        	);
        	// 戻り値
        	List<DataTableDto> rtnList = new ArrayList<>();
        	Map<String, Object> result = new HashMap<String, Object>();
        	// 対象データの全件数
        	long targetAllDataCnt = 0;
        	// 画面対象データの全件数
        	long targetDspAllDataCnt = 0;
        	List<DataTableDto> dataTableDtoList = null;
       	if (param != null && param.length > 0) {
        		// 初回表示時は、発生日時順に表示
        		String listSortCondition = "";
        		if ("1".equals(paramMap.get("sEcho").toString()) == true) {
            		listSortCondition = "at_time desc";
        		}else {
            		// ソート条件取得
            		listSortCondition = super.getListSortCondition(paramMap);
            		if ("".equals(listSortCondition) == true) {
            			// ソート条件が指定されていない場合
                		listSortCondition = "at_time desc";
            		}
        		}

        		// ページ取得OPTION指定
        		SelectOptions options = super.getSelectOptions(paramMap);

        		// 検索文字取得
        		String strSearch = "";
        		if(paramMap.get("sSearch") != null) {
        			strSearch = paramMap.get("sSearch").toString();
        		}
　　　　　　　　　　　　　　　
　　　　　　　　　　　// dataTableDtoList = ...(ここでＤＢからデータを取得する)

         	    // 該当条件の全データを取得  
         	    targetDspAllDataCnt = options.getCount();
         	    if (dataTableDtoList != null && dataTableDtoList .size() > 0) {
         			for (DataTableDto dataTableDto: dataTableDtoList ) {

    			        rtnList.add(dataTableDto);
         			}

         		    // 対象の全データ件数を取得
         			targetAllDataCnt = dataTableDtoList.size();
         	    }

        	}

        	// 画面トータル件数
        	result.put("iTotalRecords", targetAllDataCnt);
        	// 画面に送信するデータ件数
        	result.put("iTotalDisplayRecords", targetDspAllDataCnt);
        	// データ部分 rootName設定
        	result.put("responseData", rtnList);
     		return new ResponseEntity<Map<String, Object>>(result, HttpStatus.OK);
    	}catch (Exception ex) {
    		super.printExceptionLog(ex,logger);
    		throw ex;
    	}
    }
```

### 五、JavaScript側の書き方
 javascriptの実装を以下の通りです。 コメントを見れば、分かることになります。

```javascript:myTable.js
$(document).ready( function () {
    // テーブルの高さを指定する
    var h = $(window).height();
    // 初期表示件数を設定する(一ページずつ10件を表示する)
    var pageLen =10;
    
    $('#myTable').DataTable(
    {
    	destroy: true,
    	// TODO 画面表示データ(mData)とjsonの各項目をマッピングします。
    	aoColumns: [
    		{ mData: "name", sDefaultContent: "" },
    		{ mData: "position", sDefaultContent: "" },
    		{ mData: "office", sDefaultContent: "" },
    		{ mData: "age", sDefaultContent: "" },
    		{ mData: "startdate", sDefaultContent: "" },
    	],
        rowCallback: function( row, data, dataIndex ) {
    	    // ここで設定する可能です
    	  },
    	// 表示の指定
    	columnDefs: [
    		{
    			// 対象列指定(開始位置0)
    			targets: [0,1,2,3,4],
    			// カラムの名前を設定する
    			//title: "Name",
    			// テーブル表示時にフォーマットする。
    			render: function ( data, type, row ) {
					return '<p style="white-space: nowrap;">' +
							$('<div>').text(data).html() +
							'</p>';
    			}
    		},
    		// visibleをfalseに設定すると、該当カラムが表示しない
    		//{ visible: false,  "targets": [ 0,2 ] }
    	],

      // サーバーに送信するパラメータを設定する
      //    fnServerParams: function (aoData) {
      //       aoData.push({"name": "name1", "value": "value1"});
      //      aoData.push({"name": "name2", "value": "value2"});
           // ...
      // },
        // 取得JSONのルート文字列を設定します。
        // TODO 省略した場合のデフォルト値は「aaData」です。restApiを呼び出す後の戻り値
    	sAjaxDataProp: "responseData",
        // Ajax 呼び出し中に処理中の表示
        bProcessing: true,
        // サーバーと通信が発生するか否か
        bServerSide: true,
        // trueにするとAjax通信を非同期で行います。
        bDeferRender: false,
        // ページング機能
        paging: true,
        // 検索機能
        searching: true,
        // TODO URL、restApiを呼び出し、データを取得する
        sAjaxSource: "/getTableData",
        // Ajax呼出関数
        fnServerData: function (sSource, aoData, fnCallback, oSettings) {
        	execDataTableAjax(sSource, aoData, fnCallback, oSettings);
        },
	    // 件数切替機能 無効
	    lengthChange: false,
	    // ソート機能 無効
	    ordering: false,
	    //初期表示件数
	    pageLength: pageLen,
	    // 横スクロールバーを有効にする (scrollXはtrueかfalseで有効無効を切り替えます)
	    scrollX: true,
	    // 縦スクロールバーを有効にする (scrollYは200, "200px"など「最大の高さ」を指定します)
	    scrollY: h - 230,
		language: {
			sProcessing: '処理中...',
			sLengthMenu: '_MENU_ 件表示',
			sZeroRecords: 'データはありません。',
			sInfo: ' _TOTAL_ 件中 _START_ から _END_ まで表示',
			sInfoEmpty: ' 0 件中 0 から 0 まで表示',
			sInfoFiltered: '（全 _MAX_ 件より抽出）',
			sInfoPostFix: '',
			sUrl: '',
			oPaginate: {
				sPrevious: '<',
				sNext: '>',
				sSearch: '検索'
			},
			// 検索ボックスを追加する
			search: '検索'
		},
    }
    );
} );
```

### 六、結果
結果としてのイメージをは以下の通りです。
検索ボックスを入力したら、検索することができます。
改ページを選択したら、改ページとなります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225740/2af3ae31-0664-5ce5-2dfc-0b7bfce89ecf.png)


### 七、最後に
最後まで読んでいただき、ありがとうございます。

参考：
https://datatables.net/manual/