rft / yii2-searchable-depdrop
A custom searchable dependent dropdown widget for Yii2
Installs: 11
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
Language:JavaScript
Type:yii2-extension
pkg:composer/rft/yii2-searchable-depdrop
Requires
- yiisoft/yii2: ~2.0.0
README
A reusable Yii2 widget that provides a searchable dropdown list with support for dependent (cascading) dropdowns.
It is designed to work seamlessly within the wbraganca/yii2-dynamicform widget and has no dependency on any specific CSS framework like Bootstrap.
Note: This package uses the
rft\searchabledepdrop\widgetsnamespace. Make sure to update your imports if you're upgrading from an older version.
Features
- Searchable dropdown list.
- Support for dependent dropdowns (e.g., State -> City).
- Multiple selection support - Allow users to select multiple values.
- Works with
wbraganca/yii2-dynamicformfor creating dynamic forms. - Framework-independent styling with modern, responsive design.
- Custom styling for multiple selection with removable tags.
- Compatible with PHP 5.6+ and modern Yii2 projects.
Installation
Via Composer (Recommended)
The preferred way to install this extension is through Composer.
composer require rft/yii2-searchable-depdrop
Yii2 will automatically load the widget via Composer’s autoloader.
Manual Installation (Alternative)
If you don't want to use Composer, you can still install it manually:
- Download the source files from the
src/directory - Place them in your project's widget directory (e.g.,
common/widgets/searchable_dep_drop/) - Ensure the namespace in the widget files matches the new location if you change it
- Include the CSS and JS assets from the
src/assets/directory
Usage
1. Controller Action for Dependent Data
For dependent dropdowns, you need a controller action that returns data in JSON format.
The widget expects the parent value as a POST parameter (the name of the parameter is derived from the parent field's name).
The action should return a JSON object with an output key, which is an array of objects, each having an id and text property.
Example Controller Action:
public function actionListCities() { \Yii::\$app->response->format = \yii\web\Response::FORMAT_JSON; $out = ['output' => [], 'selected' => '']; if (Yii::\$app->request->post('state')) { $state = Yii::\$app->request->post('state'); if ($state) { $cities = AddressCity::find() ->where(['state' => $state]) ->orderBy('name') ->all(); $output = []; foreach ($cities as $city) { $output[] = ['id' => $city->id, 'text' => $city->name]; } $out['output'] = $output; } } return $out; }
2. View File Setup
In your view file, you can use the widget like any other Yii2 input widget.
A. Standalone Searchable Dropdown
use rft\searchabledepdrop\widgets\SearchableDepDrop; echo $form->field($model, 'state')->widget(SearchableDepDrop::class, [ 'data' => [ 'California' => 'California', 'Texas' => 'Texas', // ... other states ], 'placeholder' => 'Select a state...', ]);
B. Multiple Selection Dropdown
use rft\searchabledepdrop\widgets\SearchableDepDrop; echo $form->field($model, 'tags')->widget(SearchableDepDrop::class, [ 'data' => [ '1' => 'PHP', '2' => 'JavaScript', '3' => 'Python', '4' => 'Java', '5' => 'C#', // ... other options ], 'allowMultiple' => true, 'placeholder' => 'Select multiple technologies...', ]);
C. Dependent Dropdown
Example for a State → City dropdown setup:
use rft\searchabledepdrop\widgets\SearchableDepDrop; use yii\helpers\ArrayHelper; use yii\helpers\Url; use common\models\AddressCity; // State Dropdown (Parent) echo $form->field($model, 'state')->widget(SearchableDepDrop::class, [ 'data' => ArrayHelper::map( AddressCity::find()->select('state')->distinct()->orderBy('state')->all(), 'state', 'state' ), 'options' => [ 'id' => 'address-state', ], 'placeholder' => 'Select a state...', ]); // City Dropdown (Child) echo $form->field($model, 'city_id')->widget(SearchableDepDrop::class, [ 'options' => [ 'id' => 'address-city', ], 'placeholder' => 'Select City/Municipality', 'pluginOptions' => [ 'depends' => ['address-state'], 'url' => Url::to(['/site/list-cities']), ], ])->label('City/Municipality');
Styling Features
The widget comes with built-in CSS that provides:
- Modern Design: Clean, professional appearance with subtle shadows and borders
- Responsive Layout: Adapts to different screen sizes and container widths
- Multiple Selection Tags: Selected items appear as removable tags with:
- Black background with white text
- Rounded corners (12px border-radius)
- Remove button (×) with hover effects
- Text truncation for long items
- Search Interface: Dedicated search input with clear visual separation
- Dropdown Styling:
- Smooth hover effects
- Scrollable list (max-height: 200px)
- Active item highlighting
- No results message styling
- Framework Independence: No dependency on Bootstrap or other CSS frameworks
Custom Styling
You can override the default styles by targeting the CSS classes:
/* Main container */ .sdd-container { /* Your custom styles */ } /* Display area */ .sdd-display { border: 2px solid #your-color; border-radius: 6px; } /* Selected items in multiple selection */ .sdd-selected-item { background-color: #your-color; border-radius: 8px; } .sdd-selected-item-container { max-width: 100px; /* Adjust tag width */ } .sdd-item-text { font-size: 12px; /* Adjust text size */ } .sdd-remove-btn { color: #your-remove-color; } /* Dropdown */ .sdd-dropdown { box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); border-radius: 4px; } /* Search input */ .sdd-search { padding: 10px 12px; font-size: 14px; } /* List items */ .sdd-list li { padding: 10px 15px; } .sdd-list li:hover { background-color: #your-hover-color; }
Available CSS Classes
| Class | Purpose |
|---|---|
.sdd-container |
Main widget container |
.sdd-display |
Display area showing selected values |
.sdd-selected-item |
Individual selected item tag |
.sdd-selected-item-container |
Container for selected item and remove button |
.sdd-item-text |
Text within selected item |
.sdd-remove-btn |
Remove button (×) for selected items |
.sdd-dropdown |
Dropdown container |
.sdd-search |
Search input field |
.sdd-list |
List of available options |
.sdd-active |
Currently highlighted option |
.sdd-no-results |
No results message |
Configuration Options
The widget supports several configuration options:
| Option | Type | Default | Description |
|---|---|---|---|
data |
array | [] |
Array of options for the dropdown |
url |
string | null |
URL for dependent dropdown data |
depends |
array | [] |
Array of parent field IDs for dependent dropdowns |
paramNames |
array | [] |
Custom parameter names for dependent requests |
placeholder |
string | 'Select...' |
Placeholder text for the dropdown |
allowMultiple |
boolean | false |
Enable multiple selection |
rowSelector |
string | '.item-item, .item' |
CSS selector for dynamic form rows |
pluginOptions |
array | [] |
Additional JavaScript options |
3. Dynamic Form Integration
The widget works seamlessly with wbraganca/yii2-dynamicform. Here's how to implement dependent dropdowns in dynamic forms:
Essential Widget Usage:
use rft\searchabledepdrop\widgets\SearchableDepDrop; // State dropdown (parent) echo $form->field($addresses[$i], "[{$i}]state")->widget(SearchableDepDrop::classname(), [ 'data' => ArrayHelper::map( AddressCity::find()->select('state')->distinct()->orderBy('state')->all(), 'state', 'state' ), 'placeholder' => 'Select State...', 'options' => ['class' => 'form-control state-dropdown'], ]); // City dropdown (child - depends on state) echo $form->field($addresses[$i], "[{$i}]city_id")->widget(SearchableDepDrop::classname(), [ 'data' => [], 'placeholder' => 'Select City...', 'options' => ['class' => 'form-control city-dropdown'], 'pluginOptions' => [ 'depends' => ['.state-dropdown'], 'paramNames' => ['state'], 'url' => Url::to(['/site/cities']), ] ]);
Required JavaScript for Dynamic Forms:
function initSearchableDepDrop(context) { $(context) .find(".sdd-container") .each(function () { var $container = $(this); if ($container.data("searchableDepDrop")) return; var optionsJson = $container.data("sdd-options"); if (optionsJson) { var options = typeof optionsJson === "string" ? JSON.parse(optionsJson) : optionsJson; $container.searchableDepDrop(options); } }); } // Initialize widgets on new form rows $(".dynamicform_wrapper").on("afterInsert", function (e, item) { initSearchableDepDrop(item); }); // Initialize existing widgets initSearchableDepDrop(document.body);
Note: Replace
.dynamicform_wrapperwith your actualwidgetContainerclass fromDynamicFormWidget::begin().
Multiple Selection Example
To enable multiple selection in any dropdown, simply set allowMultiple => true:
// Multiple selection for skills/tags echo $form->field($model, 'skills')->widget(SearchableDepDrop::classname(), [ 'data' => [ '1' => 'PHP', '2' => 'JavaScript', '3' => 'Python', '4' => 'Java', '5' => 'C#', '6' => 'Ruby', '7' => 'Go', '8' => 'Swift', ], 'allowMultiple' => true, 'placeholder' => 'Select your skills...', 'options' => ['class' => 'form-control skills-dropdown'], ]); // Multiple selection for categories in dynamic form echo $form->field($contact, "[{$i}]categories")->widget(SearchableDepDrop::classname(), [ 'data' => [ '1' => 'Business', '2' => 'Personal', '3' => 'Emergency', '4' => 'Family', '5' => 'Friend', ], 'allowMultiple' => true, 'placeholder' => 'Select contact categories...', 'options' => ['class' => 'form-control categories-dropdown'], ]);
Important Notes:
- For multiple selection, your model attribute should be an array or JSON field
- The widget automatically handles the serialization of multiple values
- Selected items appear as removable tags in the display area
- The
paramNamesoption is crucial for dependent dropdowns to work properly
Recent Changes (v1.0.1)
Fixed Issues
- Fixed PSR-4 Autoloading: Reorganized file structure to match namespace requirements
- Moved
SearchableDepDrop.phptosrc/widgets/SearchableDepDrop.php - Moved
SearchableDepDropAsset.phptosrc/widgets/SearchableDepDropAsset.php - Updated asset sourcePath to use vendor directory path
- This resolves the "Class not found" error after composer install
- Moved
Enhanced Features
- Improved CSS Styling: Enhanced dropdown list items with text wrapping and visual separation
- Better Documentation: Added comprehensive styling documentation and usage examples
- Multiple Selection Support: Full support for selecting multiple values with removable tags
Package Structure
src/
├── widgets/
│ ├── SearchableDepDrop.php
│ └── SearchableDepDropAsset.php
└── assets/
├── css/
│ └── searchable-dep-drop.css
└── js/
└── searchable-dep-drop.js
Migration Guide
If you're upgrading from a previous version:
- Update your composer package:
composer update rft/yii2-searchable-depdrop - The namespace remains the same:
use rft\searchabledepdrop\widgets\SearchableDepDrop; - No code changes required in your existing implementations
License
This project is licensed under the MIT License.