ChartJS 如何根据下拉过滤器动态呈现新的图表列表?

6xfqseft  于 2023-08-05  发布在  Chart.js
关注(0)|答案(1)|浏览(163)

我没有尝试刷新刀片式服务器上的现有图表。这里的情况下,每个模块都有一个问题,选项和答案(由用户选择的选项)的列表。我有一个下拉菜单来按模块筛选问题。
我设法在加载时为第一个模块动态生成图表,但当我更改为模块2时,chartData会更新并通过emit传递回脚本,但我无法更新刀片。我得到的错误是,Uncaught(in promise)TypeError:无法从const ctx = document.getElementById(canvasId).getContext('2d')读取4:2072:66的null(阅读'getContext')的属性;.
我也提到了这个Destroy chart.js bar graph to redraw other graph in same ,任何帮助是赞赏。
Livewire组件

public function mount()
{
    $this->modules = $this->session->course->modules->where('status', 'PUBLISHED');
    $this->selectedModule = $this->modules->first()->id;

    $this->GetQuestions();
    $this->preparePieChartData();
}

public function preparePieChartData()
{
    $singleChoiceQuestions = $this->questions->where('type', 'single_choice');

    $data = [];

    foreach ($singleChoiceQuestions as $question) {
        if ($question->answers->count() > 0) {
            $options = $question->options;

            $questionData = [
                'question' => $question->question_text,
                'options' => [],
            ];

            foreach ($options as $option) {
                $count = $question->answers
                    ->where('option_uuid', $option->uuid)
                    ->where('session_id', $this->session->id)
                    ->count();

                $questionData['options'][] = [
                    'option' => $option->option_text,
                    'count' => $count,
                ];
            }

            $data[] = $questionData;
        }
    }

    $this->chartData = $data;
    
    $this->emitSelf('chartDataUpdated', $data);
}

public function updatedSelectedModule()
{
    $this->GetQuestions();
    $this->preparePieChartData();
}

字符串
在刀刃上

<select class="form-control-sm form-control" wire:model="selectedModule">
    @foreach($modules as $module)
        <option value="{{ $module->id }}">{{ $module->title }}</option>
    @endforeach
</select>

@foreach($questions as $question)
    if ($question->type == 'single_choice')
        <canvas id="pieChart{{ $loop->index }}" style="max-height: 300px; display: block;"></canvas>
    @endif
@endforeach


在刀锋剧本的结尾

<script>
    document.addEventListener('livewire:load', function () {
        const chartInstances = [];

        function GenerateCharts(chartData) {
            console.log('drawing charts...');

            chartData.forEach((chart, index) => {
                console.log(index);
                console.log(chart);

                const config = {
                    type: 'pie',
                    data: {
                        labels: chart.options.map(option => option.option),
                        datasets: [{
                            label: 'Total',
                            data: chart.options.map(option => option.count),
                        }]
                    },
                    options: {
                        plugins: {}
                    },
                }

                const canvasId = `pieChart${index}`;

                if (chartInstances[canvasId]) {
                    chartInstances[canvasId].destroy();
                    delete chartInstances[canvasId];
                }

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

                chartInstances[canvasId] = new Chart(ctx, config);
            });
        }

        GenerateCharts(@js($chartData));

        @this.on('chartDataUpdated', (data) => {
            GenerateCharts(data);
        });
    });
</script>

wwwo4jvm

wwwo4jvm1#

您可以使用事件重新调用脚本。例如,您可以使用updated方法捕获哪个字段已更新:

public function updated($field, $value) 
{
    // Validate which field should trigger a chart update. If all updates should, no if statement is needed.
    if ($field === 'questions') {
        $this->dispatchBrowserEvent('update-chart');
    }
}

字符串
然后在前端,你可以抓住它:

window.addEventListener('update-chart', () => {
    // Tear down current chart and initialize new chart
});

相关问题