-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(GDB-11566) Introduce multi-select dropdown directive
## WHAT: - Adds a new directive multiselectDropdown along with its template - Includes styles in workbench-custom.css to display a multi-select dropdown with checkboxes. - Updates webpack.config.common.js to copy the new template to the correct build location. ## WHY: - Needed a simple and reusable multi-select component for selecting multiple items ## HOW: - Created multiselect-dropdown.directive.js - Added custom styling and positioning rules - Updated webpack.config.common.js to ensure the template files are copied when building the app
- Loading branch information
1 parent
f6d5688
commit 91cf392
Showing
4 changed files
with
192 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
125 changes: 125 additions & 0 deletions
125
src/js/angular/core/directives/multiselect-dropdown/multiselect-dropdown.directive.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
/** | ||
* @function multiselectDropdown | ||
* @description | ||
* A directive for rendering a multi-select dropdown. | ||
* | ||
* This directive displays a list of options with checkboxes that allows users | ||
* to select multiple items. Each option should be an instance of the | ||
* SelectOptionsModel, which encapsulates the display label, value, | ||
* selection state, and any additional data. Clicking the toggle button opens/closes | ||
* the dropdown; clicking outside the dropdown closes it. | ||
* | ||
* @example | ||
* ### HTML Usage: | ||
* ```html | ||
* <multiselect-dropdown | ||
* ng-model="selectedOptions" | ||
* options="myOptions" | ||
* dropdown-label="'Choose Items'"> | ||
* </multiselect-dropdown> | ||
* ``` | ||
* | ||
* ### Controller Example: | ||
* ```javascript | ||
* angular.module('myApp', []) | ||
* .controller('ExampleController', function($scope) { | ||
* $scope.myOptions = [ | ||
* new SelectOptionsModel({ label: 'Option A', value: 'A' }), | ||
* new SelectOptionsModel({ label: 'Option B', value: 'B' }), | ||
* new SelectOptionsModel({ label: 'Option C', value: 'C' }) | ||
* ]; | ||
* }); | ||
* ``` | ||
* | ||
* @param {Array.<SelectOptionsModel>} options - The array of options displayed in the dropdown. | ||
* @param {string=} [dropdownLabel='Select...'] - (Optional) The placeholder text if no items are selected. | ||
* | ||
* @returns {Object} The directive definition object. | ||
*/ | ||
angular.module('graphdb.framework.core.directives.multiselect-dropdown', []) | ||
.directive('multiselectDropdown', ['$translate', function ($translate) { | ||
return { | ||
restrict: 'E', | ||
require: 'ngModel', | ||
scope: { | ||
options: '=', | ||
dropdownLabel: '=?' | ||
}, | ||
templateUrl: 'js/angular/core/directives/multiselect-dropdown/templates/multiselect-dropdown.html', | ||
link: function($scope, element, attrs, ngModel) { | ||
// ========================= | ||
// Public variables | ||
// ========================= | ||
$scope.isOpen = false; | ||
|
||
// ========================= | ||
// Private methods | ||
// ========================= | ||
// Close the dropdown if the user clicks outside it. | ||
const handleDocumentClick = (event) => { | ||
if (!element[0].contains(event.target)) { | ||
$scope.$apply(() => { | ||
$scope.isOpen = false; | ||
}); | ||
} | ||
}; | ||
|
||
const updateModel = () => { | ||
const selected = $scope.options.filter(function(option) { | ||
return option.selected; | ||
}); | ||
ngModel.$setViewValue(selected); | ||
} | ||
|
||
// ========================= | ||
// Public methods | ||
// ========================= | ||
$scope.toggleDropdown = function () { | ||
$scope.isOpen = !$scope.isOpen; | ||
}; | ||
|
||
/** | ||
* Toggle the selection state of an option. | ||
* @param {SelectOptionsModel} option | ||
*/ | ||
$scope.toggleSelection = function (option) { | ||
option.selected = !option.selected; | ||
updateModel(); | ||
}; | ||
|
||
/** | ||
* Build the display text for the dropdown toggle. | ||
* Iterates the options and joins the labels of selected options. | ||
* @returns {string} | ||
*/ | ||
$scope.getSelectedText = function () { | ||
const selectedOptions = $scope.options.filter((option) => option.selected); | ||
if (selectedOptions.length === 0) { | ||
return $scope.dropdownLabel || $translate.instant('common.select'); | ||
} | ||
return selectedOptions.map((option) => option.label).join(', '); | ||
}; | ||
|
||
/** | ||
* If ngModel provides an initial value, update the corresponding option selections. | ||
*/ | ||
ngModel.$render = function () { | ||
if (angular.isArray(ngModel.$viewValue)) { | ||
$scope.options.forEach(function(option) { | ||
option.selected = ngModel.$viewValue.some(function(selectedOption) { | ||
return selectedOption.value === option.value; | ||
}); | ||
}); | ||
} | ||
}; | ||
|
||
// ========================= | ||
// Subscriptions | ||
// ========================= | ||
document.addEventListener('click', handleDocumentClick); | ||
$scope.$on('$destroy', () => { | ||
document.removeEventListener('click', handleDocumentClick); | ||
}); | ||
} | ||
}; | ||
}]); |
15 changes: 15 additions & 0 deletions
15
src/js/angular/core/directives/multiselect-dropdown/templates/multiselect-dropdown.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
<div class="dropdown multi-select" ng-class="{'open': isOpen}"> | ||
<button type="button" | ||
class="form-control dropdown-toggle multi-select text-left" | ||
ng-click="toggleDropdown()"> | ||
{{ dropdownLabel || getSelectedText() }} | ||
</button> | ||
<ul class="dropdown-menu multi-select" role="menu"> | ||
<li class="dropdown-item multi-select" | ||
ng-repeat="option in options track by $index" | ||
ng-click="toggleSelection(option)"> | ||
<input type="checkbox" ng-model="option.selected"> | ||
{{option.label}} | ||
</li> | ||
</ul> | ||
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters