概要
Pythonのflaskフレームワークを使用して、TODOリストを管理するWEBアプリを作成したのでまとめた。
flaskのGET/POSTの方法やセッション等の扱い、Jinjaテンプレートの使い方について、当アプリを作成しながら振り返ることが目的。
今回はJavaScriptを使用してモーダルダイアログを表示する機能を追加した。
尚、実装はJavaScriptのライブラリであるjQueryを使用している。
前提
flaskフレームワークを使用して作成したTODOアプリに対して改修を行う。
概要 Pythonのflaskフレームワークを使用して、TODOリストを管理するWEBアプリを作成したのでまとめた。 flaskのGET/POSTの方法やセッション等の扱い、Jinjaテンプレートの使い方について、当アプリを作成しながら[…]
機能説明
モーダルダイアログ表示機能
・削除ボタン押下時、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(); });