Multiselect

ПолС для Π²Ρ‹Π±ΠΎΡ€Π° Π½Π΅ΡΠΊΠΎΠ»ΡŒΠΊΠΈΡ… Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ.

ΠŸΠΎΠ΄ΠΎΠΉΠ΄Π΅Ρ‚ для Ρ€Π°Π±ΠΎΡ‚Ρ‹ со связями рСсурса, Π½ΠΎ ΠΌΠΎΠΆΠ½ΠΎ Π²Ρ‹Π²ΠΎΠ΄ΠΈΡ‚ΡŒ ΠΈ Π»ΡŽΠ±Ρ‹Π΅ ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ»ΡŒΠ½Ρ‹Π΅ Π΄Π°Π½Π½Ρ‹Π΅.

Π’ livewire ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π΅ Π½ΡƒΠΆΠ½ΠΎ ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈΡ‚ΡŒ 2 поля:

  • ΠΏΠΎΠ»Π΅ со списком доступных Π²Π°Ρ€ΠΈΠ°Π½Ρ‚ΠΎΠ² Π² multiselect

  • ΠΏΠΎΠ»Π΅ с Π²Ρ‹Π±Ρ€Π°Π½Π½Ρ‹ΠΌΠΈ значСниями

Multiselect Π±Π΅Π· сортировки

Для ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π° Π²Ρ‹Π²Π΅Π΄Π΅ΠΌ ΠΏΠΎΠ»Π΅ для Π²Ρ‹Π±ΠΎΡ€Π° ΠΊΠ°Ρ‚Π΅Π³ΠΎΡ€ΠΈΠΉ поста.

posts
    id - integer
    title - string
 
categories
    id - integer
    title - string
 
post_category
    post_id - integer
    category_id - integer

Код livewire ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π°:

<?php

namespace App\Http\Livewire\Admin\Posts;

use App\Models\Category;
use App\Models\Post;
use WebVovan\RockCms\Http\Livewire\ResourceComponent;

class PostItem extends ResourceComponent
{
    ...

    // Бписок доступных ΠΊΠ°Ρ‚Π΅Π³ΠΎΡ€ΠΈΠΉ
    public array $categories;
    
    // Бписок Π²Ρ‹Π±Ρ€Π°Π½Π½Ρ‹Ρ… ΠΊΠ°Ρ‚Π΅Π³ΠΎΡ€ΠΈΠΉ
    public array $selectedCategories;

    public function init()
    {
        ...
        
        // Π˜Π½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΡ списка доступных ΠΊΠ°Ρ‚Π΅Π³ΠΎΡ€ΠΈΠΉ
        $this->categories = Category::all()
            ->map(function($category) {
                return [
                    'id' => $category->id,
                    'title' => $category->title,
                ];
            })->toArray();
            
        // Π˜Π½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΡ списка Π²Ρ‹Π±Ρ€Π°Π½Π½Ρ‹Ρ… ΠΊΠ°Ρ‚Π΅Π³ΠΎΡ€ΠΈΠΉ        
        $this->selectedCategories = $this->resource->categories
            ->pluck('id')
            ->toArray();
    }
    
    public function save()
    {
        ...

        // Π‘ΠΎΡ…Ρ€Π°Π½Π΅Π½ΠΈΠ΅ Π²Ρ‹Π±Ρ€Π°Π½Π½Ρ‹Ρ… ΠΊΠ°Ρ‚Π΅Π³ΠΎΡ€ΠΈΠΉ
        $this->resource->categories()->sync($this->selectedCategories);
    }
}

Π’Ρ‹Π²ΠΎΠ΄ поля Π² шаблонС:

<x-rock-cms::fields.multiselect
    :items="$categories"
    :selectedItems="$selectedCategories"
    itemsField="categories"
    selectedItemsField="selectedCategories"
    title="ΠšΠ°Ρ‚Π΅Π³ΠΎΡ€ΠΈΠΈ"
/>

ΠžΠΏΡ†ΠΈΠΈ:

  • items - массив с доступными Π²Π°Ρ€ΠΈΠ°Π½Ρ‚Π°ΠΌΠΈ

  • selectedItems - массив с Π²Ρ‹Π±Ρ€Π°Π½Π½Ρ‹ΠΌΠΈ Π²Π°Ρ€ΠΈΠ°Π½Ρ‚Π°ΠΌΠΈ

  • itemsField - Π½Π°Π·Π²Π°Π½ΠΈΠ΅ поля с доступными Π²Π°Ρ€ΠΈΠ°Π½Ρ‚Π°ΠΌΠΈ

  • selectedItemsField - Π½Π°Π·Π²Π°Π½ΠΈΠ΅ поля с Π²Ρ‹Π±Ρ€Π°Π½Π½Ρ‹ΠΌΠΈ Π²Π°Ρ€ΠΈΠ°Π½Ρ‚Π°ΠΌΠΈ

Multiselect с сортировкой

Для ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠΈ сортировки Π΄ΠΎΠ±Π°Π²ΠΈΠΌ Π² Ρ‚Π°Π±Π»ΠΈΡ†Ρƒ post_category ΠΏΠΎΠ»Π΅ order.

posts
    id - integer
    title - string
 
categories
    id - integer
    title - string
 
post_category
    post_id - integer
    category_id - integer
    order - integer

Π’ ΠΊΠΎΠ΄Π΅ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π° ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡ΠΈΠΌ Ρ‚Ρ€Π΅ΠΉΡ‚Ρ‹ HasSortable ΠΈ HasMultiselect.

<?php

namespace App\Http\Livewire\Admin\Posts;

use App\Models\Category;
use App\Models\Post;
use WebVovan\RockCms\Http\Livewire\ResourceComponent;
use WebVovan\RockCms\Traits\Livewire\HasMultiselect;
use WebVovan\RockCms\Traits\Livewire\HasSortable;

class PostItem extends ResourceComponent
{
    use HasSortable;
    use HasMultiselect;
    
    // Бписок доступных ΠΊΠ°Ρ‚Π΅Π³ΠΎΡ€ΠΈΠΉ
    public array $categories;
    
    // Бписок Π²Ρ‹Π±Ρ€Π°Π½Π½Ρ‹Ρ… ΠΊΠ°Ρ‚Π΅Π³ΠΎΡ€ΠΈΠΉ
    public array $selectedCategories;

    public function init()
    {
        ...
        
        // Π˜Π½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΡ списка доступных ΠΊΠ°Ρ‚Π΅Π³ΠΎΡ€ΠΈΠΉ
        $this->categories = Category::all()
            ->map(function($category) {
                return [
                    'id' => $category->id,
                    'title' => $category->title,
                ];
            })->toArray();

        // Π˜Π½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΡ списка Π²Ρ‹Π±Ρ€Π°Π½Π½Ρ‹Ρ… ΠΊΠ°Ρ‚Π΅Π³ΠΎΡ€ΠΈΠΉ
        $this->selectedCategories = $this->resource->categories
            ->map(function ($category) {
                return [
                    'id' => $category->id,
                    'title' => $category->title,
                ];
            })->toArray();

    }

    public function save()
    {
        ...

        // Π‘ΠΎΡ…Ρ€Π°Π½Π΅Π½ΠΈΠ΅ Π²Ρ‹Π±Ρ€Π°Π½Π½Ρ‹Ρ… ΠΊΠ°Ρ‚Π΅Π³ΠΎΡ€ΠΈΠΉ
        $this->resource->categories()->sync(
            collect($this->selectedCategories)->reduce(function($acc, $item, $key) {
                $acc[$item['id']] = ['order' => $key];
                return $acc;
            }, [])
        );
    }
}

Для ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠΈ сортировки Π² шаблонС Π²Ρ‹Π²ΠΎΠ΄Π° Π½ΡƒΠΆΠ½ΠΎ Π΄ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ ΠΎΠΏΡ†ΠΈΡŽ sortable:

<x-rock-cms::fields.multiselect
    :items="$categories"
    :selectedItems="$selectedCategories"
    itemsField="categories"
    selectedItemsField="selectedCategories"
    sortable
    title="ΠšΠ°Ρ‚Π΅Π³ΠΎΡ€ΠΈΠΈ"
/>

ДинамичСский поиск

Если Π΄Π°Π½Π½Ρ‹Ρ… для Π²Ρ‹Π²ΠΎΠ΄Π° Π² multiselect ΠΎΡ‡Π΅Π½ΡŒ ΠΌΠ½ΠΎΠ³ΠΎ, Ρ‚ΠΎ ΠΌΠΎΠΆΠ½ΠΎ ΠΏΡ€ΠΈ ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½Π½Ρ‹ΠΉ Π½Π°Π±ΠΎΡ€, Π° ΠΎΡΡ‚Π°Π»ΡŒΠ½ΠΎΠ΅ ΠΈΡΠΊΠ°Ρ‚ΡŒ динамичСски.

ДинамичСский поиск Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΏΡ€ΠΈ использовании сортировки.

Π’ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π΅ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈΠΌ ΠΌΠ΅Ρ‚ΠΎΠ΄ searchCategories() для поиска ΠΊΠ°Ρ‚Π΅Π³ΠΎΡ€ΠΈΠΉ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π±ΡƒΠ΄ΡƒΡ‚ Π²Ρ‹Π²ΠΎΠ΄ΠΈΡ‚ΡŒΡΡ Π² спискС.

<?php

namespace App\Http\Livewire\Admin\Posts;

use App\Models\Category;
use App\Models\Post;
use WebVovan\RockCms\Http\Livewire\ResourceComponent;
use WebVovan\RockCms\Traits\Livewire\HasMultiselect;
use WebVovan\RockCms\Traits\Livewire\HasSortable;

class PostItem extends ResourceComponent
{
    use HasSortable;
    use HasMultiselect;
    
    // Бписок доступных ΠΊΠ°Ρ‚Π΅Π³ΠΎΡ€ΠΈΠΉ
    public array $categories;
    
    // Бписок Π²Ρ‹Π±Ρ€Π°Π½Π½Ρ‹Ρ… ΠΊΠ°Ρ‚Π΅Π³ΠΎΡ€ΠΈΠΉ
    public array $selectedCategories;
    
    /**
     * Поиск ΠΊΠ°Ρ‚Π΅Π³ΠΎΡ€ΠΈΠΉ для multiselect
     * 
     * @param string $word
     */
    public function searchCategories(string $word)
    {
        $this->categories = Category::where('title', 'like', '%' . $word . '%')
            ->limit(5)
            ->get()
            ->map(function($item) {
                return [
                    'id' => $item->id,
                    'title' => $item->title,
                ];
            })->toArray();
    }

    public function init()
    {
        ...
        
        // ΠŸΡ€ΠΈ ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ Π² multiselect ΠΏΠΎΠΊΠ°Π·Ρ‹Π²Π°Π΅ΠΌ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ 5 послСдних ΠΊΠ°Ρ‚Π΅Π³ΠΎΡ€ΠΈΠΉ 
        $this->categories = Category::limit(5)
            ->orderByDesc('id')
            ->get()
            ->map(function($category) {
                return [
                    'id' => $category->id,
                    'title' => $category->title,
                ];
            })->toArray();

        // Π˜Π½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΡ списка Π²Ρ‹Π±Ρ€Π°Π½Π½Ρ‹Ρ… ΠΊΠ°Ρ‚Π΅Π³ΠΎΡ€ΠΈΠΉ
        $this->selectedCategories = $this->resource->categories
            ->map(function ($category) {
                return [
                    'id' => $category->id,
                    'title' => $category->title,
                ];
            })->toArray();

    }

    public function save()
    {
        ...

        // Π‘ΠΎΡ…Ρ€Π°Π½Π΅Π½ΠΈΠ΅ Π²Ρ‹Π±Ρ€Π°Π½Π½Ρ‹Ρ… ΠΊΠ°Ρ‚Π΅Π³ΠΎΡ€ΠΈΠΉ
        $this->resource->categories()->sync(
            collect($this->selectedCategories)->reduce(function($acc, $item, $key) {
                $acc[$item['id']] = ['order' => $key];
                return $acc;
            }, [])
        );
    }
}

ΠŸΡ€ΠΈ Π²Ρ‹Π²ΠΎΠ΄Π΅ поля Π² шаблонС Π² свойствС liveSearch ΡƒΠΊΠ°Π·Ρ‹Π²Π°Π΅ΠΌ ΠΌΠ΅Ρ‚ΠΎΠ΄ для динамичСского поиска:

<x-rock-cms::fields.multiselect
    :items="$categories"
    :selectedItems="$selectedCategories"
    itemsField="categories"
    selectedItemsField="selectedCategories"
    liveSearch="searchCategories"
    sortable
    title="ΠšΠ°Ρ‚Π΅Π³ΠΎΡ€ΠΈΠΈ"
/>

Last updated