前回[[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)によるといろいろとフックできるらしい。
今回の事象で使えそうなのはcommitとrequestかな。
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で初期化メソッドを呼び出してあげればイケそうだからやってみたけどダメだった、、、
結果
うまくいかない。。。なにかのタイミングでうまういったら記事を更新しよう!
コメント