Edited at

SpringBoot + BootStrap + DataTablesで選択画面を作成する

More than 1 year has passed since last update.


選択ボタンで検索画面をモーダル表示して検索結果を親画面に反映するケースを検討します。

1.説明

(1) 解説

画面の入力では、マスタを検索して対象を選択するようなケースがあります。このような場合において、BootStrapのモーダルダイアログの機能と、DataTablesの一覧表示機能を使って実装する方法を検討します。

(2)全体イメージ

image.png

フォーム上のボタンを押して、モーダルウィンドウを表示します。一覧から対象のデータを選択するとフォームに選択したデータが入力された状態にします。

BootStrapのモーダルウィンドウを使います。

(3)モーダルダイアログの概念図

image.png

モーダルダイアログはjQuery DataTablesを使います。データは、Ajaxプロパティに、RestControllerからデータの一覧を返すという仕組みにします。ここでは、ユーザマスタ(Account)としています。

2.プロジェクトの構成

sample-modal

│ build.gradle
└─src
└─main
├─java
│ └─com
│ └─stone
│ └─ccc
│ Account.java
│ AccountRepository.java
│ DataTablesRestController.java
│ HeloController.java
│ SampleModalApplication.java
│ ServletInitializer.java
└─resources
│ application.properties
│ hibernate.properties
├─static
│ └─DataTables-1.10.16
│ │ Japanese.json
│ │
│ ├─css
│ │ dataTables.bootstrap.min.css
│ │ dataTables.bootstrap4.min.css
│ │ dataTables.jqueryui.min.css
│ │ jquery.dataTables.min.css
│ └─js
│ dataTables.bootstrap.min.js
│ dataTables.bootstrap4.min.js
│ dataTables.jqueryui.min.js
│ jquery.dataTables.min.js
└─templates
index.html
modalempselect.html

jQuery DataTablesのcss, jsをstaticの下に配置します。

index.htmlが親画面

modalempselectがモーダルになっています。

3.依存関係


build.gradle

dependencies {

compile('org.springframework.boot:spring-boot-starter-data-jpa')
compile('org.springframework.boot:spring-boot-starter-thymeleaf')
compile('org.springframework.boot:spring-boot-starter-web')
compile('org.apache.commons:commons-lang3:3.7')
compile('org.webjars:jquery:3.2.1')
compile('org.webjars:jquery-ui:1.12.1')
compile('org.webjars:bootstrap:4.0.0')
compile('com.fasterxml.jackson.datatype:jackson-datatype-jsr310')
runtime('org.springframework.boot:spring-boot-devtools')
runtime('org.postgresql:postgresql')
compileOnly('org.projectlombok:lombok')
providedRuntime('org.springframework.boot:spring-boot-starter-tomcat')
testCompile('org.springframework.boot:spring-boot-starter-test')
}

4.DB接続設定


application.properties

spring.datasource.driverClassName=org.postgresql.Driver

spring.datasource.url=jdbc:postgresql://localhost:5432/testdb
spring.datasource.username=testuser
spring.datasource.password=testuser
spring.jpa.hibernate.ddl-auto=none

DBは、postgresqlを使います。


hibernate.properties

hibernate.jdbc.lob.non_contextual_creation = true


postgresqlを使った場合にエラーが発生するのでこのpropertyを設定しておきます。

5.DB


account.sql

create table account (

username character varying(64) not null
, password character varying(255)
, email character varying(64)
, authority character varying(64)
, primary key (username)
);


account_insert.sql

insert into account(username,password,email,authority)

values
('admin','admin','admin@localhost','ROLE_ADMIN')
,('user','pass','user@localhost','ROLE_USER');

6.Entity


Account.java

import javax.persistence.Column;

import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name = "account")
public class Account {
@Id
@Column(name="username")
private String username;
@Column(name="email")
private String email;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}

7.Repository


AccountRepository.java

import org.springframework.data.jpa.repository.JpaRepository;

public interface AccountRepository extends JpaRepository<Account, String> {}

7.RestController

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class DataTablesRestController {
@Autowired
AccountRepository Repo;
@RequestMapping("/getaccountlist")
public List<Account> getuserlist() {
return Repo.findAll();
}
}

jQuery DataTablesのajaxパラメータに渡すJsonの配列です。

8.Controller


HeloController.java

import org.springframework.stereotype.Controller;

import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
public class HeloController {
@RequestMapping(value = "/", method = RequestMethod.GET)
public String index(Model model) {
return "index";
}
}

9.html

(1)フォーム


index.html

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
<title>モーダルダイアログ サンプル</title>
<meta charset="utf-8" />
<link th:href="@{/webjars/bootstrap/4.0.0/css/bootstrap.min.css}" rel="stylesheet" />
<script type="text/javascript" th:src="@{/webjars/jquery/3.2.1/jquery.min.js}"></script>
<script type="text/javascript" th:src="@{/webjars/bootstrap/4.0.0/js/bootstrap.min.js}"></script>
<link rel="stylesheet" th:href="@{/DataTables-1.10.16/css/jquery.dataTables.min.css}"/>
<link rel="stylesheet" th:href="@{/DataTables-1.10.16/css/dataTables.bootstrap4.min.css}"/>
<script type="text/javascript" th:src="@{/webjars/jquery-ui/1.12.1/jquery-ui.min.js}"></script>
<script type="text/javascript" th:src="@{/DataTables-1.10.16/js/jquery.dataTables.min.js}"></script>
<script type="text/javascript" th:src="@{/DataTables-1.10.16/js/dataTables.bootstrap4.min.js}"></script>
</head>
<body>
<div class="container">
<h2>モーダルダイアログ サンプル</h2>
<div class="form-group">
<label class="col-sm-2">username:</label>
<input type="text" id="username" size="10"/>
</div>
<div class="form-group">
<label class="col-sm-2">email:</label>
<input type="text" id="email" size="20"/>
<a class="form-control-sm bg-primary" id="empchange"
data-toggle="modal" data-target="#modal-emp-select">選択</a>
</div>
</div>
<div th:replace="modalempselect::modalempselect"></div>
<script th:inline="javascript">
/*<![CDATA[*/
$(document).on("click","#btn-modalemp-select", function() {
$('#username').val(modalempdata.username);
$('#email').val(modalempdata.email);
$('#modal-emp-select').modal('hide');
});
/*]]>*/
</script>
</body>
</html>

point

<a class="form-control-sm bg-primary" id="empchange"

data-toggle="modal" data-target="#modal-emp-select">選択</a>

data-toggle="modal" data-target="#modal-emp-select"とするだけで、クリックしたらmodalが開きます。

(2)モーダル


modalempselect.html

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
<title>モーダルダイアログ サンプル</title>
<meta charset="utf-8" />
</head>
<body>
<div th:fragment="modalempselect">
<!-- モーダルの設定 -->
<div class="modal" id="modal-emp-select" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<h6 class="modal-title">従業員選択画面</h6>
<button type="button" class="close" data-dismiss="modal" aria-label="閉じる">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<table id="modal-emplist-table" class="table table-bordered table-hover table-lg">
<thead class="thead-light">
<tr>
<th>従業員番号</th>
<th>氏名</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
<script th:inline="javascript">
/*<![CDATA[*/
var modalempdata = null;
$(function(){
// datatableの設定を変更
var modalemptable = $("#modal-emplist-table").DataTable({
"bPaginate": true,
"bLengthChange": false,
"bFilter": true,
"bSort": false,
"bInfo": false,
"bAutoWidth": false,
"language": {
"url": /*[[@{/DataTables-1.10.16/Japanese.json}]]*/ 'Japanese.json'
},
"ajax": { url: /*[[@{/getaccountlist}]]*/ 'getaccountlist', dataSrc: '' },
"columns": [
{ data: "username" },
{ data: "email" },
],
"columnDefs": [
{ targets: 0, width: 60 },
{ targets: 1, width: 180 },
{targets:'_all',className : 'dt-head-center'},
]
});
//一覧をクリックした
$('#modal-emplist-table tbody').on("click", "tr", function() {
if ($(this).find('.dataTables_empty').length == 0) {
if ( $(this).hasClass('selected') ) {
$(this).removeClass('selected');
} else {
modalemptable.$('tr.selected').removeClass('selected');
$(this).addClass('selected');
}
modalempdata=$('#modal-emplist-table').dataTable().fnGetData(this);
}
});
})
/*]]>*/
</script>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" id="btn-modalemp-select">選択</button>
<button type="button" class="btn btn-primary" data-dismiss="modal">キャンセル</button>
</div><!-- /.modal-footer -->
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
</div>
</body>
</html>

thymeleafのfragmentを使ってます

10.実行してみます

image.png

image.png

↓ 選択ボタンを押して

image.png

↓ 行を選択してモーダルの選択ボタンを押します

image.png

できました。