目次
概要
Pythonのflaskフレームワークを使用して、TODOリストを管理するWEBアプリを作成したのでまとめた。
flaskのGET/POSTの方法やセッション等の扱い、Jinjaテンプレートの使い方について、当アプリを作成しながら振り返ることが目的。
今回はJavaScriptを使用してモーダルダイアログを表示する機能を追加した。
尚、実装はJavaScriptのライブラリであるjQueryを使用している。
前提
flaskフレームワークを使用して作成したTODOアプリに対して改修を行う。
あわせて読みたい
概要 Pythonのflaskフレームワークを使用して、TODOリストを管理するWEBアプリを作成したのでまとめた。 flaskのGET/POSTの方法やセッション等の扱い、Jinjaテンプレートの使い方について、当アプリを作成しながら[…]
機能説明
モーダルダイアログ表示機能
・ログアウトボタン押下時、JavaScriptを使用して確認ダイアログを表示する
・削除ボタン押下時、JavaScriptを使用して確認ダイアログを表示する
・確認ダイアログにて「はい」を押下すると、処理を続行する
・確認ダイアログにて「いいえ」または×ボタンを押下すると、処理を中断する
・削除ボタン押下時、JavaScriptを使用して確認ダイアログを表示する
・確認ダイアログにて「はい」を押下すると、処理を続行する
・確認ダイアログにて「いいえ」または×ボタンを押下すると、処理を中断する
対象画面
・TODOトップ画面
・TODO詳細画面
ダイアログ表示機能
画面状態
◆TODOトップ画面



◆TODO詳細画面



ファイル構成
以下の赤文字箇所について、追加修正等を行う。

ログアウトダイアログ表示機能解説
画面側
confirm_modal.html
<div class="modal fade" id="confirmModal" tabindex="-1" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="confirmModalTitle"></h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<p id="confirmModalContent"></p>
</div>
<div class="modal-footer">
<button type="button" id="confirmModalYes" class="btn btn-primary">はい</button>
<button type="button" class="btn btn-secondary modal-close" data-bs-dismiss="modal">いいえ</button>
</div>
</div>
</div>
</div>
ダイアログのひな型となるモーダル部品。
htmlを分離することで、他画面からインクルードしてモーダル部品を参照できる。
top.html
<!-- モーダルエリア -->
{% include 'components/confirm_modal.html' %}
{% endblock %}
{% block extra_js %}
<script src="{{ url_for('static', filename='js/top.js') }}"></script>
{% endblock %}
モーダル画面を使用するため、ダイアログ部品を以下のようにインクルードする。
{% include 'components/confirm_modal.html' %}
また、モーダルダイアログ表示イベントを定義したtop.jsを参照する。
<script src="{{ url_for('static', filename='js/top.js') }}"></script>
JS側
top.js
/**
* ログアウトボタン押下時
*/
$(document).on("click", "#logout", function(e) {
e.preventDefault();
// モーダル情報セット
$("#confirmModalTitle").text("確認");
$("#confirmModalContent").text("ログアウトしてもよろしいですか?");
// モーダルの「はい」押下イベントを定義
$("#confirmModalYes").on("click", function(e){
window.location.href = $("#logout").attr("href");
});
// モーダル表示
let modal = new bootstrap.Modal($("#confirmModal"));
modal.show();
});
ログアウトボタン押下時のイベントを定義。
モーダルのタイトルとメッセージを設定し、ダイアログの「はい」押下時のイベントを動的に定義して、モーダルウィンドを表示する。
※削除確認ダイアログの機能も同じつくりのため、説明は割愛する。
ファイル詳細
confirm_modal.html
<div class="modal fade" id="confirmModal" tabindex="-1" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="confirmModalTitle"></h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<p id="confirmModalContent"></p>
</div>
<div class="modal-footer">
<button type="button" id="confirmModalYes" class="btn btn-primary">はい</button>
<button type="button" class="btn btn-secondary modal-close" data-bs-dismiss="modal">いいえ</button>
</div>
</div>
</div>
</div>
top.html
{% extends "base.html" %}
{% block title %}TODOトップ{% endblock %}
{% block main %}
<div class="container mt-5">
<h2 class="text-center">{{ session["name"] }} さんのタスク一覧</h2>
<a href="{{ url_for('show_create') }}" class="btn btn-primary me-3">タスク登録</a>
<a href="{{ url_for('logout') }}" id="logout" class="btn btn-primary">ログアウト</a>
<div class="card mt-4">
<div class="card-body">
{% for msg in errors %}
<div id="error-message" class="text-danger mb-3">{{ msg }}</div>
{% endfor %}
<table class="table table-striped">
<thead>
<tr>
<th>カテゴリ</th>
<th>タイトル</th>
<th>タスク名</th>
<th>期日</th>
<th>ステータス</th>
<th>アクション</th>
</tr>
</thead>
<tbody>
{% for todo_item in todos %}
<tr>
<td>{{ todo_item["category"] }}</td>
<td>{{ todo_item["title"] }}</td>
<td><a href="{{ url_for('show_detail', t_id=todo_item['id']) }}">{{ todo_item["content"] }}</a></td>
<td>{{ todo_item["due_date"] }}</td>
<td>{{ todo_item["status"] }}</td>
<td><a href="{{ url_for('update_todo_done', t_id=todo_item['id']) }}" class="btn btn-success">完了</a></td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
<!-- モーダルエリア -->
{% include 'components/confirm_modal.html' %}
{% endblock %}
{% block extra_js %}
<script src="{{ url_for('static', filename='js/top.js') }}"></script>
{% endblock %}
detail.html
{% extends "base.html" %}
{% block title %}TODO詳細{% endblock %}
{% block main %}
<div class="container mt-2">
<a href="{{ url_for('top') }}" class="btn btn-primary mb-3">戻る</a>
<h2 class="text-center">TODO詳細</h2>
<div class="card mt-4 border">
<div class="card-body">
<div class="row border p-2 mb-2">
<div class="col-sm-3">
<h5>カテゴリ:</h5>
</div>
<div class="col-sm-9">
<p>{{ todo["category"] }}</p>
</div>
</div>
<div class="row border p-2 mb-2">
<div class="col-sm-3">
<h5>タイトル:</h5>
</div>
<div class="col-sm-9">
<p>{{ todo["title"] }}</p>
</div>
</div>
<div class="row border p-2 mb-2">
<div class="col-sm-3">
<h5>タスク内容:</h5>
</div>
<div class="col-sm-9">
<p>{{ todo["content"] }}</p>
</div>
</div>
<div class="row border p-2 mb-2">
<div class="col-sm-3">
<h5>ステータス:</h5>
</div>
<div class="col-sm-9">
<p>{{ todo["status"] }}</p>
</div>
</div>
<div class="row border p-2 mb-2">
<div class="col-sm-3">
<h5>メモ:</h5>
</div>
<div class="col-sm-9">
{% if todo["memo"] %}
<p>{{ todo["memo"].replace("\r\n", "<br>") | safe }}</p>
{% else %}
<p></p>
{% endif %}
</div>
</div>
<div class="row border p-2 mb-2">
<div class="col-sm-3">
<h5>期日:</h5>
</div>
<div class="col-sm-9">
<p>{{ todo["due_date"] }}</p>
</div>
</div>
<div class="d-flex justify-content-center mt-2">
<a href="{{ url_for('show_edit', t_id=todo['id']) }}" class="btn btn-primary mb-3 me-3">編集する</a>
<a href="{{ url_for('delete_todo', t_id=todo['id']) }}" id="deleteTask" class="btn btn-danger mb-3">削除する</a>
</div>
</div>
</div>
</div>
<!-- モーダルエリア -->
{% include 'components/confirm_modal.html' %}
{% endblock %}
{% block extra_js %}
<script src="{{ url_for('static', filename='js/detail.js') }}"></script>
{% endblock %}
top.js
"use strict";
/**
* ログアウトボタン押下時
*/
$(document).on("click", "#logout", function(e) {
e.preventDefault();
// モーダル情報セット
$("#confirmModalTitle").text("確認");
$("#confirmModalContent").text("ログアウトしてもよろしいですか?");
// モーダルの「はい」押下イベントを定義
$("#confirmModalYes").on("click", function(e){
window.location.href = $("#logout").attr("href");
});
// モーダル表示
let modal = new bootstrap.Modal($("#confirmModal"));
modal.show();
});
detail.js
"use strict";
/**
* 削除ボタン押下時
*/
$(document).on("click", "#deleteTask", function(e) {
e.preventDefault();
// モーダル情報セット
$("#confirmModalTitle").text("タスクの削除");
$("#confirmModalContent").text("タスクを削除します。よろしいですか?");
// モーダルの「はい」押下イベントを定義
$("#confirmModalYes").on("click", function(e){
window.location.href = $("#deleteTask").attr("href");
});
// モーダル表示
let modal = new bootstrap.Modal($("#confirmModal"));
modal.show();
});
