[Laravel11+LIVEWIRE3 #10]CSSフレームワークとの相性やJavascriptのライフサイクル(でいいのか?)

Laravel
LIVEWIRE LOGO

前回[[Laravel11+LIVEWIRE #9]アップロードファイルをAzureのストレージ(BLOB)へ]はこちら。

LaravelのMVCモデルのシステムからLivewireへ移行してみようと実装を進めていたが、CSSフレームワークとの相性の問題でなかなか大変な状況。

問題点

通常のLaravelは、コントローラーでリクエストを受け取ってビューをブラウザに返却し、ブラウザ側のCSSフレームワークで実行するJavascriptで表示整形を行う仕組みになっている。

Livewireだと初回の表示は正しく行われるが、wire:clickでサーバ側へデータ送信すると、htmlが初期化されてCSSフレームワークの整形が消えてしまう状況となる。

前準備

前回までのソースで使用しているCSSフレームワークはSemantic UIなんだけど、ちょっとわかりやすくするために、jQueryでDOMの操作を行って、動作を再現させてみる。

まずは、前回までのソースで再現するソースを作っていく。

resources/views/components/layouts/app.blade.php

レイアウトファイルの最後でJavascriptを実行したいので以下の修正を行う。

    :
    :
        <script src="https://code.jquery.com/jquery-3.7.1.min.js" integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=" crossorigin="anonymous"></script>
        <script src="https://cdn.jsdelivr.net/npm/semantic-ui@2.5.0/dist/semantic.min.js"></script>

        @stack('js')    ←この行を追加

    </body>
</html>

resources/views/livewire/post/index.blade.php

一覧画面の最後に、ボタン名を変えるようなJSを組み込む。

    :
    :
    <button type="button" class="ui primary button" wire:click="jsTest()" id="jsTestButton">JSテスト</button>

@push('js')
<script>
testInit = () => {
    $('#jsTestButton').text("じぇいえすてすと");
}
testInit();
</script>
@endpush

</div>
    :
    :

これで、一覧画面を表示すると、JSテストボタン名は「JSテスト」から「じぇいえすてすと」という表示になる。

ちょっとやっている(結果、解決できず、、、)

Livewire側からCSSフレームワークの表示整形のメソッドを呼び出してあげれば良いのでは?ということで、Livewireのライフサイクルの最後でCSSフレームワークの表示整形メソッドを呼び出してみようとやってみた。ちなみにLivewireからブラウザのJavascriptを実行するにはコンポーネントで$this->js("alert('うにうに');");と言う感じで実行できる。

app/Livewire/Post/Index.php

JSテストボタンクリック時に初期化メソッドを呼び出してみる。

    :
    :
    public function jsTest()
    {
        logger()->debug('Index::jsTest');
        $this->js('testInit();');
    }
    :
    :

これで実行してみるとJSテストボタン(表示はじぇいえすてすと)は、ボタンクリック後にボタン名は「JSテスト」となり、「じぇいえすてすと」とはならない。

整形のタイミングが初期化メソッドのあとに行われるため、正常な表示にならない。

適当にやってちゃダメだね。ちゃんと整理しましょう。

ライフサイクルフック(Lifecycle Hooks)

公式(https://livewire.laravel.com/docs/lifecycle-hooks)によるとPHP側でライフサイクル最後にJSの初期化メソッドを実行してあげればよいのでは?と考えた。rendered()もしくはdehydrate()でJSの初期化メソッドを実行してあげても結果はダメだった、、、

LivewireのJavascriptフック

公式(https://livewire.laravel.com/docs/javascript)によるといろいろとフックできるらしい。

今回の事象で使えそうなのはcommitrequestかな。

resources/views/livewire/post/index.blade.php

@push('js')
<script>
testInit = () => {
    $('#jsTestButton').text("じぇいえすてすと");
}
testInit();

// 以下を追加する。ここから
document.addEventListener('livewire:initialized', () => {
	console.log('livewire:initialized');
})
document.addEventListener('livewire:init', () => {
	console.log('livewire:init');
});

$(document).ready( () => {

    Livewire.hook('commit', ({ component, commit, respond, succeed, fail }) => {
        respond(() => {
            console.log('commit.respond');
        })
        succeed(({ snapshot, effect }) => {
            console.log('commit.succeed');
        })
        fail(() => {
            console.log('commit.fail');
        })
    });

    Livewire.hook('request', ({ uri, options, payload, respond, succeed, fail }) => {
        respond(({ status, response }) => {
            console.log('request.respond');
        })
        succeed(({ status, json }) => {
            console.log('request.succeed');
        })
        fail(({ status, content, preventDefault }) => {
            console.log('request.fail');
        })
    });
});
// ここまで追加
</script>

@endpush

Livewireオブジェクトは$(document).ready状態じゃないと生成されない。あ!livewire:initializedの中でもイケるのかも、、、後で試してみるか、、、

ブラウザをリロードする。

コンソールログには以下が出力される。

livewire:init
livewire:initialized

commitとrequestは動かない。

ボタンをクリックする。

コンソールログには以下が出力される。

request.respond
commit.respond
commit.succeed
request.succeed

たぶん、succeedで初期化メソッドを呼び出してあげればイケそうだからやってみたけどダメだった、、、

結果

うまくいかない。。。なにかのタイミングでうまういったら記事を更新しよう!

コメント

タイトルとURLをコピーしました