接著上篇,Laracasts,這邊將會展示 livewire 自定義組件和傳遞參數。
生成 livewire parent component
$ php artisan livewire:layout
生成主要 component
$ php artisan make:livewire TestForm
將原本在 route 做的組件注入遷移至 TestForm 當中,由 Form 進行生成:
Route::get('/', TestForm::class);
//App\Livewire\TestForm.php
class TestForm extends Component
{
public $email; // 放置變化結果
public function render()
{
$input = TextInput::make('email')
->label('Email Address');
return view('livewire.test-form', [
'input' => $input
]);
}
}
到目前為止會是跟原本實作結果一致,接下來開始進行使 Label 具有 closure 傳遞調整:
$input = TextInput::make('email')
->label(function () {
return Str::random();
});
到 TextInput field 進行 allow property:
class TextInput implements Htmlable
{
protected string | \Closure $label;
public function getLabel():string
{
return $this->evaluate($this->label ?? null) ?? str($this->name)->title();
}
簡單寫 evaluate 呼叫 closure 的方法:
public function evaluate($value)
{
if ($value instanceof \Closure) {
return $value(); // call
}
return $value;
}
希望 label 會因為我輸入的 input 隨機生成字串,而 text-input.blade.php
則需要透過 livewire:model.live 進行實時數據綁定:
<input type="text" wire:model.live="{{ $getName() }}"/>
// App\Components\TextInput.php
public function getName(): string
{
return $this->name;
}
到此已經完成需求,接下來要使用神奇的 app()->call()
這個可以透過 laravel container 進行呼叫函式並且傳遞指定變數在裡面操作:
public function evaluate($value)
{
if ($value instanceof \Closure) {
// $value = clsoure
return app()->call($value, [
'random' => Str::random(),
]);
}
然後在前面就可以這樣使用:
$input = TextInput::make('email')
->label(function ($random) {
return $random;
});
// 非常神奇,這樣在之後定義 closure 參數時可以多加利用:
return app()->call($value, [
'random' => Str::random(),
'name' => 'Yish'
]);
接下來可以把 livewire 組件也注入到方法內可以調用:
public function livewire(Component $livewire): self
{
$this->livewire = $livewire;
return $this;
}
$input = TextInput::make('email')
->label(function ($random, $name) {
return $name;
})->livewire($this);
public function evaluate($value)
{
if ($value instanceof \Closure) {
return app()->call($value, [
'random' => Str::random(),
'name' => 'Yish',
// 取得 livewire component state 這邊是指 TestForm 的 $email
'state' => $this->livewire->{$this->getName()},
]);
}
$input = TextInput::make('email')
->label(function ($random, $name, $state) {
return $state;
})->livewire($this);
這樣 label 就會隨著輸入框內容進行 update。