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

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

ただいまの
回答率

90.39%

  • Node.js

    2457questions

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

  • Express

    317questions

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

  • EJS

    21questions

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

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 444

police

score 2

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

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

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

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

  // create an array with nodes
  var nodes = new vis.DataSet([
    {id: 1, label:'html color', color: 'lime'},
    {id: 2, label:'rgb color', color: 'rgb(255,168,7)'},
    {id: 3, label:'hex color', color: '#7BE141'},
    {id: 4, label:'rgba color', color: 'rgba(97,195,238,0.5)'},
    {id: 5, label:'colorObject', color: {background:'pink', border:'purple'}},
    {id: 6, label:'colorObject + highlight', color: {background:'#F03967', border:'#713E7F',highlight:{background:'red',border:'black'}}},
    {id: 7, label:'colorObject + highlight + hover', color: {background:'cyan', border:'blue',highlight:{background:'red',border:'blue'},hover:{background:'white',border:'red'}}}
  ])

  // create an array with edges
  var edges = new vis.DataSet([
    {from: 1, to: 3},
    {from: 1, to: 2},
    {from: 2, to: 4},
    {from: 2, to: 5},
    {from: 2, to: 6},
    {from: 4, to: 7},
  ]);


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

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

以下、Expressの/routes/index.js

const express = require('express');
const router = express.Router();
const mysql = require('mysql2/promise');

const params = {
  host: "localhost",
  user: "root",
  database: "foo"
};

const getFunc = async (id) => {
  const conn = await mysql.createConnection(params);
  const sql = `SELECT * FROM hoge WHERE id = ?`;
  const [result] = await conn.query(sql, [id]);
  conn.end();

  const obj = { // これを/views/index.ejsのvar nodesに取り込めれば解決
    id: result[0].fuga_id,
    label: result[0].fuga_label,
    title: result[0].fuga_title,
    color: result[0].fuga_color,
    shape: 'box'
  };

  // var edgesはいったん省略

  return obj;
};

main = () => {
  router.get('/', async (req, res, next) => {
    let obj;
    if (req.query.p) obj = await getFunc(req.query.p);
    res.render('index', { obj: obj });
  });
};

main();

module.exports = router;


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

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

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

0

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

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

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

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

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

そこにどうやって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/12 16:04

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

    キャンセル

0

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

const 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

const express = require('express')
const router = express.Router()
const mysql = require('mysql2/promise')
const pMap = require('p-map')

const params = {
  host: 'localhost',
  user: 'root',
  database: 'hoge'
}

const getFunc = async id => {
  try {
    const conn = await mysql.createConnection(params)
    const [result] = await conn.query('SELECT * FROM foo WHERE id = ?', [id])
    conn.end()

    let nodesArr = []
    let edgesArr = []

    await pMap(
      result,
      async r => {
        const nodesObj = {
          id: id,
          label: r.label,
          title: r.title,
          color: r.color,
          shape: 'box'
        }
        nodesArr.push(nodesObj)

        const edgesObj = {
          from: id,
          to: r.parent_id,
          arrows: 'to'
        }
        edgesArr.push(edgesObj)
      },
      { concurrency: 1 }
    )

    return { nodes: nodesArr, edges: edgesArr }
  } catch (err) {
    console.log(err)
  }
}

const main = () => {
  try {
    router.get('/', async (req, res) => {
      const obj = await getFunc(req.query.id)
      const data = { nodes: obj.nodes, edges: obj.edges }
      res.render('index', data)
    })
  } catch (err) {
    console.log(err)
  }
}

main()

module.exports = router


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

<script>
// create an array with nodes
const nodes = new vis.DataSet(<%- JSON.stringify(nodes) %>)

// create an array with edges
const edges = new vis.DataSet(<%- JSON.stringify(edges) %>)

// create a network
const container = document.getElementById('mynetwork')

const data = {
  nodes: nodes,
  edges: edges
}

const options = {
  physics: false,
  clickToUse: false,
  nodes: {
    labelHighlightBold: false,
    font: {
      size: 14,
      color: '#fff'
    }
  },
  edges: {
    smooth: {
    type: 'vertical',
    forceDirection: 'vertical',
    roundness: 0.5
    }
  },
  layout: {
    randomSeed: 0
  }
}

const network = new vis.Network(container, data, options)
</script>

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 90.39%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • Node.js

    2457questions

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

  • Express

    317questions

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

  • EJS

    21questions