Laravel+Chart.jsで、複数のドロップダウンメニューでの選択に応じて動的にグラフが切り替わる仕組みを作りたいと考えています。
Laravelは6系、
Chart.js:2.9.4です。
全体大まかな流れはこのような形になります。
- ドロップダウンメニューを複数設置
- ドロップダウンで条件を指定する
- 指定されたときに、ajaxで指定された複数の条件をpostする(int形式で送信する)
- コントローラー側でpostされた条件を元にselect文を投げ、一致するレコードのみ抽出する
- JS側でチャートを再描画する
そこで問題なのですが、5の手順まで完了してAjax通信してコントローラーから取得した値をグラフで表現するところまでできましたが、グラフをマウスオーバーすると前回の値が表示されてしまいます。
- ドロップダウンメニューで、「日本」「A型」 と選択すると、動的にグラフが切り替わる
- ドロップダウンメニューで、「アメリカ」「B型」と選択すると、動的にグラフが切り替わる
- グラフをマウスオーバーすると、マウスオーバーの位置によって1と2が両方表示(ちらつき)されてしまう
グラフ.destroy(); で既存のグラフは削除してから再描画しているはずなのですが、ちらつく原因が分からずつまづいています。
こちらの原因に関しまして、ご教示いただけますと幸いです。
【テーブル定義】
testuserテーブル
カラム | 概要 |
---|---|
- id | id |
- blood | int |
- country_id | 国籍テーブル切り出し |
- 家賃 | int |
countriesテーブル
カラム名 | 概要 |
---|---|
id | id |
country | 国名 |
// blade.php <select name="country" id="country"> <option value="1">日本</option> <option value="2">アメリカ</option> </select> <select name="blood" id="blood"> <option value="1">A</option> <option value="2">B</option> </select> <canvas id="myBarChart"></canvas>
//script部分 <script> // カレンダー初期表示 var ctx = document.getElementById("myBarChart"); var myBarChart = new Chart(ctx, { type: "bar", data: { labels: ["条件に一致するレコードの家賃の合計"], datasets: [ { label: "売上", data: [], backgroundColor: "rgba(219,39,91,0.5)", }, ], }, options: { title: { display: true, text: "売上", }, scales: { yAxes: [ { ticks: { suggestedMax: 100, suggestedMin: 0, stepSize: 10, callback: function (value, index, values) { return "¥" + value; }, }, }, ], }, }, }); // 国籍のドロップダウンメニューを取得 var dropDown = document.getElementById("country"); // もし、ドロップダウンメニューが選択されたら dropDown.onchange = function () { var country = $(this).val(); // countryの選択値を取得 var blood = $("#blood").val(); // bloodの選択値を取得 $.ajaxSetup({ headers: { "X-CSRF-TOKEN": $('meta[name="csrf-token"]').attr("content"), }, }); $.ajax({ //POST通信 type: "post", //ここでデータの送信先URLを指定します。 url: "/getcharts", dataType: "json", data: { country: country, //ドロップダウンの選択値を送信 blood: blood, }, }) //通信が成功したとき .then((res) => { if(myBarChart){ myBarChart.destroy(); } // レスポンスの結果(連想配列)から、「家賃」のところだけ合計する const total = res.reduce((sum, i) => sum + i.house_money, 0); // グラフ再描画 var myBarChart = new Chart(ctx, { type: "bar", data: { labels: ["条件に一致するレコードの家賃の合計"], datasets: [ { label: "売上", data: [total], // レスポンスの結果(家賃だけ合計した値) backgroundColor: "rgba(219,39,91,0.5)", }, ], }, options: { title: { display: true, text: "売上", }, scales: { yAxes: [ { ticks: { suggestedMax: 100, suggestedMin: 0, stepSize: 10, callback: function (value, index, values) { return "¥" + value; }, }, }, ], }, }, }); }) //通信が失敗したとき .fail((error) => { console.log(error); }) }; // 血液型のドロップダウンメニューを取得 var dropDown = document.getElementById("blood"); // もし、ドロップダウンメニューが選択されたら dropDown.onchange = function () { var country = $("#country").val(); // countryの選択値を取得 var blood = $(this).val(); // bloodの選択値を取得 $.ajaxSetup({ headers: { "X-CSRF-TOKEN": $('meta[name="csrf-token"]').attr("content"), }, }); $.ajax({ //POST通信 type: "post", //ここでデータの送信先URLを指定します。 url: "/getcharts", dataType: "json", data: { country: country, blood: blood, }, }) //通信が成功したとき .then((res) => { if(myBarChart){ myBarChart.destroy(); } // レスポンスの結果(連想配列)から、「家賃」のところだけ合計する const total = res.reduce((sum, i) => sum + i.house_money, 0); // グラフ再描画 var myBarChart = new Chart(ctx, { type: "bar", data: { labels: ["条件に一致するレコードの家賃の合計"], datasets: [ { label: "売上", data: [total], // レスポンスの結果(家賃だけ合計した値) backgroundColor: "rgba(219,39,91,0.5)", }, ], }, options: { title: { display: true, text: "売上", }, scales: { yAxes: [ { ticks: { suggestedMax: 100, suggestedMin: 0, stepSize: 10, callback: function (value, index, values) { return "¥" + value; }, }, }, ], }, }, }); }) //通信が失敗したとき .fail((error) => { console.log(error); }) }; </script>
// Controller部分 public function getCharts(Request $request) { // ドロップダウンメニューの選択の結果から、当てはまるレコードのみを抽出 $country = $request->country; $blood = $request->blood; $house_money = Testuser::where("country_id", "=", $country) ->where("blood", "=", $blood)->get(); return $house_money; //JS側に値を返却 }
回答1件
あなたの回答
tips
プレビュー