Javascript(jQuery)でBootstrap4のモーダルを表示・非表示

jQueryでbootstrap4のモーダルを表示・非表示する方法。

表示


  1. $('#my_modal').modal();



非表示


  1. $('#my_modal').modal('hide');




全体のサンプル


  1. <html lang="ja">
  2. <head>
  3.     <meta charset="UTF-8">
  4.     <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css">
  5.     <title>modal</title>
  6. </head>
  7. <body>
  8.     <button id="modal_show">表示</button>
  9.     <div class="modal" tabindex="-1" role="dialog" id="my_modal">
  10.         <div class="modal-dialog" role="document">
  11.             <div class="modal-content">
  12.                 <div class="modal-header">
  13.                     <h5 class="modal-title">モーダルのタイトル</h5>
  14.                     <button type="button" class="close" data-dismiss="modal" aria-label="閉じる">
  15.                         <span aria-hidden="true">×</span>
  16.                     </button>
  17.                 </div><!-- /.modal-header -->
  18.                 <div class="modal-body">
  19.                     <p>サンプル</p>
  20.                 </div><!-- /.modal-body -->
  21.                 <div class="modal-footer">
  22.                 <button type="button" class="btn btn-secondary" data-dismiss="modal">閉じる(デフォルト)</button>
  23.                 <button type="button" class="btn btn-primary" id="modal_close">閉じる(スクリプト)</button>
  24.                 </div><!-- /.modal-footer -->
  25.             </div><!-- /.modal-content -->
  26.         </div><!-- /.modal-dialog -->
  27.     </div><!-- /.modal -->
  28. <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
  29. <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js"></script>
  30. <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js"></script>
  31. <script>
  32. $(function() {
  33.     $('#modal_show').on('click', function() {
  34.         $('#my_modal').modal();
  35.     });
  36.     $('#modal_close').on('click', function() {
  37.         $('#my_modal').modal('hide');
  38.     });
  39. })
  40. </script>
  41. </body>
  42. </html>




【参考URL】
How to hide Bootstrap modal with javascript?

Riot.js 4 + Bootstrap 4のモーダルダイアログをriot.tagで定義

jQueryでボタンクリックを取得し、riot.tagにデータを設定してみました。
Riot.js 4 + jQuery ボタンクリックをjQueryで取得し、Riotタグに値を渡す

jQuery同様、Bootstrapもよく使用されるライブラリだと思います。
Bootstrapのダイアログをriot.tagで定義。
表示するデータをjQueryから設定できるか試してみます。


jQuery + Bootstrapでのサンプル



まず、jQuery + Bootstrapのみのサンプルです。
モーダル画面で値を更新させる際、初期値を与えた後表示させたいようなパターンはよくあるかと思います。

・index.html


  1. <html lang="ja">
  2. <head>
  3.     <meta charset="UTF-8">
  4.     <title>jquery sample</title>
  5.     <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
  6. </head>
  7. <body>
  8.     <div><input type="button" value="ダイアログ表示" id="show"></div>
  9.     <!-- ダイアログ -->
  10.     <div class="modal" id="example" tabindex="-1" role="dialog">
  11.         <div class="modal-dialog" role="document">
  12.             <div class="modal-content">
  13.             <div class="modal-header">
  14.                 <h5 class="modal-title" id="title">(タイトル)</h5>
  15.                 <button type="button" class="close" data-dismiss="modal" aria-label="Close">
  16.                 <span aria-hidden="true">×</span>
  17.                 </button>
  18.             </div>
  19.             <div class="modal-body">
  20.                 <p id="message">(メッセージ)</p>
  21.             </div>
  22.             <div class="modal-footer">
  23.                 <button type="button" class="btn btn-primary">Save changes</button>
  24.                 <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
  25.             </div>
  26.             </div>
  27.         </div>
  28.     </div>
  29. <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
  30. <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"></script>
  31. <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>
  32. <script>
  33. $(function() {
  34.     // jQueryでボタンクリックを取得
  35.     $('#show').on('click', function() {
  36.         // 表示する前にタイトルとメッセージを設定
  37.         $('#title').html('ダイアログタイトル')
  38.         $('#message').html('メッセージ')
  39.         $('#example').modal('show')
  40.     })
  41. })
  42. </script>
  43. </body>




動作は単純にボタンを押したらモーダルダイアログが表示されるだけです。

989_01.png

989_02.png

表示前に書き換える箇所が増えると面倒なので、ダイアログの定義部分を
まるごとriot.tagに変更したい。



Riot.js



ダイアログ部分をRiot.jsのタグで宣言します。

・index.html


  1. <html lang="ja">
  2. <head>
  3.     <meta charset="UTF-8">
  4.     <title>riot sample</title>
  5.     <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
  6. </head>
  7. <body>
  8.     <div><input type="button" value="ダイアログ表示" id="show"></div>
  9.     <!-- タグの表示位置 -->
  10.     <my-dialog />
  11.     <!-- タグの定義ファイルを指定 -->
  12.     <script src="my-dialog.riot" type="riot"></script>
  13. <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
  14. <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"></script>
  15. <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>
  16. <script src="https://cdnjs.cloudflare.com/ajax/libs/riot/4.1.1/riot+compiler.min.js"></script>
  17. <script>
  18. (async function main() {
  19.     await riot.compile()
  20.     const mydialog = riot.mount('my-dialog')
  21.     // jQueryでボタンクリックを取得
  22.     $('#show').on('click', function() {
  23.         // 表示する前にタイトルとメッセージを設定
  24.         mydialog[0].update({title:'Riotダイアログタイトル', message:'Riotメッセージ'})
  25.         $('#example').modal('show')
  26.     })
  27. }())
  28. </script>
  29. </body>




・my-dialog.riot


  1. <my-dialog>
  2.     <!-- ダイアログ -->
  3.     <div class="modal" id="example" tabindex="-1" role="dialog">
  4.         <div class="modal-dialog" role="document">
  5.             <div class="modal-content">
  6.             <div class="modal-header">
  7.                 <h5 class="modal-title">{ state.title }</h5>
  8.                 <button type="button" class="close" data-dismiss="modal" aria-label="Close">
  9.                 <span aria-hidden="true">×</span>
  10.                 </button>
  11.             </div>
  12.             <div class="modal-body">
  13.                 <p>{ state.message }</p>
  14.             </div>
  15.             <div class="modal-footer">
  16.                 <button type="button" class="btn btn-primary">Save changes</button>
  17.                 <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
  18.             </div>
  19.             </div>
  20.         </div>
  21.     </div>
  22. </my-dialog>




動作はjQuery版と変わりません。

989_03.png

989_04.png

これで随分便利になりました。



show_modal



データの設定とダイアログ表示部分をriot.tag部分に移動することで、もう少しスッキリできそうです。

my-dialog.riot側にデータ設定&モーダル表示を行うメソッドを定義。
jQueryからは作成したメソッドを呼び出して、データの設定とモーダル表示を行ってみます。

・index.html


  1. <html lang="ja">
  2. <head>
  3.     <meta charset="UTF-8">
  4.     <title>riot sample</title>
  5.     <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
  6. </head>
  7. <body>
  8.     <div><input type="button" value="ダイアログ表示" id="show"></div>
  9.     <!-- タグの表示位置 -->
  10.     <my-dialog />
  11.     <!-- タグの定義ファイルを指定 -->
  12.     <script src="my-dialog.riot" type="riot"></script>
  13. <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
  14. <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"></script>
  15. <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>
  16. <script src="https://cdnjs.cloudflare.com/ajax/libs/riot/4.1.1/riot+compiler.min.js"></script>
  17. <script>
  18. (async function main() {
  19.     await riot.compile()
  20.     const mydialog = riot.mount('my-dialog')
  21.     // jQueryでボタンクリックを取得
  22.     $('#show').on('click', function() {
  23.         // 表示する前にタイトルとメッセージを設定
  24.         //mydialog[0].update({title:'Riotダイアログタイトル', message:'Riotメッセージ'})
  25.         //$('#example').modal('show')
  26.         mydialog[0].show_modal({title:'ダイアログタイトル', message:'メッセージ'})
  27.     })
  28. }())
  29. </script>
  30. </body>




・my-dialog.riot


  1. <my-dialog>
  2.     <!-- ダイアログ -->
  3.     <div class="modal" id="example" tabindex="-1" role="dialog">
  4.         <div class="modal-dialog" role="document">
  5.             <div class="modal-content">
  6.             <div class="modal-header">
  7.                 <h5 class="modal-title">{ state.title }</h5>
  8.                 <button type="button" class="close" data-dismiss="modal" aria-label="Close">
  9.                 <span aria-hidden="true">×</span>
  10.                 </button>
  11.             </div>
  12.             <div class="modal-body">
  13.                 <p>{ state.message }</p>
  14.             </div>
  15.             <div class="modal-footer">
  16.                 <button type="button" class="btn btn-primary">Save changes</button>
  17.                 <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
  18.             </div>
  19.             </div>
  20.         </div>
  21.     </div>
  22.     <script>
  23.     export default {
  24.         show_modal(data) {
  25.             this.update(data)
  26.             $('#example').modal('show')
  27.         }
  28.     }
  29.     </script>
  30. </my-dialog>




これでupdateとshowを別々に呼ばなくて良くなりました。

Riot.js 4 + jQuery ボタンクリックをjQueryで取得し、Riotタグに値を渡す

既存のjQueryを利用したアプリケーション。
ajaxでデータを取得し、テーブルに表示する処理を書くのが面倒なので、
表示部分だけRiotの機能を利用したい。

サンプル



ポイントは
・riot.mountした戻り値のコンポーネントを大切にとっておく
・updateメソッドで変更後のデータを渡す
・riot tagではstateオブジェクトを介してデータを取得する


・index.html


  1. <html lang="ja">
  2. <head>
  3. <meta charset="UTF-8">
  4.     <title>riot sample</title>
  5. </head>
  6. <body>
  7.     <div><input type="button" value="データ表示" id="show"></div>
  8.     <!-- タグの表示位置 -->
  9.     <my-tag></my-tag>
  10.     <!-- タグの定義ファイルを指定 -->
  11.     <script src="my-tag.riot" type="riot"></script>
  12. <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
  13. <script src="https://cdnjs.cloudflare.com/ajax/libs/riot/4.1.1/riot+compiler.min.js"></script>
  14. <script>
  15. (async function main() {
  16.     await riot.compile()
  17.     // mountした戻り値のコンポーネントを保持
  18.     // コンポーネントは配列であることに注意
  19.     const mytag = riot.mount('my-tag')
  20.     // jQueryでボタンクリックを取得
  21.     $('#show').on('click', function() {
  22.         // テーブルに表示するデータ
  23.         const items = [
  24.             {id:1, name:'初めての'},
  25.             {id:2, name:'Riot'}
  26.         ];
  27.         // コンポーネントは配列
  28.         // 先頭のupdateメソッドにデータを渡す
  29.         mytag[0].update({items:items})
  30.         
  31.     })
  32. }())
  33. </script>
  34. </body>




・my-tag.riot


  1. <my-tag>
  2.     <table>
  3.         <thead>
  4.             <tr>
  5.                 <th>id</th>
  6.                 <th>name</th>
  7.             </tr>
  8.         </thead>
  9.         <tbody>
  10.             <!-- updateで設定された値はstateオブジェクトに配置される -->
  11.             <tr each={ item in state.items }>
  12.                 <td>{item.id}</td>
  13.                 <td>{item.name}</td>
  14.             </tr>
  15.         </tbody>
  16.     </table>
  17. </my-tag>




初期表示

988_01.png

ボタンを押すと、狙い通りテーブルにデータが設定できました。

988_02.png


【参考URL】

コンポーネントオブジェクト

Riot.js 4.1で「riot+compiler.min.js:2 Uncaught (in promise) SyntaxError: Unexpected token (14:8)」

Riot.js 4.0.2では動作するコード。

・index.html


  1. <html lang="ja">
  2. <head>
  3. <meta charset="UTF-8">
  4.     <title>riot sample</title>
  5. </head>
  6. <body>
  7.     <!-- タグの表示位置 -->
  8.     <my-tag></my-tag>
  9.     <!-- タグの定義ファイルを指定 -->
  10.     <script src="my-tag.riot" type="riot"></script>
  11. <script src="https://cdnjs.cloudflare.com/ajax/libs/riot/4.0.2/riot+compiler.min.js"></script>
  12. <script>
  13. (async function main() {
  14. await riot.compile()
  15. riot.mount('my-tag')
  16. }())
  17. </script>
  18. </body>




・my-tag.riot


  1. <my-tag>
  2.     <h3>ボタンクリックで項目追加</h3>
  3.     <slot each={ item in items }>
  4.         <div>項目:<span>{ item.text }</span></div>
  5.     </slot>
  6.     <div><input type="button" value="追加" onclick={ add }></div>
  7.     <script>
  8.     export default {
  9.         
  10.         onBeforeMount(props, state) {
  11.             this.items = []
  12.         }
  13.         add(event) {
  14.             this.items.push({text : 'テキスト追加'})
  15.             this.update()
  16.         }
  17.     }
  18.     </script>
  19. </my-tag>




Riot.js 4.1.1に上げると、エラーになります。


riot+compiler.min.js:2 Uncaught (in promise) SyntaxError: Unexpected token (14:8)






export default



原因は、my-tag.riotのexport defaultに記載したコード


  1. <my-tag>
  2.     <h3>ボタンクリックで項目追加</h3>
  3.     <slot each={ item in items }>
  4.         <div>項目:<span>{ item.text }</span></div>
  5.     </slot>
  6.     <div><input type="button" value="追加" onclick={ add }></div>
  7.     <script>
  8.     export default {
  9.         
  10.         onBeforeMount(props, state) {
  11.             this.items = []
  12.         },
  13.         add(event) {
  14.             this.items.push({text : 'テキスト追加'})
  15.             this.update()
  16.         }
  17.     }
  18.     </script>
  19. </my-tag>



わずかな変化ですが、onBeforeMountとaddの間に「,」が必要です。
4.0系では許容してくれていたのですが、4.1から必須のようですね。

ずいぶんハマったのでメモしておきます。

GraalVM native-imageでJavaのコードを実行可能なバイトコードに変換

GraalVMをUbuntu 18.04にインストールしてみました。
GraalVM Community Edition 19 をUbuntu Server 18.04にインストールする

ドキュメントを見ていると、「native-image」という項目が。
Native Images

動作を確認してみます。


Javaプログラム



native-imageコマンドを利用するため、gu installでnative-imageをインストールします。


$ gu install native-image



サンプルに従い、Javaのプログラムを作成。

・HelloWorld.java


  1. public class HelloWorld {
  2.     public static void main(String[] args) {
  3.         System.out.println("Hello, World!");
  4.     }
  5. }



Javaとしてコンパイルして実行してみます。


$ javac HelloWorld.java
$ java HelloWorld
Hello, World!






Native Images



作成したHelloWorldをnative imageに変換してみます。


$ native-image HelloWorld
Build on Server(pid: 15418, port: 38627)*
[helloworld:15418]    classlist: 1,479.07 ms
[helloworld:15418]        (cap):     689.59 ms
[helloworld:15418]        setup:     923.48 ms
Error: Error compiling query code (in /tmp/SVM-7230892489949457802/PosixDirectives.c).
Compiler command
gcc /tmp/SVM-7230892489949457802/PosixDirectives.c -o /tmp/SVM-7230892489949457802/PosixDirectives
output included error: /tmp/SVM-7230892489949457802/PosixDirectives.c:77:10:
fatal error: zlib.h: そのようなファイルやディレクトリはありません
    C file contents around line 77:
    /tmp/SVM-7230892489949457802/PosixDirectives.c:76: #include <unistd.h>
    /tmp/SVM-7230892489949457802/PosixDirectives.c:77: #include <zlib.h>
    /tmp/SVM-7230892489949457802/PosixDirectives.c:78: #include <arpa/inet.h>
Error: Use -H:+ReportExceptionStackTraces to print stacktrace of underlying exception
Error: Image build request failed with exit status 1



zlibが必要とのこと。
インストールします。


$ sudo apt-get install zlib1g-dev



改めてnative-imageを実行。


$ native-image HelloWorld
Build on Server(pid: 15418, port: 38627)
[helloworld:15418]    classlist:     125.65 ms
[helloworld:15418]        (cap):     754.78 ms
[helloworld:15418]        setup: 1,691.07 ms
[helloworld:15418] (typeflow): 3,383.24 ms
[helloworld:15418]    (objects):     794.57 ms
[helloworld:15418] (features):     137.75 ms
[helloworld:15418]     analysis: 4,373.45 ms
[helloworld:15418]     (clinit):     81.05 ms
[helloworld:15418]     universe:     294.43 ms
[helloworld:15418]     (parse):     757.81 ms
[helloworld:15418]     (inline): 1,192.29 ms
[helloworld:15418]    (compile): 5,584.71 ms
[helloworld:15418]     compile: 7,750.21 ms
[helloworld:15418]        image:     277.84 ms
[helloworld:15418]        write:     83.24 ms
[helloworld:15418]     [total]: 14,700.19 ms




生成されたhelloworldバイナリを実行してみます。


$ ./helloworld
Hello, World!




サンプルのような簡単なプログラムでも、helloworldのファイルサイズは
2.5MBになりました。
もちろん、他のUbuntuにコピーしても動作します。

これはいいですね。
サーバーのログ収集や死活監視クライアントがJava製だと
「このためだけにjreインストールするのはちょっと...」
と思うことがあったので、バイナリ単体で動いてくれると便利です。




native-imageの生成条件



native-imageを生成するときはコンパイルされたclassファイルが存在していれば良く、ソースファイルは不要です。
ということは、他のJVMでコンパイルしたclassファイルでもnative-imageにできるのでは?

別の端末にインストールしているOpenJDKでビルドして試してみます。
ソースファイルを微調整。

・HelloWorld.java


  1. public class HelloWorld {
  2.     public static void main(String[] args) {
  3.         System.out.println("Hello, Symfoware!");
  4.     }
  5. }



classファイル生成


$ javac HelloWorld.java



HelloWorld.classをGraalVMをインストールしている端末にコピー。
native-imageに変換してみます。


$ native-image HelloWorld
Build on Server(pid: 15418, port: 38627)
[helloworld:15418]    classlist:     201.97 ms
Fatal error: java.lang.UnsupportedClassVersionError:
HelloWorld has been compiled by a more recent version of the Java Runtime (class file version 55.0),
this version of the Java Runtime only recognizes class file versions up to 52.0
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:468)
    at java.net.URLClassLoader.access$100(URLClassLoader.java:74)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:369)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:363)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:362)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:348)
    at com.oracle.svm.hosted.NativeImageGeneratorRunner.buildImage(NativeImageGeneratorRunner.java:239)
    at com.oracle.svm.hosted.NativeImageGeneratorRunner.build(NativeImageGeneratorRunner.java:427)
    at com.oracle.svm.hosted.server.NativeImageBuildServer.executeCompilation(NativeImageBuildServer.java:390)
    at com.oracle.svm.hosted.server.NativeImageBuildServer.lambda$processCommand$8(NativeImageBuildServer.java:327)
    at com.oracle.svm.hosted.server.NativeImageBuildServer.withJVMContext(NativeImageBuildServer.java:408)
    at com.oracle.svm.hosted.server.NativeImageBuildServer.processCommand(NativeImageBuildServer.java:324)
    at com.oracle.svm.hosted.server.NativeImageBuildServer.processRequest(NativeImageBuildServer.java:268)
    at com.oracle.svm.hosted.server.NativeImageBuildServer.lambda$serve$7(NativeImageBuildServer.java:228)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)
Error: Image build request failed with exit status 1



やっぱりダメかと思ったのですが、UnsupportedClassVersionErrorですね。
OpenJDKのバージョンを確認すると11でした。


$ java --version
openjdk 11.0.3 2019-04-16
OpenJDK Runtime Environment (build 11.0.3+7-Ubuntu-1ubuntu218.04.1)
OpenJDK 64-Bit Server VM (build 11.0.3+7-Ubuntu-1ubuntu218.04.1, mixed mode, sharing)



OpenJDK 8で改めてビルド。
これでclass file versionsは52になるはずです。


$ /usr/lib/jvm/java-8-openjdk-amd64/bin/javac HelloWorld.java



再度classファイルをコピーして、native-imageを実行。


$ native-image HelloWorld
Build on Server(pid: 15418, port: 38627)
[helloworld:15418]    classlist:     112.44 ms
[helloworld:15418]        (cap):     699.61 ms
[helloworld:15418]        setup:     968.52 ms
[helloworld:15418] (typeflow): 2,372.49 ms
[helloworld:15418]    (objects):     421.86 ms
[helloworld:15418] (features):     77.86 ms
[helloworld:15418]     analysis: 2,913.51 ms
[helloworld:15418]     (clinit):     41.64 ms
[helloworld:15418]     universe:     136.86 ms
[helloworld:15418]     (parse):     414.27 ms
[helloworld:15418]     (inline):     952.17 ms
[helloworld:15418]    (compile): 2,771.61 ms
[helloworld:15418]     compile: 4,336.30 ms
[helloworld:15418]        image:     204.96 ms
[helloworld:15418]        write:     43.26 ms
[helloworld:15418]     [total]: 8,762.90 ms




動いてくれました。


$ ./helloworld
Hello, Symfoware!


プロフィール

Author:symfo
blog形式だと探しにくいので、まとめサイト作成中です。
Symfoware まとめ

PR




検索フォーム

月別アーカイブ