質問をすることでしか得られない、回答やアドバイスがある。

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

新規登録して質問してみよう
ただいま回答率
85.48%
EJS

EJSは、JavaScript用のテンプレートエンジン。HTMLなどのテンプレートテキストにJavaScriptのロジックを記述することができます。また、変数・関数の実行をテンプレートテキスト内に埋め込むことも可能です。

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

Express

ExpressはNode.jsのWebアプリケーションフレームワークです。 マルチページを構築するための機能セットおよびハイブリッドのWebアプリケーションを提供します。

Q&A

解決済

2回答

3839閲覧

node.js + Express + ejs + vis.js でノードを動的に表示したい

police

総合スコア14

EJS

EJSは、JavaScript用のテンプレートエンジン。HTMLなどのテンプレートテキストにJavaScriptのロジックを記述することができます。また、変数・関数の実行をテンプレートテキスト内に埋め込むことも可能です。

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

Express

ExpressはNode.jsのWebアプリケーションフレームワークです。 マルチページを構築するための機能セットおよびハイブリッドのWebアプリケーションを提供します。

0グッド

1クリップ

投稿2019/01/11 08:28

編集2019/01/12 06:12

###vis.jsでノードを表示させたい

vis.jsでノードを表示させたいのですが、最終的にはURLのパラメータを元に中身を動的に表示させたいです。

実際に使用しているvis.jsのサンプルはこちらです。
http://visjs.org/examples/network/nodeStyles/colors.html

colors.htmlのソースを見ると、

javascript

1 // create an array with nodes 2 var nodes = new vis.DataSet([ 3 {id: 1, label:'html color', color: 'lime'}, 4 {id: 2, label:'rgb color', color: 'rgb(255,168,7)'}, 5 {id: 3, label:'hex color', color: '#7BE141'}, 6 {id: 4, label:'rgba color', color: 'rgba(97,195,238,0.5)'}, 7 {id: 5, label:'colorObject', color: {background:'pink', border:'purple'}}, 8 {id: 6, label:'colorObject + highlight', color: {background:'#F03967', border:'#713E7F',highlight:{background:'red',border:'black'}}}, 9 {id: 7, label:'colorObject + highlight + hover', color: {background:'cyan', border:'blue',highlight:{background:'red',border:'blue'},hover:{background:'white',border:'red'}}} 10 ]) 11 12 // create an array with edges 13 var edges = new vis.DataSet([ 14 {from: 1, to: 3}, 15 {from: 1, to: 2}, 16 {from: 2, to: 4}, 17 {from: 2, to: 5}, 18 {from: 2, to: 6}, 19 {from: 4, to: 7}, 20 ]);

とある部分のオブジェクト部分を動的にしたいのです。

node.js、ExpressでMySQLから結果を取得してオブジェクトにしたのですが、それをどうやってindex.ejsに取り込めばいいのかがわかりません。

以下、Expressの/routes/index.js

javascript

1const express = require('express'); 2const router = express.Router(); 3const mysql = require('mysql2/promise'); 4 5const params = { 6 host: "localhost", 7 user: "root", 8 database: "foo" 9}; 10 11const getFunc = async (id) => { 12 const conn = await mysql.createConnection(params); 13 const sql = `SELECT * FROM hoge WHERE id = ?`; 14 const [result] = await conn.query(sql, [id]); 15 conn.end(); 16 17 const obj = { // これを/views/index.ejsのvar nodesに取り込めれば解決 18 id: result[0].fuga_id, 19 label: result[0].fuga_label, 20 title: result[0].fuga_title, 21 color: result[0].fuga_color, 22 shape: 'box' 23 }; 24 25 // var edgesはいったん省略 26 27 return obj; 28}; 29 30main = () => { 31 router.get('/', async (req, res, next) => { 32 let obj; 33 if (req.query.p) obj = await getFunc(req.query.p); 34 res.render('index', { obj: obj }); 35 }); 36}; 37 38main(); 39 40module.exports = router;

サンプルでいうところのcolors.htmlがマルっとExpressのindex.ejsになるのですが、サンプルではvis.jsのJavaScriptをHTMLに直に埋め込んでいると思います。
そこにどうやってnode.jsからの結果を埋め込めばいいのかと。。。

JavaScript同士なのだから簡単に変数を渡せるような気がするのですが、やり方がわからないです。
すみませんが、よろしくお願い致します。

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

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

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

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

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

guest

回答2

0

まずはExpressの/views/index.ejsですが、該当部分を以下のように書いたら動きました。

javascript

1const nodes = new vis.DataSet(<%- JSON.stringify(obj) %>)

教えて頂いた解説は事前に読んでいたのですが、eslintにエラーと言われていたので別の部分のコードのバグに気づかず、できないものだと勘違いしてました。
上記で動きます。

それから/routes/index.jsの該当部分は、上記からとくに修正せず実行できました。

回答で頂いたソースはapp.get()なのですが、当方Expressファイルをexpress-generatorを使用して生成しているので、ファイルの場所が/app.jsではなくて/routes/index.js、app.get()ではなくてrouter.get()になっています。
若干書き方が違っていますが動きは双方同じですので、参考にご覧になっている方がいらしたらご注意ください。

上記は質問用にシンプルなコードに書き起こしたものなので(まだバグってるかも・・・)、下に実際のコードの抜粋を載せておきます。

/routes/index.js

javascript

1const express = require('express') 2const router = express.Router() 3const mysql = require('mysql2/promise') 4const pMap = require('p-map') 5 6const params = { 7 host: 'localhost', 8 user: 'root', 9 database: 'hoge' 10} 11 12const getFunc = async id => { 13 try { 14 const conn = await mysql.createConnection(params) 15 const [result] = await conn.query('SELECT * FROM foo WHERE id = ?', [id]) 16 conn.end() 17 18 let nodesArr = [] 19 let edgesArr = [] 20 21 await pMap( 22 result, 23 async r => { 24 const nodesObj = { 25 id: id, 26 label: r.label, 27 title: r.title, 28 color: r.color, 29 shape: 'box' 30 } 31 nodesArr.push(nodesObj) 32 33 const edgesObj = { 34 from: id, 35 to: r.parent_id, 36 arrows: 'to' 37 } 38 edgesArr.push(edgesObj) 39 }, 40 { concurrency: 1 } 41 ) 42 43 return { nodes: nodesArr, edges: edgesArr } 44 } catch (err) { 45 console.log(err) 46 } 47} 48 49const main = () => { 50 try { 51 router.get('/', async (req, res) => { 52 const obj = await getFunc(req.query.id) 53 const data = { nodes: obj.nodes, edges: obj.edges } 54 res.render('index', data) 55 }) 56 } catch (err) { 57 console.log(err) 58 } 59} 60 61main() 62 63module.exports = router

/views/index.ejsのscript部分のみ

html

1<script> 2// create an array with nodes 3const nodes = new vis.DataSet(<%- JSON.stringify(nodes) %>) 4 5// create an array with edges 6const edges = new vis.DataSet(<%- JSON.stringify(edges) %>) 7 8// create a network 9const container = document.getElementById('mynetwork') 10 11const data = { 12 nodes: nodes, 13 edges: edges 14} 15 16const options = { 17 physics: false, 18 clickToUse: false, 19 nodes: { 20 labelHighlightBold: false, 21 font: { 22 size: 14, 23 color: '#fff' 24 } 25 }, 26 edges: { 27 smooth: { 28 type: 'vertical', 29 forceDirection: 'vertical', 30 roundness: 0.5 31 } 32 }, 33 layout: { 34 randomSeed: 0 35 } 36} 37 38const network = new vis.Network(container, data, options) 39</script>

投稿2019/01/12 07:07

police

総合スコア14

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

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

0

ベストアンサー

ちょっとasync/await病にかかってますね。
これを使うのはPromiseを利用する瞬間だけです。

例えばmainは正確に書けばこう、ついでに答えを書きます。

JavaScript

1main = () => { 2 router.get('/', async (req, res, next) => { 3 let obj = {}; // ifで注入するなら先にletで宣言して後から代入するしかない 4 if (req.query.p) { 5 id = req.query.p; 6 obj = await getFunc(id); 7 }; 8 res.render('index', (obj || {})); 9 }); 10};

理由はQiitaの記事で調べたらみつかりました。
Expressにおけるejsの使い方 - Qiita

JavaScript

1app.get("/", function (req, res) { 2 var data = { 3 items: [ 4 {name: "<h1>リンゴ</h1>"}, 5 {name: "<h2>バナナ</h2>"}, 6 {name: "<h3>スイカ</h3>"} 7 ] 8 }; 9 // レンダリングを行う 10 res.render("./index.ejs", data); 11});

そこにどうやってnode.jsからの結果を埋め込めばいいのかと。。。

混乱してそうなので明記しておきますが、Webサーバの処理順番は下記です。

  1. Chrome等のブラウザがWebサーバにHTTPリクエストを送信する
  2. WebサーバはHTTPレスポンスとしてHTML(文字列)を返す
  3. Chromeは受け取ったHTMLをロードして読み込む
  4. HTMLの読み込み作業中、<script>タグを検出する事をトリガーに中身のJavaScriptを実行する

Expressで書いているのは2の話ですね。
つまり、一度HTMLという一枚ペラの用紙を作ってブラウザに送り届け、再度解析してもらう必要があります。
Node.jsを使っているからとオブジェクトをオブジェクトのまま渡せないという大問題に遭遇するわけですね。

なので、オブジェクトを一度文字列化(シリアライズ)しなければなりません。
検索したら下記のような記事がヒットしたので、ejsにデータを持ち込んだ後はこれを参考にHTML化してみましょう。
Express and ejs <%= to render a JSON

投稿2019/01/11 09:37

miyabi-sun

総合スコア21158

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

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

police

2019/01/12 07:04

ありがとうございました。やっとできました。 teratail用に急いで書き起こしたコードで、検証していなかったので凡ミスはすみませんでした。 ちょっと修正しました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問