javascript - 单击按钮时图表不呈现 w/Chart.js

标签 javascript chart.js

我有一个网络应用程序,它向用户展示一个表单,用于使用 Chart.js 绘制图表。

我在单击按钮时收集表单数据,正确设置格式,然后要呈现图表。

代码如下:

// /public/main.js
const chartData = {
  labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
  datasets: [{
    label: '# of Votes',
    data: [12, 19, 3, 16, 2, 3],
    backgroundColor: [
      'rgba(255, 99, 132, 0.2)',
      'rgba(54, 162, 235, 0.2)',
      'rgba(255, 206, 86, 0.2)',
      'rgba(75, 192, 192, 0.2)',
      'rgba(153, 102, 255, 0.2)',
      'rgba(255, 159, 64, 0.2)'
    ]
  }]
};
const barOptions = {
  scales: {
    yAxes: [{
      ticks: {
        beginAtZero: true
      }
    }]
  }
};

const ctx = document.getElementById("myChart").getContext('2d');

const myChart = new Chart(ctx, {
  type: 'bar',
  data: chartData,
  options: barOptions
});
// Get Chart Info from form

$(document).ready(function() {
  $("#render_btn").on("click", function(e) {
    e.preventDefault();

    // First grab form data off the page
    const formData = $("form").serializeArray();
    // Get Chart Type Seperate from Form Data
    const chartType = document.getElementById('chart_type').value;

    // Create a data Object for Chart constructor to use
    const chartData = {
      datasets: []
    };
    let datasetsItem = {};

    // Convert formData array to chartData object
    formData.forEach(function(value, index) {
      if (formData[index].name == 'labels') {
        chartData[(formData[index].name)] = formData[index].value;
      } else {
        datasetsItem[formData[index].name] = formData[index].value;
        chartData.datasets[0] = datasetsItem;
      }
    });

    // Now we have to do some converting i.e., chartData.labels must be
    // converted to array from string etc
    chartData.datasets[0].backgroundColor = splitString(chartData.datasets[0].backgroundColor);
    chartData.datasets[0].data = strToNumberArray(chartData.datasets[0].data);
    chartData.labels = splitString(chartData.labels);

    // Check if succesful
    try {
      if (!(chartData.datasets[0].backgroundColor) || !(chartData.datasets[0].data) || !(chartData.labels)) {
        throw new Error("Input Error. Recheck your form data.");
      }

      myChart.update({
        type: chartType,
        data: chartData

      });
    } catch (error) {
      alert(error);
    }


    // ============================================================= //
    // ============= Function definitions ========================== //
    // ============================================================= //
    function splitString(strToSplit, separator = ',') {
      if (strToSplit === undefined) {
        console.log("Error: splitString is empty.");
        return "";
      }

      // Test for a comma in the string
      const result = /,+/.test(strToSplit);
      if (!result) {
        alert(`Comma delimiter missing from ${strToSplit}`);
        return false;
      }

      // Split a string into an array and trim any whitespace
      let arrayOfStrings = strToSplit.split(separator);
      arrayOfStrings.forEach(function(value, index) {
        arrayOfStrings[index] = value.trim();
      });

      return arrayOfStrings;
    }

    // Function to convert string to an array then convert each element to a number
    function strToNumberArray(str, separator = ',') {
      if (str === undefined) {
        alert('Error: string is empty.');
        return "";
      }
      // Test for a comma in the string
      const result = /,+/.test(str);
      if (!result) {
        alert(`Comma delimiter missing from ${str}`);
        return false;
      }

      let arrayOfNumbers = str.split(separator).map(Number);

      return arrayOfNumbers;
    }

    // ============================================================== //
    // ================== End Function Definitions ================== //
    // ============================================================== //
  }); // .on "click"
});
<script src="https://code.jquery.com/jquery-3.2.1.min.js" integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" crossorigin="anonymous"></script>

<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>

<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.1/Chart.bundle.min.js"></script>

<canvas id="myChart" width="400" height="400"></canvas>

<h2>Input your values:</h2>
<!-- Chart Input Form -->
<!-- We dont want chart_type as part of form when we use serializeArray
        gather the data and use in chartData object -->
<div class="row">
  <div class="col-md-4 col-md-offset-4">
    <div class="form-group">
      <label for="chart_type">Chart Type</label>
      <input type="text" name="type" class="form-control" id="chart_type" placeholder="Chart Type">
    </div>
  </div>
</div>

<form>
  <div class="row">
    <div class="col-md-4 col-md-offset-4">
      <div class="form-group">
        <label for="chart_Label">Chart Label</label>
        <input type="text" name="label" class="form-control" id="chart_Label" placeholder="Chart Label">
      </div>
    </div>
  </div>

  <div class="row">
    <div class="col-md-6 col-md-offset-4">
      <div class="form-group">
        <label for="chart_labels">Chart Labels</label>
        <input type="text" name="labels" class="form-control" id="chart_labels" placeholder="Apr, May, June Note:Seperated by Commas">
      </div>
    </div>
  </div>

  <div class="row">
    <div class="col-md-6 col-md-offset-4">
      <div class="form-group">
        <label for="chart_data">Chart Data</label>
        <input type="text" name="data" class="form-control" id="chart_data" placeholder="i.e., 25 44 60 etc">
      </div>
    </div>
  </div>

  <div class="row">
    <div class="col-md-6 col-md-offset-4">
      <div class="form-group">
        <label for="chart_colors">Chart Colors</label>
        <input type="text" name="backgroundColor" class="form-control" id="chart_colors" placeholder="i.e., red, blue, yellow, purple">
      </div>
    </div>
  </div>
  <div class="row">
    <div class="col-md-4 col-md-offset-5">
      <button class="btn btn-primary btn-lg" id="render_btn">Render Graph</button>
    </div>
  </div>
</form>

当我点击按钮时,我什么也得不到。

如果我用一些数据填充图表数据对象并全局声明一个新的 myChart 然后在页面加载时图表呈现 OK 但我添加的任何新数据然后单击表单按钮会立即呈现然后消失(!?)

理想情况下,我想要一个空白 Canvas ,让用户输入数据,然后单击渲染按钮并生成图表。我在网上看过,但没有找到任何涉及表单和事件处理程序的内容。

我查看了 Chart.js 文档并尝试使用他们的示例,但无济于事 w/update 和 render。

非常感谢任何帮助...

更新:OK 片段运行时出现了我遇到的问题。当您填写表格并单击渲染时,我什么也得不到。谢谢我从未使用过片段。任何人都可以使用它吗? 附言- 我将 e.preventDefault 添加到代码片段中,认为默认操作可能会干扰 Chart.js。不好。此外,所有值都应以逗号分隔。

最佳答案

update 函数的文档如下:

Triggers an update of the chart. This can be safely called after updating the data object. This will update all scales, legends, and then re-render the chart.

因此您必须更新数据对象,而不是在 update 方法中传递更新的数据对象。该方法只接受这些属性:

  • 持续时间
  • 懒惰
  • 缓和

在您的示例中,您必须更改以下代码:

myChart.update({
   type: chartType,
   data: chartData
});

myChart.type = chartType;
myChart.data = chartData;
myChart.update();

以下是您的更改代码段:

// /public/main.js
const chartData = {
  labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
  datasets: [{
    label: '# of Votes',
    data: [12, 19, 3, 16, 2, 3],
    backgroundColor: [
      'rgba(255, 99, 132, 0.2)',
      'rgba(54, 162, 235, 0.2)',
      'rgba(255, 206, 86, 0.2)',
      'rgba(75, 192, 192, 0.2)',
      'rgba(153, 102, 255, 0.2)',
      'rgba(255, 159, 64, 0.2)'
    ]
  }]
};
const barOptions = {
  scales: {
    yAxes: [{
      ticks: {
        beginAtZero: true
      }
    }]
  }
};

const ctx = document.getElementById("myChart").getContext('2d');

const myChart = new Chart(ctx, {
  type: 'bar',
  data: chartData,
  options: barOptions
});
// Get Chart Info from form

$(document).ready(function() {
  $("#render_btn").on("click", function(e) {
    e.preventDefault();

    // First grab form data off the page
    const formData = $("form").serializeArray();
    // Get Chart Type Seperate from Form Data
    const chartType = document.getElementById('chart_type').value;

    // Create a data Object for Chart constructor to use
    const chartData = {
      datasets: []
    };
    let datasetsItem = {};

    // Convert formData array to chartData object
    formData.forEach(function(value, index) {
      if (formData[index].name == 'labels') {
        chartData[(formData[index].name)] = formData[index].value;
      } else {
        datasetsItem[formData[index].name] = formData[index].value;
        chartData.datasets[0] = datasetsItem;
      }
    });

    // Now we have to do some converting i.e., chartData.labels must be
    // converted to array from string etc
    chartData.datasets[0].backgroundColor = splitString(chartData.datasets[0].backgroundColor);
    chartData.datasets[0].data = strToNumberArray(chartData.datasets[0].data);
    chartData.labels = splitString(chartData.labels);

    // Check if succesful
    try {
      if (!(chartData.datasets[0].backgroundColor) || !(chartData.datasets[0].data) || !(chartData.labels)) {
        throw new Error("Input Error. Recheck your form data.");
      }
      
      myChart.type = chartType;
      myChart.data = chartData;
      myChart.update();
    } catch (error) {
      alert(error);
    }


    // ============================================================= //
    // ============= Function definitions ========================== //
    // ============================================================= //
    function splitString(strToSplit, separator = ',') {
      if (strToSplit === undefined) {
        console.log("Error: splitString is empty.");
        return "";
      }

      // Test for a comma in the string
      const result = /,+/.test(strToSplit);
      if (!result) {
        alert(`Comma delimiter missing from ${strToSplit}`);
        return false;
      }

      // Split a string into an array and trim any whitespace
      let arrayOfStrings = strToSplit.split(separator);
      arrayOfStrings.forEach(function(value, index) {
        arrayOfStrings[index] = value.trim();
      });

      return arrayOfStrings;
    }

    // Function to convert string to an array then convert each element to a number
    function strToNumberArray(str, separator = ',') {
      if (str === undefined) {
        alert('Error: string is empty.');
        return "";
      }
      // Test for a comma in the string
      const result = /,+/.test(str);
      if (!result) {
        alert(`Comma delimiter missing from ${str}`);
        return false;
      }

      let arrayOfNumbers = str.split(separator).map(Number);

      return arrayOfNumbers;
    }

    // ============================================================== //
    // ================== End Function Definitions ================== //
    // ============================================================== //
  }); // .on "click"
});
<script src="https://code.jquery.com/jquery-3.2.1.min.js" integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" crossorigin="anonymous"></script>

<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>

<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.1/Chart.bundle.min.js"></script>

<canvas id="myChart" width="400" height="400"></canvas>

<h2>Input your values:</h2>
<!-- Chart Input Form -->
<!-- We dont want chart_type as part of form when we use serializeArray
        gather the data and use in chartData object -->
<div class="row">
  <div class="col-md-4 col-md-offset-4">
    <div class="form-group">
      <label for="chart_type">Chart Type</label>
      <input type="text" name="type" class="form-control" id="chart_type" placeholder="Chart Type">
    </div>
  </div>
</div>

<form>
  <div class="row">
    <div class="col-md-4 col-md-offset-4">
      <div class="form-group">
        <label for="chart_Label">Chart Label</label>
        <input type="text" name="label" class="form-control" id="chart_Label" placeholder="Chart Label">
      </div>
    </div>
  </div>

  <div class="row">
    <div class="col-md-6 col-md-offset-4">
      <div class="form-group">
        <label for="chart_labels">Chart Labels</label>
        <input type="text" name="labels" class="form-control" id="chart_labels" placeholder="Apr, May, June Note:Seperated by Commas">
      </div>
    </div>
  </div>

  <div class="row">
    <div class="col-md-6 col-md-offset-4">
      <div class="form-group">
        <label for="chart_data">Chart Data</label>
        <input type="text" name="data" class="form-control" id="chart_data" placeholder="i.e., 25 44 60 etc">
      </div>
    </div>
  </div>

  <div class="row">
    <div class="col-md-6 col-md-offset-4">
      <div class="form-group">
        <label for="chart_colors">Chart Colors</label>
        <input type="text" name="backgroundColor" class="form-control" id="chart_colors" placeholder="i.e., red, blue, yellow, purple">
      </div>
    </div>
  </div>
  <div class="row">
    <div class="col-md-4 col-md-offset-5">
      <button class="btn btn-primary btn-lg" id="render_btn">Render Graph</button>
    </div>
  </div>
</form>

关于javascript - 单击按钮时图表不呈现 w/Chart.js,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47914620/

相关文章:

javascript - Chartjs 选项被忽略

javascript - 如何在 Y 轴上显示一定数量的刻度?

charts - 如何在Chart js中向数据集添加偏移量

javascript - Chart.js 条形图 : show tooltip on label hover

javascript - 使用 Google map 发出 AJAX 请求时,使 Highcharts 显示在 infowindow 窗口中

javascript - 如何在js中将html内容添加到静态文本中

javascript - 在鼠标 Y 上更改 2 种背景颜色 + 使 <p> 适应该新颜色

javascript - WebRTC 上的信令 channel

javascript - 递归 'setTimeout' 函数调用最终会杀死 JS 引擎吗?

javascript - 更新 Chart.js 中的数据