Livewire/Alpine 切换绑定的动态数量
Livewire/Alpine Dynamic # of Toggle Binding
我有一个显示多个 toggle switches 的表单。
开关数量根据 table 中的“权限”动态变化。我如何绑定这些以便在单击它们时将数据发回 livewire?我找到的 'Non-dynamic' 答案是 x-data="{isChecked: @entangle('foo')}" 但如果我有未知数量的项目而不是单个 'foo'.
我尝试了一种方法 wire:click="update({{ $value->id }})" 但这只会将被点击元素的 ID 传回 livewire,而不是它的状态(开或关)。
@foreach($permissions as $key => $value)
<div>
<span>
<span>{{ $value->name }}</span>
<span>{{ $value->description }}</span>
</span>
<button type="button"
x-data="{isChecked: {{ $value->allowed ? 1 : 0 }}}"
@click="isChecked = !isChecked"
{# wire:click? doesn't send state #}
wire:click="update"
:class="{'bg-liteblue': isChecked, 'bg-gray-200': !isChecked }"
class="relative..."
role="switch"
:aria-checked="isChecked"
aria-labelledby="availability-label">
<span class="sr-only">Use setting</span>
<span aria-hidden="true"
:class="{'translate-x-5': isChecked, 'translate-x-0': !isChecked }"
class="translate-x-5 transition ease-in-out duration-200"></span>
</button>
</div>
@endforeach
我希望每次切换都在单击时更新数据库(而不是在最后一次提交中)。如何将状态传回 livewire 控制器?
我认为您需要在 x 数据行中使用“@entangle”。以下是 https://laravel-livewire.com/docs/2.x/alpine-js 上大约 1/2 向下的示例。这纠缠 javascript 变量 = 打开 livewire public 属性 $showDropdown。当您更改 open 的值时,public 属性 $showDropdown 将更改为与 open 等效的值。但是,我认为通信只有一种方式——apine to livewire。
<div x-data="{ open: @entangle('showDropdown') }">
或者你可以使用这样的东西
<button x-on:click="$wire.someMethod($value->id)">xxxxxxx</button>
该参数将识别您点击了哪个开关。 livewire 方法 - someMethod() - 然后会将选择保存在数据库中。
我遇到了类似的问题。以下是我正在尝试的。当点击事件被触发时,它会切换 alpine 变量 'enableit'。 alert(enableit) 显示正在切换的状态。但是 alert('{{ $isEnabled }}') 显示为空白。但是,如果我查看控制台中返回的 json,我会看到 $isEnabled 属性 被切换,但与 enableit 变量相反。
@props([
'choice' => 'Make Administrator?',
'desc' => 'We encourage you to make your spouse / partner an administrator',
'isEnabled' => false,
])
<div
x-data="{ open: @entangle('showToggleButton').defer,
enableit: @entangle('isEnabled')}"
class="flex items-center justify-between"
>
<span x-show="open" class="flex-grow flex flex-col" id="availability-label">
<span class="text-sm font-medium text-gray-900 mr-4">{{ $choice }}</span>
<span class="text-sm text-gray-500 mr-4">{{ $desc }}</span>
</span>
<!-- Enabled: "bg-indigo-600", Not Enabled: "bg-gray-200" -->
<button x-show="open" type="button"
@click="enableit = !enableit; alert(enableit); alert('{{ $isEnabled }}')"
class="{{ ($isEnabled) ? 'bg-indigo-600' : 'bg-gray-200' }} relative inline-flex flex-shrink-0 h-6 w-11 border-2 border-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
role="switch" aria-checked="enableit" aria-labelledby="availability-label">
<span x-show="open" class="sr-only">Use setting</span>
<!-- Enabled: "translate-x-5", Not Enabled: "translate-x-0" -->
<span x-show="open" aria-hidden="!enableit"
class="{{ ($isEnabled) ? 'translate-x-5' : 'translate-x-0' }} pointer-events-none inline-block h-5 w-5 rounded-full bg-white shadow transform ring-0 transition ease-in-out duration-200"></span>
</button>
</div>
顺便说一句,你提到了
# wire:click? doesn't send state #
我相信你应该在 alpine 组件中使用 $wire.click。
我用一个名为 'permission-toggle' 的子组件解决了这个问题,这样每个切换都可以负责保持它的状态而不是一个数组,然后在父组件中用
实例化它
@foreach($permissions as $permission)
<livewire:permission-toggle :group="$selectedGroup" :permission="$permission" :key="$selectedGroup.'.'.$permission->slug">
@endforeach
父“permission-form”组件负责从数据库获取所有权限(因此只有一个大的加载调用),然后每个单独的“permission-toggle”组件负责更新自身。 (个别数据库调用)权限切换的 livewire 控制器如下
class PermissionToggle extends Component
{
public bool $checked;
public string $name;
public string $description;
public string $slug;
public string $group;
public function mount($permission)
{
$this->checked = $permission->allowed;
$this->name = $permission->name;
$this->description = $permission->description;
$this->slug = $permission->slug;
}
public function updating($a, bool $checked)
{
$group = Group::where('slug', $this->group)->first();
if($checked === true)
$group->assignPermissions($this->slug);
else
$group->revokePermissions($this->slug);
}
public function render()
{
return view('livewire.permission-toggle');
}
}
回答这个问题有几个层次。第一个是:
为什么@entangle?
如果你要通过 Livewire 同步数据,那么严格来说(至少从我从你的代码中理解的形式),你不需要将数据与 Alpine 纠缠在一起。
二级是:
如果你坚持使用@entangle
您不需要创建全新的组件。你可以纠缠一个数组(和数组的数组,以及数组的数组的数组):
毫无疑问,您接受的解决方案有效。但在我看来,它看起来像是一个非常冗长的解决方案。我不喜欢掩埋 classes/files 层来解决一个应该作为单一概念“考虑”的解决方案。当您必须翻阅多个文件时,它会使长期维护更加耗时。 (也许是个人喜好,随便吧。)
我处理这个问题的方式如下。在原始 Livewire 组件中定义单个数组:
class PropertiesPage extends Component
{
// in the real world, this array would be populated from a DB
public array $permissions = [
'inventory' => [ // group level
'view_inv' => [ // permission level
'description' => 'View Inventory',
'slug' => '/viewinv',
'is_checked' => true,
],
'update_inv' => [
'description' => 'Modify Inventory',
'slug' => '/modinv',
'is_checked' => false,
],
],
];
在你的 blade.php
文件中,你然后纠缠整个数组:
<div x-data="dbPermissions: @entangle('permissions')">
<p>Blah...</p>
</div>
然后您可以使用 Blade 的 @foreach
以类似于您在问题中所做的方式循环遍历数组。 但是,正如我在上面的第一点中强调的那样,如果您的逻辑和同步发生在 Blade/Livewire 中,为什么还要麻烦 @entangle
-ing?当然,如果首先想要 @entangle
的重点是使用 Alpine 的循环解决方案,也就是说你可以这样做:
<template x-for="(perms, group) in dbPermissions">
<p x-text="group"></p>
<template x-for="(props, permId) in perms">
<input type="radio" x-model="dbPermissions[group][permId].is_checked">
</template>
</template>
当然,我所有的代码都是伪代码,因为我没有完全掌握您的实际解决方案。我在此站点上的意图始终是公开分享概念,而不是将您的特定问题解决到 T。
我有一个显示多个 toggle switches 的表单。
开关数量根据 table 中的“权限”动态变化。我如何绑定这些以便在单击它们时将数据发回 livewire?我找到的 'Non-dynamic' 答案是 x-data="{isChecked: @entangle('foo')}" 但如果我有未知数量的项目而不是单个 'foo'.
我尝试了一种方法 wire:click="update({{ $value->id }})" 但这只会将被点击元素的 ID 传回 livewire,而不是它的状态(开或关)。
@foreach($permissions as $key => $value)
<div>
<span>
<span>{{ $value->name }}</span>
<span>{{ $value->description }}</span>
</span>
<button type="button"
x-data="{isChecked: {{ $value->allowed ? 1 : 0 }}}"
@click="isChecked = !isChecked"
{# wire:click? doesn't send state #}
wire:click="update"
:class="{'bg-liteblue': isChecked, 'bg-gray-200': !isChecked }"
class="relative..."
role="switch"
:aria-checked="isChecked"
aria-labelledby="availability-label">
<span class="sr-only">Use setting</span>
<span aria-hidden="true"
:class="{'translate-x-5': isChecked, 'translate-x-0': !isChecked }"
class="translate-x-5 transition ease-in-out duration-200"></span>
</button>
</div>
@endforeach
我希望每次切换都在单击时更新数据库(而不是在最后一次提交中)。如何将状态传回 livewire 控制器?
我认为您需要在 x 数据行中使用“@entangle”。以下是 https://laravel-livewire.com/docs/2.x/alpine-js 上大约 1/2 向下的示例。这纠缠 javascript 变量 = 打开 livewire public 属性 $showDropdown。当您更改 open 的值时,public 属性 $showDropdown 将更改为与 open 等效的值。但是,我认为通信只有一种方式——apine to livewire。
<div x-data="{ open: @entangle('showDropdown') }">
或者你可以使用这样的东西
<button x-on:click="$wire.someMethod($value->id)">xxxxxxx</button>
该参数将识别您点击了哪个开关。 livewire 方法 - someMethod() - 然后会将选择保存在数据库中。
我遇到了类似的问题。以下是我正在尝试的。当点击事件被触发时,它会切换 alpine 变量 'enableit'。 alert(enableit) 显示正在切换的状态。但是 alert('{{ $isEnabled }}') 显示为空白。但是,如果我查看控制台中返回的 json,我会看到 $isEnabled 属性 被切换,但与 enableit 变量相反。
@props([
'choice' => 'Make Administrator?',
'desc' => 'We encourage you to make your spouse / partner an administrator',
'isEnabled' => false,
])
<div
x-data="{ open: @entangle('showToggleButton').defer,
enableit: @entangle('isEnabled')}"
class="flex items-center justify-between"
>
<span x-show="open" class="flex-grow flex flex-col" id="availability-label">
<span class="text-sm font-medium text-gray-900 mr-4">{{ $choice }}</span>
<span class="text-sm text-gray-500 mr-4">{{ $desc }}</span>
</span>
<!-- Enabled: "bg-indigo-600", Not Enabled: "bg-gray-200" -->
<button x-show="open" type="button"
@click="enableit = !enableit; alert(enableit); alert('{{ $isEnabled }}')"
class="{{ ($isEnabled) ? 'bg-indigo-600' : 'bg-gray-200' }} relative inline-flex flex-shrink-0 h-6 w-11 border-2 border-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
role="switch" aria-checked="enableit" aria-labelledby="availability-label">
<span x-show="open" class="sr-only">Use setting</span>
<!-- Enabled: "translate-x-5", Not Enabled: "translate-x-0" -->
<span x-show="open" aria-hidden="!enableit"
class="{{ ($isEnabled) ? 'translate-x-5' : 'translate-x-0' }} pointer-events-none inline-block h-5 w-5 rounded-full bg-white shadow transform ring-0 transition ease-in-out duration-200"></span>
</button>
</div>
顺便说一句,你提到了
# wire:click? doesn't send state #
我相信你应该在 alpine 组件中使用 $wire.click。
我用一个名为 'permission-toggle' 的子组件解决了这个问题,这样每个切换都可以负责保持它的状态而不是一个数组,然后在父组件中用
实例化它@foreach($permissions as $permission)
<livewire:permission-toggle :group="$selectedGroup" :permission="$permission" :key="$selectedGroup.'.'.$permission->slug">
@endforeach
父“permission-form”组件负责从数据库获取所有权限(因此只有一个大的加载调用),然后每个单独的“permission-toggle”组件负责更新自身。 (个别数据库调用)权限切换的 livewire 控制器如下
class PermissionToggle extends Component
{
public bool $checked;
public string $name;
public string $description;
public string $slug;
public string $group;
public function mount($permission)
{
$this->checked = $permission->allowed;
$this->name = $permission->name;
$this->description = $permission->description;
$this->slug = $permission->slug;
}
public function updating($a, bool $checked)
{
$group = Group::where('slug', $this->group)->first();
if($checked === true)
$group->assignPermissions($this->slug);
else
$group->revokePermissions($this->slug);
}
public function render()
{
return view('livewire.permission-toggle');
}
}
回答这个问题有几个层次。第一个是:
为什么@entangle?
如果你要通过 Livewire 同步数据,那么严格来说(至少从我从你的代码中理解的形式),你不需要将数据与 Alpine 纠缠在一起。
二级是:
如果你坚持使用@entangle
您不需要创建全新的组件。你可以纠缠一个数组(和数组的数组,以及数组的数组的数组):
毫无疑问,您接受的解决方案有效。但在我看来,它看起来像是一个非常冗长的解决方案。我不喜欢掩埋 classes/files 层来解决一个应该作为单一概念“考虑”的解决方案。当您必须翻阅多个文件时,它会使长期维护更加耗时。 (也许是个人喜好,随便吧。)
我处理这个问题的方式如下。在原始 Livewire 组件中定义单个数组:
class PropertiesPage extends Component
{
// in the real world, this array would be populated from a DB
public array $permissions = [
'inventory' => [ // group level
'view_inv' => [ // permission level
'description' => 'View Inventory',
'slug' => '/viewinv',
'is_checked' => true,
],
'update_inv' => [
'description' => 'Modify Inventory',
'slug' => '/modinv',
'is_checked' => false,
],
],
];
在你的 blade.php
文件中,你然后纠缠整个数组:
<div x-data="dbPermissions: @entangle('permissions')">
<p>Blah...</p>
</div>
然后您可以使用 Blade 的 @foreach
以类似于您在问题中所做的方式循环遍历数组。 但是,正如我在上面的第一点中强调的那样,如果您的逻辑和同步发生在 Blade/Livewire 中,为什么还要麻烦 @entangle
-ing?当然,如果首先想要 @entangle
的重点是使用 Alpine 的循环解决方案,也就是说你可以这样做:
<template x-for="(perms, group) in dbPermissions">
<p x-text="group"></p>
<template x-for="(props, permId) in perms">
<input type="radio" x-model="dbPermissions[group][permId].is_checked">
</template>
</template>
当然,我所有的代码都是伪代码,因为我没有完全掌握您的实际解决方案。我在此站点上的意图始终是公开分享概念,而不是将您的特定问题解决到 T。