Chartjs-Data is not display in correct order after update

1👍

This is a working example with you data.

Edit romantic-microservice-ziok9

Here is the template code, I used a computed property to sort the array of data instead of sorting the actual data.

Please review the dependencies of the Chart.js package, as time series chart require external date adapters as mentioned here.

Also, there seems to be a Chart.js wrapper for Vue, perhaps you should try it.

    <template>
      <div class="container">
        <div class="row">
          <div class="col" style="position: relative; height: 50vh">
            <canvas id="graphique"></canvas>
          </div>
          <div>
            <h1>Finds</h1>
            <div v-for="(find, index) in finds" v-bind:key="index">
              <input v-model="find.date" />
              <input v-model="find.value" />
              <input v-model="find.label" />
            </div>
            <input v-model="dateToAdd" />
            <input v-model="valueToAdd" />
            <input v-model="labelToAdd" />
            <button @click="addFind">Add cost</button>
            <p v-if="Chart">{{ Chart.data }}</p>
          </div>
        </div>
      </div>
    </template>
    
    <script>
    import Chart from "chart.js/auto";
    import "chartjs-adapter-moment";
    
    export default {
      name: "PlanetChart",
      data() {
        return {
          Chart: null,
          valueToAdd: 20,
          labelToAdd: "A",
          dateToAdd: "12/01/1900",
          finds: [
            { date: "12/01/2020", label: "1", value: 12 },
            { date: "12/01/2021", label: "2", value: 2 },
            { date: "12/01/2000", label: "0", value: 1 },
            { date: "12/01/2023", label: "3", value: 12 },
          ],
        };
      },
      mounted() {
        const ctx = document.getElementById("graphique");
        this.Chart = new Chart(ctx, {
          type: "line",
          data: {
            datasets: [
              {
                label: "US Dates",
                backgroundColor: "#fff",
                borderWidth: 1,
                pointBorderWidth: 1,
                borderColor: "#f00",
                data: this.transformedData,
                fill: false,
                borderColor: "red",
              },
            ],
          },
          options: {
            scales: {
              x: {
                type: "time",
                time: {
                  unit: "month",
                },
              },
            },
          },
        });
      },
      computed: {
        transformedData() {
          const d = this.finds.map((i) => {
            return { x: new Date(i.date), y: i.value };
          });
    
          d.sort(function (a, b) {
            return a.x - b.x;
          });
    
          return d;
        },
      },
      methods: {
        addFind: function () {
          if (this.valueToAdd > 0 && this.labelToAdd !== "") {
            this.finds.push({
              date: this.dateToAdd,
              value: this.valueToAdd,
              label: this.labelToAdd,
            });
            this.finds.sort(function (a, b) {
              return new Date(a.date) - new Date(b.date);
            });
            this.Chart.data.datasets[0].data = this.transformedData;
            console.log(this.Chart.data.datasets[0].data);
            this.Chart.update();
            this.valueToAdd = 0;
            this.dateToAdd = "";
            this.labelToAdd = "";
          }
        },
      },
    };
    </script>

1👍

So without using a computed method is it possible to do it simply by using the
import "chartjs-adapter-moment";
as Juand David mentioned. And don’t forget to convert the string in Date.

Here is my solution :

    <template>
      <div class="container">
        <div class="row">
          <div class="col">
            <canvas id="graphique"></canvas>
          </div>
        </div>
        <div class="row">
          <div class="col-xxs">
            <h1>Mes catégories</h1>
            <div v-for="(cat, index) in category" v-bind:key="index">
              {{ cat.label }}
            </div>
          </div>
          <div class="col">
            <h1>Mes dépenses</h1>
            <div v-for="(find, index) in finds" v-bind:key="index">
              <input v-model="find.date" readonly />
              <input v-model="find.value" readonly />
              <input v-model="find.label" readonly />
            </div>
            <div>
              <input v-model="dateToAdd" />
              <input v-model="valueToAdd" />
              <select v-model="labelToAdd">
                <option
                  v-for="(cat, index) in category"
                  :value="cat.label"
                  v-bind:key="index"
                >
                  {{ cat.label }}
                </option>
              </select>
              <button @click="addFind">Add cost</button>
            </div>
          </div>
        </div>
      </div>
    </template>
    <script>
    import Chart from "chart.js/auto";
    import "chartjs-adapter-moment";
    
    export default {
      name: "PlanetChart",
      data() {
        return {
          ctx: null,
          Chart: null,
          valueToAdd: null,
          labelToAdd: null,
          dateToAdd: null,
          category: [
            { id: "salary", label: "Salaire" },
            { id: "fun", label: "Loisir" },
          ],
          finds: [
            { date: new Date("12/01/2020"), label: "Dépense 1", value: 12 },
            { date: new Date("12/01/2021"), label: "Salariée", value: 2 },
            { date: new Date("12/01/2000"), label: "Ciné", value: 1 },
            { date: new Date("12/01/2023"), label: "Restaurant", value: 12 },
          ],
        };
      },
      mounted() {
        this.ctx = document.getElementById("graphique");
        this.finds.sort(function (a, b) {
          return a.date - b.date;
        });
        this.Chart = this.createChart(this.finds);
      },
      methods: {
        createChart: function (dataToAdd) {
          var toRet = new Chart(this.ctx, {
            type: "line",
            data: {
              datasets: [
                {
                  label: "My dataset",
                  fill: false,
                  lineTension: 0.1,
                  backgroundColor: "rgba(75,192,192,0.4)",
                  borderColor: "rgba(75,192,192,1)",
                  borderCapStyle: "butt",
                  borderDash: [],
                  borderDashOffset: 0.0,
                  borderJoinStyle: "miter",
                  pointBorderColor: "rgba(75,192,192,1)",
                  pointBackgroundColor: "#fff",
                  pointBorderWidth: 1,
                  pointHoverRadius: 5,
                  pointHoverBackgroundColor: "rgba(75,192,192,1)",
                  pointHoverBorderColor: "rgba(220,220,220,1)",
                  pointHoverBorderWidth: 2,
                  pointRadius: 5,
                  pointHitRadius: 10,
                  data: dataToAdd,
                },
              ],
            },
            options: {
              parsing: {
                xAxisKey: "date",
                yAxisKey: "value",
              },
              scales: {
                x: {
                  type: "time",
                  time: {
                    unit: "month",
                  },
                },
              },
              responsive: true,
              maintainAspectRatio: false,
            },
          });
          return toRet;
        },
        addCategory: function () {},
        addFind: function () {
          if (this.valueToAdd !== null && this.labelToAdd !== null) {
            this.finds.push( { date: new Date("12/01/1990"), label: "Dépense nouvelle", value: 5 });
            this.finds.sort(function (a, b) {
              return new Date(a.date) - new Date(b.date);
            });
            this.Chart.data.datasets[0].data = this.finds;
            // console.log(this.Chart.data.datasets);
            this.Chart.update();
            // this.Chart = this.createChart(this.finds);
            this.valueToAdd = 0;
            this.dateToAdd = "";
            this.labelToAdd = "";
          }
        },
      },
    };
    </script>

Leave a comment