پرش به مطلب اصلی

کامپوننت

کامپوننت x-select یک ورودی انتخاب (dropdown/select) پیشرفته برای فرم‌ها است که امکانات متنوعی مانند جستجو، انتخاب پویا، انتخاب چندتایی (multi-select)، انتخاب همه، نمایش تعداد انتخاب‌شده، کنترل فقط‌خواندنی، پیام راهنما، پیام خطا و ... را ارائه می‌دهد.


ویژگی‌ها

  • پشتیبانی از انتخاب تکی و چندتایی (multi-select)
  • قابلیت جستجو در آیتم‌ها (search)
  • امکان بارگذاری آیتم‌ها به صورت پویا از route
  • بارگذاری تدریجی (infinite scroll) با تعداد آیتمِ قابل‌تعیین در هر صفحه (perPage)
  • پشتیبانی از انتخاب همه (select all) در حالت چندتایی
  • نمایش تعداد آیتم‌های انتخاب‌شده به جای لیست (displaySelectedAsCount)
  • قابلیت پاک‌کردن انتخاب (clearable)
  • پشتیبانی از حالت فقط‌خواندنی (readonly)
  • نمایش پیام راهنما هنگام غیرفعال بودن (disabledTooltip)
  • تولتیپ به‌ازای هر آیتم (tooltip / disabledTooltip) بر اساس فعال یا غیرفعال بودنِ همان آیتم
  • نمایش پیام فقط‌خواندنی (readonlyTooltip)
  • امکان شخصی‌سازی کلاس‌های CSS برای خود و کانتینر
  • پشتیبانی از پیام راهنما (hint)
  • پشتیبانی از لیبل و فضای رزرو لیبل
  • پشتیبانی از پیام خطا و پیام‌های سفارشی با استایل‌های مختلف
  • پشتیبانی از autoClose و suppressLogicMessages
  • امکان تعریف template ویژه برای آپشن‌ها در حالت select

ورودی‌های کامپوننت

نام پراپنوع دادهمقدار پیش‌فرضتوضیحات
namestringنام فیلد (اجباری)
labelstringnullلیبل اصلی
labelSpaceReservedboolfalseآیا فضای لیبل حتی بدون مقدار رزرو شود؟
idstringnullشناسه یکتا برای ورودی
placeholderstring"انتخاب کنید"متن پیش‌فرض نمایش داده شده در ورودی
itemsarray[]آرایه‌ای از آیتم‌ها (هر آیتم باید شامل id, name باشد)
selectedstring, int, array, nullnullمقدار(های) انتخاب‌شده (در حالت multi-select، آرایه)
requiredboolfalseاجباری بودن فیلد
disabledboolfalseغیرفعال بودن ورودی
readonlyboolfalseفقط‌خواندنی بودن ورودی
clearablebooltrueامکان پاک‌کردن انتخاب‌شده
searchBarVisibilitybool, nullnullنمایش یا عدم نمایش نوار جستجو (null: اتوماتیک بر اساس تعداد آیتم‌ها)
parentIdstring, nullnullشناسه والد برای وابستگی داینامیک
infiniteScrollbool, nullnullفعال کردن قابلیت infinite scroll برای لود مقادیر سلکت
perPageint10تعداد آیتم‌های بارگذاری‌شده در هر بار اسکرول (فقط با infiniteScroll)
routeNamestring, nullnullنام route برای بارگذاری آیتم‌ها به صورت داینامیک
routeParametersstring, array, nullnullپارامترهای route تعریف شده در routeName
parametersstring, array, nullnullپارامترهای مورد نیاز (در Controller مربوط به route در دسترس خواهد بود)
allowSelectAllbool, nullfalseفعال‌سازی انتخاب همه (در حالت multi-select)
displaySelectedAsCountbool, nullfalseنمایش تعداد آیتم‌های انتخاب‌شده به جای لیست
fromFilterboolfalseاستفاده در فیلترها
autoClosebooltrue (تکی), false (چندتایی)بستن خودکار لیست پس از انتخاب
messageStylestring, enum"message"استایل نمایش پیام (message, tooltip, ...)
defaultMessageTypestring, enum"info"نوع پیام پیش‌فرض (info, error, success, ...)
defaultMessagestringnullپیام پیش‌فرض برای نمایش
suppressLogicMessagesboolfalseعدم نمایش پیام‌های منطقی
hintstringnullپیام راهنما یا توضیح کوتاه
classstringnullکلاس CSS سفارشی برای خود ورودی
containerClassstringnullکلاس CSS سفارشی برای کانتینر
disabledTooltipstringnullپیام راهنما هنگام غیرفعال بودن ورودی
readonlyTooltipstringnullپیام راهنما هنگام فقط‌خواندنی بودن ورودی
templateSelectionstringnullنام تابع جاوا اسکریپتی برای تعریف template گزینه انتخاب شده
templateResultstringnullنام تابع جاوا اسکریپتی برای تعریف template گزینه‌های لیست سلکت

فرمت آرایه آیتم‌ها (Item Array Format)

برای ارسال آیتم‌ها به کامپوننت Select، هر آیتم باید به صورت یک آرایه با ساختار زیر باشد:

کلیدنوع دادهتوضیحات
idstringاجباری. مقدار value برای گزینه
namestringاجباری. متن نمایشی برای گزینه
selectedbooleanاختیاری. اگر true باشد، این گزینه به صورت پیش‌فرض انتخاب می‌شود
is_activebooleanاختیاری. اگر false باشد، این گزینه غیرفعال (disabled) نمایش داده می‌شود
tooltipstringاختیاری. تولتیپی که هنگام هاور روی ردیفِ گزینه — وقتی فعال است — نمایش داده می‌شود
disabledTooltipstringاختیاری. تولتیپی که هنگام هاور روی ردیفِ گزینهٔ غیرفعال (is_active: false) نمایش داده می‌شود
تولتیپ به‌ازای هر آیتم

هر آیتم می‌تواند tooltip و/یا disabledTooltip داشته باشد و بر اساس فعال یا غیرفعال بودنِ همان آیتم تصمیم گرفته می‌شود کدام نمایش داده شود:

  • آیتمِ فعال → مقدار tooltip
  • آیتمِ غیرفعال (is_active: false) → مقدار disabledTooltip

تولتیپ به کلِ ردیفِ گزینه (li) متصل می‌شود، پس هاور روی هر جای ردیف آن را نشان می‌دهد؛ روی ردیف‌های غیرفعال هم pointer-events دوباره فعال می‌شود تا هاور کار کند.


ساخت Select وابسته (Dependent Select)

برای ساخت Select وابسته (مثلاً انتخاب شهر بر اساس استان)، کافی است پراپرتی‌های زیر را روی Select فرزند تنظیم کنید:

  1. parentId: مقدار این پراپرتی باید برابر با id کامپوننت Select والد باشد.
  2. routeName: نام route یا API که داده‌های وابسته را برمی‌گرداند (مثلاً "api.cities").
  3. parameters (اختیاری): پارامترهای اضافی برای ارسال به API.
والدِ چندانتخابی

اگر Select والد چندانتخابی باشد، با تغییر انتخاب‌ها یک درخواست برای همه‌ی مقادیر انتخاب‌شده ارسال می‌شود (نه یک درخواست به‌ازای هر مقدار) و Select فرزند یک لیست یکپارچه از نتایج همه‌ی آن‌ها را نمایش می‌دهد.

سمت کنترلر، این مقادیر در parentSelected قرار می‌گیرند؛ جزئیات در مستند کنترلر.


متدها

متدتوضیحات
$(selector).items(data)
پر کردن مقادیر select با استفاده از جاوااسکریپت

مثال‌ها

انتخاب استان و شهر به صورت وابسته

<x-select
id="province-select-depend-on"
containerClass="col-md-4"
name="province_id"
label="استان"
:items="$provinces"
:selected="old('province_id')"
/>

<x-select
id="city-select-depend-on"
containerClass="col-md-4"
parentId="province-select-depend-on"
routeName="admin.admins.admins.select.cities"
:allowSelectAll="true"
name="city_id"
label="شهر"
:selected="old('city_id', 34)"
defaultMessage="نمایش حقوق"
defaultMessageType="warning"
messageStyle="message"
/>

<x-select
id="center-select-depend-on"
containerClass="col-md-4"
name="center_id"
label="مرکز"
:selected="old('center_id', 45)"
routeName="admin.admins.admins.select.centers"
parentId="city-select-depend-on"
/>

انتخاب چندتایی (Multi-select) با قابلیت انتخاب همه (Select All)

<x-multi-select
id="province-multiselect-normal"
containerClass="col-md-4"
name="province_ids"
label="استان"
:items="$provinces"
:selected="[old('province_id')]"
allow-select-all="1"
/>
نکته

اگر می خواهید از select در فیلتر کامپوننت table استفاده کنید و قابلیت انتخاب چندتایی باید در فیلتر وجود داشته باشد باید از کامپوننت multi select استفاده کنید

تولتیپ به‌ازای هر آیتم (فعال/غیرفعال)

هر آیتم می‌تواند tooltip (برای حالت فعال) و disabledTooltip (برای حالت غیرفعال) داشته باشد. بسته به مقدار is_active، تولتیپِ مناسب هنگام هاور روی ردیفِ گزینه نمایش داده می‌شود.

<x-select
id="province-select"
name="province_id"
:label="__('استان')"
:items="[
[
'id' => 1,
'name' => 'تهران',
'is_active' => true,
'tooltip' => 'استان تهران قابل انتخاب است',
],
[
'id' => 2,
'name' => 'البرز',
'is_active' => false,
'disabledTooltip' => 'استان البرز در حال حاضر غیرفعال است',
],
]"
/>
  • آیتم فعال (is_active: true) → متنِ tooltip نمایش داده می‌شود.
  • آیتم غیرفعال (is_active: false) → متنِ disabledTooltip نمایش داده می‌شود.

تولتیپ به کلِ ردیف (li) متصل است، پس هاور روی هر جای ردیف کافی است.

اجرای کد جاوااسکریپت بعد از لود شدن داده‌ها در سلکت‌های وابسته

برای کنترل بیشتر روی این سلکت‌ها، رویدادی به نام depend-on-fetched تعریف شده است که نحوه عملکرد آن به صورت زیر می‌باشد:

$("#city-select-depend-on").on("depend-on-fetched", (event, data) => {
console.log(data);
});

در کد بالا کامپوننت city-select-depend-on یک سلکت وابسته به یک المان دیگر است. با تغییر مقدار المان والد، مقادیر این سلکت نیز به طور خودکار fetch شده و در سلکت قرار می‌گیرند. این متد به شما این اجازه را می‌دهد که پس از تکمیل این مراحل و لود شدن داده‌ها در کامپوننت city-select-depend-on، کد جاوااسکریپتی مورد نیازتان را اجرا کنید. مانند مثال زیر:

$("#city-select-depend-on").on("depend-on-fetched", (event) => {
$("#city-select-depend-on").setValue("xyz");
});
نکته

لازم به ذکر است که برای عملکرد درست این رویداد، باید تمام پارامترهای مورد نیاز در سلکت‌های وابسته و المان والد قرار داده شده باشند.

مقداردهی با جاوااسکریپت

برای مقداردهی یا تغییر مقدار کامپوننت x-select به صورت داینامیک با جاوااسکریپت، می‌توانید از متد زیر استفاده کنید:

// مقداردهی با مقدار تکی
$("#select-id").setValue("option_value");

// مقداردهی با آرایه (در حالت multi-select)
$("#select-id").setValue(["option1", "option2"]);
  • مقدار جدید به صورت خودکار در سلکت انتخاب می‌شود و رویداد change نیز اجرا می‌گردد.
  • گزینه‌های انتخاب‌شده به عنوان مقدار پیش‌فرض (برای ریست) نیز ذخیره می‌شوند.
  • در حالت multi-select، مقدار باید آرایه‌ای از مقادیر گزینه‌ها باشد.

نمایش template ویژه برای گزینه‌های سلکت

<script>
window.customSelectTemplate = function (state) {
// THIS IS REQUIRED FOR PLACEHOLDER
if (!state.id) return state.text;

const $state = $(state.element);

// CUSTOM PROPS NEEDED FOR DESIGN
const image = $state.data("image");
const code = $state.data("code");
const description = $state.data("description");

// THIS IS REQUIRED FOR DISABLE ITEMS
const isDisabled = $state.data("disabled") || $state.closest("select").attr("readonly");

// HTML TEMPLATE
return $(`
<div class="d-flex align-items-center gap-4" ${isDisabled ? 'data-disabled="true"' : ""}>
<img src="${image}" style="width:48px;height:48px;object-fit:cover;border-radius:4px;">
<div class="d-flex flex-column">
<span class="fs-14">${state.text}</span>
<small class="text-muted">کد استان: ${code} توضیحات: ${description}</small>
</div>
</div>
`);
};
</script>

<x-select
id="custom-template"
name="custom-select"
containerClass="col-md-6"
label="سلکت با آپشن کاستوم"
:items="[
[
'name' => 'آذربایجان شرقی',
'id' => 1,
'selected' => false,
'is_active' => true,
'description' => 'لورم ایپسوم متن ساختگی',
'code' => '03',
'image' => 'https://upload.wikimedia.org/630px-Flag_of_Iran.svg.png',
],
[
'name' => 'گیلان',
'id' => 2,
'selected' => false,
'is_active' => true,
'description' => 'لورم ایپسوم متن ساختگی',
'code' => '04',
'image' => 'https://upload.wikimedia.org/630px-Flag_of_Iran.svg.png',
],
[
'name' => 'فارس',
'id' => 3,
'selected' => false,
'is_active' => true,
'description' => 'لورم ایپسوم متن ساختگی',
'code' => '05',
'image' => 'https://upload.wikimedia.org/630px-Flag_of_Iran.svg.png',
],
[
'name' => 'تهران',
'id' => 4,
'selected' => true,
'is_active' => true,
'description' => 'پایتخت ایران و مرکز سیاسی، اقتصادی و فرهنگی کشور',
'code' => '01',
'image' => 'https://upload.wikimedia.org/630px-Flag_of_Iran.svg.png',
],
[
'name' => 'اصفهان',
'id' => 5,
'selected' => false,
'is_active' => true,
'description' => 'شهر تاریخی و فرهنگی با معماری باشکوه و آثار باستانی معروف',
'code' => '02',
'image' => 'https://upload.wikimedia.org/630px-Flag_of_Iran.svg.png',
],
]
"
templateResult="customSelectTemplate"
templateSelection="customSelectTemplate"
/>

infinite scroll با تعداد آیتمِ قابل‌تعیین در هر صفحه (perPage)

هنگام استفاده از infiniteScroll، تعداد آیتم‌هایی که در هر بار اسکرول بارگذاری می‌شوند با ویژگی perPage قابل تعیین است. اگر مقداری ندهید، به‌صورت پیش‌فرض ۱۰ آیتم در هر صفحه بارگذاری می‌شود.

<!-- هر بار اسکرول، ۵ آیتم بارگذاری می‌شود -->
<x-select
id="banks"
name="bank_id"
label="بانک"
:infinite-scroll="true"
:per-page="5"
route-name="api.admin.api.banks.index"
/>

<!-- بدون perPage: پیش‌فرض ۱۰ آیتم در هر صفحه -->
<x-select
id="banks-default"
name="bank_id_default"
label="بانک"
:infinite-scroll="true"
route-name="api.admin.api.banks.index"
/>
اطلاع

مقدار perPage به‌صورت pagination.pageSize به Controller ارسال می‌شود. کنترلرهایی که با dorapiPaginate() صفحه‌بندی می‌کنند به‌صورت خودکار این مقدار را اعمال می‌کنند؛ در حالت صفحه‌بندی پیش‌فرض (paginate) نیز اگر مقداری ارسال نشود، از ثابتِ PER_PAGE کنترلر استفاده می‌شود.