🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Django

DjangoはPythonで書かれた、オープンソースウェブアプリケーションのフレームワークです。複雑なデータベースを扱うウェブサイトを開発する際に必要な労力を減らす為にデザインされました。

Materialize

Materializeは、Googleが提唱するマテリアルデザインのサイト作成ができるCSSのフレームワーク。頻繁に使用されるスタイルが既に定義されており、優れたデザインのページを作成できます。また、レスポンシブWebデザインにも対応可能です。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Ajax

Ajaxとは、Webブラウザ内で搭載されているJavaScriptのHTTP通信機能を使って非同期通信を利用し、インターフェイスの構築などを行う技術の総称です。XMLドキュメントを指定したURLから読み込み、画面描画やユーザの操作などと並行してサーバと非同期に通信するWebアプリケーションを実現することができます。

Q&A

解決済

1回答

2668閲覧

MaterializeのModals内でAjaxを使用したい

KKTN

総合スコア11

Django

DjangoはPythonで書かれた、オープンソースウェブアプリケーションのフレームワークです。複雑なデータベースを扱うウェブサイトを開発する際に必要な労力を減らす為にデザインされました。

Materialize

Materializeは、Googleが提唱するマテリアルデザインのサイト作成ができるCSSのフレームワーク。頻繁に使用されるスタイルが既に定義されており、優れたデザインのページを作成できます。また、レスポンシブWebデザインにも対応可能です。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Ajax

Ajaxとは、Webブラウザ内で搭載されているJavaScriptのHTTP通信機能を使って非同期通信を利用し、インターフェイスの構築などを行う技術の総称です。XMLドキュメントを指定したURLから読み込み、画面描画やユーザの操作などと並行してサーバと非同期に通信するWebアプリケーションを実現することができます。

0グッド

0クリップ

投稿2019/07/02 13:15

前提・実現したいこと

Djangoのテンプレートでmodelのデータ一覧を表示し、チェックボックスで選択したデータを削除するページ(index.html)を作成しています。
削除前の確認ダイアログを当初tkinterで簡易表示していましたが、Materializeのモーダルに変更することになりました。

  • チェックボックスの値をPOSTで受け取り、削除対象データ一覧を表示するページ(answer.html)を更新

  • 「削除する」ボタンクリックで、モーダルタグの内部にanswer.htmlをAjaxで読み込み、モーダルウィンドウで削除確認画面を表示

上記のような動作にしたかったのですが、試したところボタンクリック1回ではanswer.htmlが読み込まれただけで、モーダルは非表示のままでした。同じボタンをもう1回クリックしないとモーダルが表示されません。

2回クリックしなければならない以外は一応希望の動作ではありますが、クリックの問題がなかなか解消できません。
ワンクリックでAjaxとモーダル両方を起動する方法がありましたら、ご教示いただけないでしょうか。
よろしくお願いいたします。

発生している問題・エラーメッセージ

クリック1回ではAjaxが読み込まれるだけでモーダルが表示されず、同じボタンをもう1回クリックしなければならない。

該当のソースコード

HTML

1templates/index.html 2 3<html> 4<head> 5<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css"> 6</head> 7<body> 8 <form id="fm_del_ids" name="fm_del_ids" action="answer" method="POST"> 9 {% csrf_token %} 10 11 <table> 12 {% for item in log %} 13 <tr> 14 <td> 15 <label> 16 <input type="checkbox" class="filled-in" name="del_ids" value="{{item.id}}" /> 17 <span></span> 18 </label> 19 </td> 20 <td>{{item.id}}</td> 21 <td>{{item.name}}</td> 22 <td>{{item.group}}</td> 23 </tr> 24 {% endfor %} 25 </table> 26 27 <!-- Modal Trigger --> 28 <button id="btn_del" data-target="modal1" class="btn modal-trigger" type="submit"> 29 チェックしたデータを削除する 30 </button> 31 </form> 32 33 <span id="div_response"></span> 34 35<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script> 36<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script> 37 38<script> 39$("#fm_del_ids").submit(function(event) { 40 event.preventDefault(); 41 var form = $(this); 42 $.ajax({ 43 url: form.prop("action"), 44 method: form.prop("method"), 45 data: form.serialize(), 46 timeout: 10000, 47 dataType: "html", 48 }) 49 .done(function(data) { 50 $("#div_response").html(data); 51 }) 52 }); 53</script> 54 55</body> 56</html>

HTML

1templates/answer.html 2 3 <!-- Modal Structure --> 4 <div id="modal1" class="modal"> 5 <div class="modal-content"> 6 <form method="POST" name="del_comp" action="{% url 'index' %}"> 7 {% csrf_token %} 8 <input type="hidden" name="del_key" value="{{res}}"> 9 10 <p>以下のデータを本当に削除しますか?</p> 11 <table> 12 {% for item in del_log %} 13 <tr> 14 <td>{{item.id}}</td> 15 <td>{{item.name}}</td> 16 <td>{{item.group}}</td> 17 </tr> 18 {% endfor %} 19 </table> 20 <button type="submit">本当に削除する</button> 21 </form> 22 </div> 23 <div class="modal-footer"> 24 <a href="" class="modal-close waves-effect waves-green btn">閉じる</a> 25 </div> 26 </div> 27 28<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script> 29<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script> 30 31<script> 32$(document).ready(function(){ 33 $('.modal').modal(); 34}); 35</script>

Django

1view.py 2 3from django.shortcuts import render 4from .models import test_log 5 6def index(request): 7 log = test_log.objects.all() 8 9 if request.POST == "POST": 10 del_list = request.POST['del_key'].split(',') 11 del_obj = test_log.objects.filter(id__in=del_list) 12 del_obj.delete() 13 14 params={ 15 "log":log, 16 } 17 return render(request, "index.html",params) 18 19def answer(request): 20 select_ids = request.POST.getlist("del_ids") 21 del_log = test_log.objects.filter(id__in=select_ids) 22 res = ",".join(select_ids) 23 24 params={ 25 "del_log":del_log, 26 "res":res, 27 } 28 return render(request, "answer.html",params) 29 30

Django

1models.py 2 3from django.db import models 4 5class test_log(models.Model): 6 name = models.CharField(max_length=100) 7 group= models.CharField(max_length=100)

Django

1urls.py 2 3from django.urls import path 4from . import views 5 6urlpatterns = [ 7 path('', views.index, name='index'), 8 path("answer", views.answer), 9]

試したこと

内部からクリックイベントかモーダルイベントを起こせないかと思い、Ajaxのところ(doneの最後)で以下を試しましたが、事象は変わりませんでした。

jQuery

1$("#btn_del").click(); 2$("#btn_del").trigger("click"); 3 4$("#modal1").modal("open");

補足情報(FW/ツールのバージョンなど)

Python 3.7.3
Django 2.2.1
jQuery CDNJS 3.4.1
Materialize 1.0.0

動作確認
Chrome 75
Windows10

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

Pythonは詳しくないので、Python観点というより、Materialize観点での回答です。(あと自身が対応可能なPHPならどうするか、という感じ)

原因と思われること:
動的にモーダル用のHTMLが追加されるようになっているので「1回目のクリックで画面内に追加されて、2回目のクリックで認識する」ようになっている。

対策案:その1。Ajaxでは必要なデータだけ取得する

下記は最初からindex.htmlに置いておく

html

1 <div id="modal1" class="modal"> 2 <div class="modal-content"> 3 4 </div> 5 <div class="modal-footer"> 6 <a href="" class="modal-close waves-effect waves-green btn">閉じる</a> 7 </div> 8 </div>

もっと言えば、Ajax実行先のプログラムではHTMLガッツリではなく「データだけ返却する」ようにする。
おそらく{% url 'index' %}とか{% csrf_token %}はAjaxじゃなくても取ってこれると思うので、最初から入れておくのは可能と思います。
つまり、{% for item in del_log %}の内容だけで充分とも言えます。
データをJSONで返して、tableをJavaScriptで組むようにすると良いと思います。

というのをまとめると最初からindex.htmlには下記は持っておいても良いと思います。

html

1 <div id="modal1" class="modal"> 2 <div class="modal-content"> 3 <form method="POST" name="del_comp" action="{% url 'index' %}"> 4 {% csrf_token %} 5 <input type="hidden" name="del_key" value="{{res}}"> 6 7 <p>以下のデータを本当に削除しますか?</p> 8 <table id="confirmList"> 9 </table> 10 <button type="submit">本当に削除する</button> 11 </form> 12 </div> 13 <div class="modal-footer"> 14 <a href="" class="modal-close waves-effect waves-green btn">閉じる</a> 15 </div> 16 </div> 17

table#confirmListに対して<tr>~~</tr>を対象のデータ数だけ追加して行くように作る感じですね。
index.htmlに最初から.modalが存在することになるので、$('.modal').modal();もindex.htmlに置いておけば良いです。

対策案:その2。意図したタイミングでモーダルを付与する

data-targetがなくてもmodal('open')を使えば自身が意図するタイミングで立ち上げが可能なはずなので、ボタンのdata-target属性と.modal-triggerは不要で、
index.htmlのAjaxのdoneにて下記のように書けばいけそうに思います(未検証です)

js

1.done(function(data) { 2 $("#div_response").html(data); 3 $('.modal').modal(); 4 $("#modal1").modal("open"); 5}) 6

私としては「その1」だけだとデータ取得するまで空のモーダルが出ていることになるので、1と2の合わせ技が良いようにいは思います。

いずれにしても対応が必要なこと。

answer.htmlある下記一式は不要

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script> <script> $(document).ready(function(){ $('.modal').modal(); }); </script>

Materialize本体とjQueryがバッティングすることにもなりますしね。

投稿2019/07/03 01:51

m.ts10806

総合スコア80875

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

KKTN

2019/07/03 15:48

対策案その1「モーダルタグをindex.htmlに置く」と、対策案その2「modal('open')を使用する」を合わせたところ、ワンクリックでモーダルが開くようになりました! 現時点ではanswerがHTMLのままですが、アドバイスをいただいたJSON形式の送受信について、Djangoでの方法を調べて置き換えたいと思います。 いろいろ触りはじめたばかりで応用できずにいたので、本当に助かりました。丁寧なご回答をいただき、ありがとうございました。
m.ts10806

2019/07/03 20:13

ヒントになったようで何よりです
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問