laravel 带有Livewire的Choices.js用于多个选择

cotxawn7  于 2023-03-31  发布在  其他
关注(0)|答案(1)|浏览(141)

我是几个月前发现Livewire的新手,对Vanilla JS有点生疏。
我已经创建了一个Livewire组件来过滤新闻文章表,但我很难使用Choices.js库来选择多个类别并将它们放入数组中。

Livewire组件:

public $filters = [
   ...
   'categories' => [],
   ...
];

public function render()
{
   $reports = Article::query()
      ->where('active', true)
      ->when($this->filters['categories'], function ($query, $category_ids) {
         $query->whereHas('categories', function ($query) use ($category_ids) {
            $query->whereIn('category_id', $category_ids);
         });
      })
      ->get();

   $categories = Category::all();

   return view('livewire.reports.list-reports', compact('categories'));
}

刀片:

...
<div class="mb-2" wire:ignore>
   <label class="mb-1">Category</label>
   <select wire:model="filters.categories" class="form-control js-choice" multiple id="filter-categories">
   @foreach ($categories as $category)
      <option value="{{ $category->id }}">{{ $category->type }}</option>
   @endforeach
   </select>
</div>
...
@section('page-scripts')
<script src="{{ asset('assets/js/user/plugins/choices/choices.js') }}"></script>
@endsection

choices.js文件:

import Choices from "choices.js";

const elements = document.querySelectorAll('.js-choice');

elements.forEach((item) => {
    const choices = new Choices(item, {
        removeItems: true,
        removeItemButton: true,
        searchEnabled: true,
        placeholder: true,
        placeholderValue: 'Select your options'
    });
    return choices;
});

问题是

在不使用choices.js和使用本机浏览器多选框的情况下,它工作得非常好,filter.categories属性输出"categories": ["13","2","26"...]并相应地更新控制器查询,显示具有所选类别ID的所有新闻文章。
但是使用choices.js,它只输出最后一次点击的值,看起来像这样:"categories": {"value":"13"}。因为它不在数组中,所以它只是返回在此示例中ID为13的所有新闻文章。单击多个选项只是将属性更改为最后单击的选项。此外,从选择框中清除所有选项不会将filters.categories属性重置为空,它只是使用最后关闭的选项的ID填充它。
我如何收集所选选项的ID并将其放置到filter.categories数组中,并在删除项目时删除它们?
我知道我需要在choices.js文件中放入一些逻辑来访问所选选项的detail.value,但我真的很难让它工作。我已经探索了Alpine,因为我相信这可能是关键,但我不知道从哪里开始。
任何帮助都是非常感谢的,我已经被困在这几天。

ajsxfq5m

ajsxfq5m1#

我没有choices.js的经验,所以我会根据我使用slimselect.js的经验尽我所能。
基本上,当JS应用于选择框时,它通常会抽象出您实际单击的内容,并且这些元素已经在wire:ignore块中,因此部分DOM不会重新加载。
所以当我使用你描述的东西时,我使用JS回调函数来设置Livewire组件的属性。
最简单的形式是这样的

//where dataArray is the JS array you want to assign to the livewire component
@this.set(filters.categories, dataArray);

只要看看choices.js文档,你就可以使用'choice'事件。

const element = document.getElementById('filter-categories');
element.addEventListener(
  'choice',
  function(event) {
    //this is just selecting what the choices element's data is. not sure on syntax sorry.
    var dataArray = this.choices;
    @this.set(filters.categories, dataArray);
  },
  false,
);

希望这能帮上忙

相关问题