通过 JS 将数据动态传递到 Laravel/Livewire 项目中的图表

Passing dynamically data via JS to a chart in a Laravel/Livewire project

我正在开发一个 laravel 8 + livewire 应用程序,我需要在我的应用程序中动态填充图表。 当我在我的视图中插入带有静态数据的图表时,它会被正确填充和显示,但是当我尝试动态填充它时,它不会显示任何内容。 为了将数据传递给脚本,我从我的 livewire 控制器使用了 dispatchBrowserEvent 方法,并在视图中监听了事件。 但是这样做我没有得到任何东西,我不明白为什么......你有什么建议或想法吗?

这是我的代码:

<?php

namespace App\Http\Livewire;

use Livewire\Component;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Livewire\WithPagination;
use App\Tenant;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Carbon;
use App\Models\AnagraficaSoggetto;

class TableReportResiduiFasce extends Component
{
    use WithPagination;

    protected $paginationTheme = 'bootstrap';

    protected $connection = null;
    protected $render = true;
    public $fascia1 = null;
    public $fascia2 = null;
    public $fascia3 = null;
    public $fascia4 = null;
    public $fascia5 = null;
    public $fascia6 = null;
    public $tot_posizioni = null;
    public $tot_residuo = null;

    public function mount(Request $request)
    {
       // Setto la connessione
        if (null !== $request->get('throughMiddleware')) {
            $this->connection = 'tenant';
        } else {
            $this->connection = null;
        }

        $anagrafica = new AnagraficaSoggetto();
        $anagrafica->setConnection($this->connection);

        //query fascia 1, conto il numero di contribuenti con un residuo >0 e < 100
        $this->fascia1 = $anagrafica->select(
            DB::raw('count(anagrafica_soggetto.codiceFiscale) as total'),
            DB::raw('sum(importoResiduo) as residuo')
        )
            ->join('minuta_partita', 'minuta_partita.id_soggetto', '=', 'anagrafica_soggetto.id')
            ->join('partita_pagamenti', 'partita_pagamenti.id_minuta_partita', '=', 'minuta_partita.id', 'left outer')
            ->join('users', 'minuta_partita.id_user', '=', 'users.id', 'left outer')
            ->join('tipologia_imposta', 'minuta_partita.id_tipologia_imposta', '=', 'tipologia_imposta.id')
            ->whereBetween('importoResiduo', [1, 99])->get()->toArray();
    

        //query fascia 2, conto il numero di contribuenti con un residuo >=100 e <=1000
        $this->fascia2 = $anagrafica->select(
            DB::raw('count(anagrafica_soggetto.codiceFiscale) as total'),
            DB::raw('sum(importoResiduo) as residuo')
        )
            ->join('minuta_partita', 'minuta_partita.id_soggetto', '=', 'anagrafica_soggetto.id')
            ->join('partita_pagamenti', 'partita_pagamenti.id_minuta_partita', '=', 'minuta_partita.id', 'left outer')
            ->join('users', 'minuta_partita.id_user', '=', 'users.id', 'left outer')
            ->join('tipologia_imposta', 'minuta_partita.id_tipologia_imposta', '=', 'tipologia_imposta.id')
            ->whereBetween('importoResiduo', [100, 1000])->get()->toArray();
        

        //query fascia 1, conto il numero di contribuenti con un residuo >1000 e <= 5000
        $this->fascia3 = $anagrafica->select(
            DB::raw('count(anagrafica_soggetto.codiceFiscale) as total'),
            DB::raw('sum(importoResiduo) as residuo')
        )
            ->join('minuta_partita', 'minuta_partita.id_soggetto', '=', 'anagrafica_soggetto.id')
            ->join('partita_pagamenti', 'partita_pagamenti.id_minuta_partita', '=', 'minuta_partita.id', 'left outer')
            ->join('users', 'minuta_partita.id_user', '=', 'users.id', 'left outer')
            ->join('tipologia_imposta', 'minuta_partita.id_tipologia_imposta', '=', 'tipologia_imposta.id')
            ->whereBetween('importoResiduo', [1001, 5000])->get()->toArray();
        

        //query fascia 1, conto il numero di contribuenti con un residuo >5000 e <= 10000
        $this->fascia4 = $anagrafica->select(
            DB::raw('count(anagrafica_soggetto.codiceFiscale) as total'),
            DB::raw('sum(importoResiduo) as residuo')
        )
            ->join('minuta_partita', 'minuta_partita.id_soggetto', '=', 'anagrafica_soggetto.id')
            ->join('partita_pagamenti', 'partita_pagamenti.id_minuta_partita', '=', 'minuta_partita.id', 'left outer')
            ->join('users', 'minuta_partita.id_user', '=', 'users.id', 'left outer')
            ->join('tipologia_imposta', 'minuta_partita.id_tipologia_imposta', '=', 'tipologia_imposta.id')
            ->whereBetween('importoResiduo', [5001, 10000])->get()->toArray();
        

        //query fascia 5, conto il numero di contribuenti con un residuo >10000 e <=20000
        $this->fascia5 = $anagrafica->select(
            DB::raw('count(anagrafica_soggetto.codiceFiscale) as total'),
            DB::raw('sum(importoResiduo) as residuo')
        )
            ->join('minuta_partita', 'minuta_partita.id_soggetto', '=', 'anagrafica_soggetto.id')
            ->join('partita_pagamenti', 'partita_pagamenti.id_minuta_partita', '=', 'minuta_partita.id', 'left outer')
            ->join('users', 'minuta_partita.id_user', '=', 'users.id', 'left outer')
            ->join('tipologia_imposta', 'minuta_partita.id_tipologia_imposta', '=', 'tipologia_imposta.id')
            ->whereBetween('importoResiduo', [10001, 200000])->get()->toArray();
        

        //query fascia 1, conto il numero di contribuenti con un residuo >20000
        $this->fascia6 = $anagrafica->select(
            DB::raw('count(anagrafica_soggetto.codiceFiscale) as total'),
            DB::raw('sum(importoResiduo) as residuo')
        )
            ->join('minuta_partita', 'minuta_partita.id_soggetto', '=', 'anagrafica_soggetto.id')
            ->join('partita_pagamenti', 'partita_pagamenti.id_minuta_partita', '=', 'minuta_partita.id', 'left outer')
            ->join('users', 'minuta_partita.id_user', '=', 'users.id', 'left outer')
            ->join('tipologia_imposta', 'minuta_partita.id_tipologia_imposta', '=', 'tipologia_imposta.id')
            ->where('importoResiduo', '>', 20000)->get()->toArray();

        if (!empty($this->fascia1[0])) {
            $this->tot_posizioni = $this->tot_posizioni + $this->fascia1[0]['total'];
            $this->tot_residuo = $this->tot_residuo + $this->fascia1[0]['residuo'];
        }

        if (!empty($this->fascia2[0])) {
            $this->tot_posizioni = $this->tot_posizioni + $this->fascia2[0]['total'];
            $this->tot_residuo = $this->tot_residuo + $this->fascia2[0]['residuo'];
        }

        if (!empty($this->fascia3[0])) {
            $this->tot_posizioni = $this->tot_posizioni + $this->fascia3[0]['total'];
            $this->tot_residuo = $this->tot_residuo + $this->fascia3[0]['residuo'];
        }

        if (!empty($this->fascia4[0])) {
            $this->tot_posizioni = $this->tot_posizioni + $this->fascia4[0]['total'];
            $this->tot_residuo = $this->tot_residuo + $this->fascia4[0]['residuo'];
        }

        if (!empty($this->fascia5[0])) {
            $this->tot_posizioni = $this->tot_posizioni + $this->fascia5[0]['total'];
            $this->tot_residuo = $this->tot_residuo + $this->fascia5[0]['residuo'];
        }

        if (!empty($this->fascia6[0])) {
            $this->tot_posizioni = $this->tot_posizioni + $this->fascia6[0]['total'];
            $this->tot_residuo = $this->tot_residuo + $this->fascia6[0]['residuo'];
        }

        $this->dispatchBrowserEvent('open',['fascia1' => $this->fascia1, 
                                            'fascia2' => $this->fascia2,
                                            'fascia3' => $this->fascia3,
                                            'fascia4' => $this->fascia4,
                                            'fascia5' => $this->fascia5,
                                            'fascia6' => $this->fascia6,
                                            'tot_posizioni' => $this->tot_posizioni]);
        //dd($this->fascia3);
    }

    public function render()
    {
        return view('livewire.table-report-residui-fasce')
        ->with('fascia1', $this->fascia1)
        ->with('fascia2', $this->fascia2)
        ->with('fascia3', $this->fascia3)
        ->with('fascia4', $this->fascia4)
        ->with('fascia5', $this->fascia5)
        ->with('fascia6', $this->fascia6)
        ->with('tot_posizioni', $this->tot_posizioni)
        ->with('tot_residuo', $this->tot_residuo);
    }
}

<div class="row">
    <div class="col-12">
        <div class="card">
            <div class="card-header">
                <h4 class="card-title">Report residui per fasce</h4>
            </div>
            <div class="card-body">
                <div class="table-responsive">
                    <table class="table table-responsive-md" style="min-width: 845px">
                        <thead>
                            <tr>
                                <th>Fascia</th>
                                <th># Posizioni</th>
                                <th>Residuo &euro;</th>
                                <th>% Posizioni</th>
                                <th>% Residuo</th>
                                <th>Valore Medio &euro;</th>
                            </tr>
                        </thead>
                        <tbody>
                            @if ($fascia1[0]['total'] !== 0)
                                <tr>
                                    <td><span class="badge light badge-lg badge-info">
                                            < 100 &euro;</span>
                                    </td>
                                    <td>{{ $fascia1[0]['total'] }}</td>
                                    <td>{{ $fascia1[0]['residuo'] }} &euro;</td>
                                    <td>{{ round((100 * $fascia1[0]['total']) / $tot_posizioni, 2) }} % </td>
                                    <td>{{ round((100 * $fascia1[0]['residuo']) / $tot_residuo, 2) }} %</td>
                                    <td>
                                        @if (!empty($fascia1[0]['total']))
                                        {{ round($fascia1[0]['residuo'] / $fascia1[0]['total'], 2) }} @else 0
                                        @endif &euro;
                                    </td>
                                </tr>
                            @else
                                <tr>
                                    <td><span class="badge light badge-lg badge-info">
                                            < 100 &euro;</span>
                                    </td>
                                    <td>0</td>
                                    <td>0 &euro;</td>
                                    <td>0 % </td>
                                    <td>0 %</td>
                                    <td>0 &euro;</td>
                                </tr>
                            @endif
                            @if ($fascia2[0]['total'] !== 0)
                                <tr>
                                    <td><span class="badge light badge-lg badge-success">100 - 1000 &euro;</span></td>
                                    <td>{{ $fascia2[0]['total'] }}</td>
                                    <td>{{ $fascia2[0]['residuo'] }} &euro;</td>
                                    <td>{{ round((100 * $fascia2[0]['total']) / $tot_posizioni, 2) }} % </td>
                                    <td>{{ round((100 * $fascia2[0]['residuo']) / $tot_residuo, 2) }} %</td>
                                    <td>
                                        @if (!empty($fascia2[0]['total']))
                                        {{ round($fascia2[0]['residuo'] / $fascia2[0]['total'], 2) }} @else 0
                                        @endif &euro;
                                    </td>
                                </tr>
                            @else
                                <tr>
                                    <td><span class="badge light badge-lg badge-success"> 100 - 1000 &euro;</span></td>
                                    <td>0</td>
                                    <td>0 &euro;</td>
                                    <td>0 % </td>
                                    <td>0 %</td>
                                    <td>0 &euro;</td>
                                </tr>
                            @endif
                            @if ($fascia3[0]['total'] !== 0)
                                <tr>
                                    <td><span class="badge light badge-lg badge-light">1000 - 5000 &euro;</span></td>
                                    <td>{{ $fascia3[0]['total'] }}</td>
                                    <td>{{ $fascia3[0]['residuo'] }} &euro;</td>
                                    <td>{{ round((100 * $fascia3[0]['total']) / $tot_posizioni, 2) }} % </td>
                                    <td>{{ round((100 * $fascia3[0]['residuo']) / $tot_residuo, 2) }} %</td>
                                    <td>
                                        @if (!empty($fascia3[0]['total']))
                                        {{ round($fascia3[0]['residuo'] / $fascia3[0]['total'], 2) }} @else 0
                                        @endif &euro;
                                    </td>
                                </tr>
                            @else
                                <tr>
                                    <td><span class="badge light badge-lg badge-light"> 1000 - 5000 &euro;</span></td>
                                    <td>0</td>
                                    <td>0 &euro;</td>
                                    <td>0 % </td>
                                    <td>0 %</td>
                                    <td>0 &euro;</td>
                                </tr>
                            @endif
                            @if ($fascia4[0]['total'] !== 0)
                                <tr>
                                    <td><span class="badge light badge-lg badge-dark">5000 - 10000 &euro;</span></td>
                                    <td>{{ $fascia4[0]['total'] }}</td>
                                    <td>{{ $fascia4[0]['residuo'] }} &euro;</td>
                                    <td>{{ round((100 * $fascia4[0]['total']) / $tot_posizioni, 2) }} % </td>
                                    <td>{{ round((100 * $fascia4[0]['residuo']) / $tot_residuo, 2) }} %</td>
                                    <td>
                                        @if (!empty($fascia4[0]['total']))
                                        {{ round($fascia4[0]['residuo'] / $fascia4[0]['total'], 2) }} @else 0
                                        @endif &euro;
                                    </td>
                                </tr>
                            @else
                                <tr>
                                    <td><span class="badge light badge-lg badge-dark"> 5000 - 10000 &euro;</span> </td>
                                    <td>0</td>
                                    <td>0 &euro;</td>
                                    <td>0 % </td>
                                    <td>0 %</td>
                                    <td>0 &euro;</td>
                                </tr>
                            @endif
                            @if ($fascia5[0]['total'] !== 0)
                                <tr>
                                    <td><span class="badge light badge-lg badge-warning">10000 - 20000 &euro;</span>
                                    </td>
                                    <td>{{ $fascia5[0]['total'] }}</td>
                                    <td>{{ $fascia5[0]['residuo'] }} &euro;</td>
                                    <td>{{ round((100 * $fascia5[0]['total']) / $tot_posizioni, 2) }} % </td>
                                    <td>{{ round((100 * $fascia5[0]['residuo']) / $tot_residuo, 2) }} %</td>
                                    <td>
                                        @if (!empty($fascia5[0]['total']))
                                        {{ round($fascia5[0]['residuo'] / $fascia5[0]['total'], 2) }} @else 0
                                        @endif &euro;
                                    </td>
                                </tr>
                            @else
                                <tr>
                                    <td><span class="badge light badge-lg badge-warning"> 10000 - 20000 &euro; </span>
                                    </td>
                                    <td>0</td>
                                    <td>0 &euro;</td>
                                    <td>0 % </td>
                                    <td>0 %</td>
                                    <td>0 &euro;</td>
                                </tr>
                            @endif
                            @if ($fascia6[0]['total'] !== 0)
                                <tr>
                                    <td><span class="badge light badge-lg badge-danger"> > 2000 &euro;</span></td>
                                    <td>{{ $fascia6[0]['total'] }}</td>
                                    <td>{{ $fascia6[0]['residuo'] }} &euro;</td>
                                    <td>{{ round((100 * $fascia6[0]['total']) / $tot_posizioni, 2) }} % </td>
                                    <td>{{ round((100 * $fascia6[0]['residuo']) / $tot_residuo, 2) }} %</td>
                                    <td>
                                        @if (!empty($fascia6[0]['total']))
                                        {{ round($fascia6[0]['residuo'] / $fascia6[0]['total'], 2) }} @else 0
                                        @endif &euro;
                                    </td>
                                </tr>
                            @else
                                <tr>
                                    <td><span class="badge light badge-lg badge-danger"> > 20000 &euro;</span> </td>
                                    <td>0</td>
                                    <td>0 &euro;</td>
                                    <td>0 % </td>
                                    <td>0 %</td>
                                    <td>0 &euro;</td>
                                </tr>
                            @endif
                        </tbody>
                        <tfoot>
                            <th></th>
                            <th>Tot posizioni: {{ $tot_posizioni }}</th>
                            <th>Tot residuo: {{ $tot_residuo }} &euro;</th>
                            <th>100%</th>
                            <th>100%</th>
                            <th>Tot medio: @if ($tot_posizioni != 0)
                                {{ round($tot_residuo / $tot_posizioni, 2) }} @else 0 @endif
                                &euro;</th>
                        </tfoot>
                    </table>
                </div>
            </div>
        </div>
    </div>
    <!-- grafichiamo i risultati stampati in tabella -->
    <div class="col-xl-6 col-lg-12">
        <div class="card">
            <div class="card-header">
                <h4 class="card-title">Residui per fasce</h4>
            </div>
            <div class="card-body">
                <div id="morris" class="morris_chart_height">
                    
                </div>
            </div>
        </div>
    </div>

</div>

@push('custom_scripts')
<script>

     
    //Codice per popolare il grafico
    var screenWidth = $(window).width();

    var setChartWidth = function() {
        if (screenWidth <= 768) {
            var chartBlockWidth = 0;
            chartBlockWidth = (screenWidth < 300) ? screenWidth : 300;
            jQuery('.morris_chart_height').css('min-width', chartBlockWidth - 31);
        }
    }
    // VALORI HARD CODED SOLO A FINI DI TEST DI STAMPA A VIDEO DEL GRAFICO
    // VANNO POI MODIFICATI PER ESSERE DINAMICI
    // La somma di questi deve essere uguale a total 

//HERE I'M LISTENING THE EVENT TO TAKE VALUE WITH 'event.detail.fascia[i]['total']' VALUE
 window.addEventListener('open', event => {
    let Data = [{
            label: "Fascia < 100 €", //color: info
            value: 12  //12 commenting the window.addEventListener 
                       //or dynamically value from event.detail
        },
        {
            label: "Fascia 100 - 1000 €", //color: success
            value: 30
        },
        {
            label: "Fascia 1000 - 5000 €",  //color: light
            value: 20
        },
        {
            label: "Fascia 5000 - 10000 €", //color: dark
            value: 20
        },
        {
            label: "Fascia 10000 - 20000 €", //color: warning
            value: 20
        },
        {
            label: "Fascia > 20000 €", //color: danger
            value: 20
        },
    ];
})

    let total = 122; // Numero totale di residui non può essere hard coded
    var browsersChart = Morris.Donut({
            element: 'morris', // Id del div dove va messo il grafico
            data: Data,
            formatter: function(value, data) {
                return Math.floor(value / total * 100) + '%';
            },
            resize: true,
            redraw: true,
            colors: ['rgba(0, 227, 239, 0.533)',
                     'rgba(0, 239, 52, 0.506)',
                     'rgba(171, 168, 168, 0.437)', 
                     'rgba(80, 63, 88, 0.56)', 
                     'rgba(246, 152, 45, 0.608)', 
                     'rgba(251, 39, 39, 0.676)'] // Mettere tanti colori quante sono le fasce
        });
</script>
@endpush

你为什么要使用浏览器事件,你不能只使用你已经通过 render() 方法传递的数据吗?

您可以使用 Laravel 的 {{ }},因为此 JS 在 <script> 标签内,其代码将是 pre-processed by Laravel blade 引擎,因此每个 {{ }} 将在将页面发送到客户端之前被识别和替换。

所以在你的具体情况下你可以这样做:

let Data = [{
            label: "Fascia < 100 €", //color: info
            value: {{ $fascia1[0]['residuo'] }}
        },
        {
            label: "Fascia 100 - 1000 €", //color: success
            value: {{ $fascia2[0]['residuo'] }}
        },
        {
            label: "Fascia 1000 - 5000 €",  //color: light
            value: {{ $fascia3[0]['residuo'] }}
        },
        {
            label: "Fascia 5000 - 10000 €", //color: dark
            value: {{ $fascia3[0]['residuo'] }}
        },
        {
            label: "Fascia 10000 - 20000 €", //color: warning
            value: {{ $fascia5[0]['residuo'] }}
        },
        {
            label: "Fascia > 20000 €", //color: danger
            value: {{ $fascia6[0]['residuo'] }}
        },
    ];
    let total = {{ $tot_residuo }}; 

确保同时检查 0 值,因为在这些情况下您不想显示相应的标签。

假设筋膜 5000 - 10000 的值为 0 那么您不想显示该标签,否则图表将毫无意义。

我也怀疑为什么要将变量 $fascia 保存为数组,这样您就必须像 $fascia6[0]['residuo'] 一样访问它们。避免 toArray() 方法并在它们从 Eloquent 返回时保存它们会不会更容易(因为它们不是给定查询的 collection )。这样您就可以像 $fascia6['residuo']

一样访问它们