загрузка данных после загрузки страницы в livewire

#laravel #laravel-livewire

Вопрос:

Внутри представления у меня есть компонент livewire, который получает список монет из api и отображается внутри таблицы.Теперь я хочу, чтобы сначала загрузилась страница, а затем загрузился мой компонент и отобразился список монет.Как я могу это сделать? Мой код таков, что данные поступают до загрузки страницы

 namespace AppHttpLivewireBackendCrypto;

use LivewireComponent;

class Cryptolist extends Component
{
    public function render()
    {
        try {
            $api = new BinanceAPI('api','secret');
            $prices = $api->coins();
            $one = json_encode($prices, true);

            $coins = json_decode($one , true);
            return view('livewire.backend.crypto.cryptolist')->with('coins' , $coins);
        }catch(Exception $e)
        {
            return view('wrong')->with('e' , $e);
        }
    }
}

 

это вид

 @extends('backend.layouts.app')

@section('title', __('User Management'))

@section('breadcrumb-links')
    @include('backend.auth.user.includes.breadcrumb-links')
@endsection

@section('content')
    <div class="components">
        <div class="card card-bordered">
            <div class="card-inner">
                <livewire:backend.crypto.cryptolist />
            </div>
        </div>
        <!-- .card-preview -->
    </div>
    </div>
@endsection
 

и это компонент для отображения данных :

 <div wire:ignore wire:init="init">
    <div id="loadesh1">
    <table class="datatable-init nk-tb-list nk-tb-ulist" data-auto-responsive="false">
        <thead>
        <tr class="nk-tb-item nk-tb-head">
            <th class="nk-tb-col"><span class="sub-text">name</span></th>
            <th class="nk-tb-col tb-col-mb"><span class="sub-text">balance</span></th>
        </tr>
        </thead>
        <tbody>
        @foreach ($coins as $item => $value)
            <tr class="nk-tb-item">
                <td class="nk-tb-col">
                    <div class="user-card">
                        <div class="user-avatar d-none d-sm-flex">

                            @if(file_exists(public_path() . '/img/crypto/'.strtolower($value['coin'].".svg")))
                                <img style="border-radius: 0" src="{{asset('/img/crypto/'.strtolower($value['coin']))}}.svg" class="img-fluid" alt="">
                            @else
                                <img style="border-radius: 0" src="https://demo.rayanscript.ir/-/vendor/cryptocurrency-icons/32/color/noimage.png" class="img-fluid" alt="">
                            @endif

                        </div>
                        <div class="user-info">
                            <span class="tb-lead english" style="font-weight: bolder">{{$value['name']}}</span>
                            <span class="english">{{$value['coin']}}</span>
                        </div>
                    </div>
                </td>
                <td class="nk-tb-col tb-col-mb" data-order="{{$value['coin']}}">
                    <div class="btn-group" aria-label="Basic example">
                        <button type="button" class="btn btn-sm btn-dim btn-light" wire:click="getBalance('{{$value['coin']}}')">
                            <div wire:loading wire:target="getBalance('{{$value['coin']}}')">
                                <span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>
                            </div>
                            <span class="w-120px" id="coin-{{$value['coin']}}">get balance</span>
                        </button>
                        <button type="button" class="btn btn-sm btn-dim btn-primary">add coin</button>
                    </div>
                </td>
            </tr><!-- .nk-tb-item  -->
        @endforeach
        </tbody>
    </table>
    </div>
    </div>
</div>
 

Ответ №1:

В Livewire есть директива под названием wire:init . Это принимает метод в вашем компоненте, который запускается после первого, начального рендеринга.

Объявите свойство в своем классе, которое определяет, следует ли загружать данные или нет. Установите значение false по умолчанию и установите значение true в своем методе, который вызывается при инициализации.

Будьте осторожны, чтобы установить другие свойства в состояние, в котором ваше представление по-прежнему отображается без данных, поскольку, как вы видите, приведенный ниже код устанавливает пустой массив перед начальной загрузкой.

 class Cryptolist extends Component
{
    public bool $loadData = false;

    public function init()
    {
        $this->loadData = true;
    }

    public function render()
    {
        try {
            if ($this->loadData) {
                $api = new BinanceAPI('api','secret');
                $prices = $api->coins();
                $one = json_encode($prices, true);

                $coins = json_decode($one , true);
            } else {
                $coins = [];
            }
            return view('livewire.backend.crypto.cryptolist')->with('coins' , $coins);
        }catch(Exception $e)
        {
            return view('wrong')->with('e' , $e);
        }
    }
}
 

Затем в корневом элементе в представлении блейда поместите

 wire:init="init"
 

https://laravel-livewire.com/docs/2.x/defer-loading


Увидев ваше представление после редактирования и то, что у вас возникли проблемы с вашим wire:ignore — вот как это обойти: оберните таблицу и код, которые должны игнорироваться, в условное из @if ($loadData) . Таким образом, компонент Livewire может повторно отобразить и переместить таблицу с данными после ее загрузки, а также отобразить загрузочный текст до загрузки данных.

 <div wire:init="init">
    @if ($loadData)
        <div id="loadesh1" wire:ignore>
            <table class="datatable-init nk-tb-list nk-tb-ulist" data-auto-responsive="false">
                <!-- Rest of your table -->
            </table>
        </div>
    @else
        Loading data...
    @endif
</div>
 

Комментарии:

1. Я написал этот код, но после загрузки страницы ничего не происходит и ничего не загружается

2. В элементе «Проверка» и на вкладке «Сеть» я заметил, что информация была получена, но в таблице ничего не отображалось

3. Вы добавили wire:init ? Звучит так, будто ты этого не делал. Если да, то куда вы его положили?

4. Да, я добавил его, и он работает, потому что я увидел на вкладке «Сеть», что запрос был отправлен и получен ответ, но проблема в том, что информация не отображается в таблице. Я добавил его в корневой элемент

5. Вы явно сказали Livewire игнорировать изменения в представлении, с wire:ignore , поэтому Livewire не будет выполнять никаких изменений в нем. Удалите wire:ignore , и это сработает. Еще одна вещь, которую следует отметить , вы должны иметь wire:key при себе <tr class="nk-tb-item"> , делая это <tr class="nk-tb-item" wire:key="coin-{{ $loop->index }}"> .