Socket
Socket
Sign inDemoInstall

angular-2-dropdown-multiselect

Package Overview
Dependencies
Maintainers
1
Versions
42
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

angular-2-dropdown-multiselect - npm Package Compare versions

Comparing version 1.0.8 to 1.1.0

2

package.json
{
"name": "angular-2-dropdown-multiselect",
"version": "1.0.8",
"version": "1.1.0",
"description": "Customizable dropdown multiselect in Angular 2 with bootstrap css.",

@@ -5,0 +5,0 @@ "main": "src/multiselect-dropdown.ts",

@@ -63,27 +63,24 @@ # AngularX Dropdown Multiselect for Bootstrap CSS

Import the IMultiSelectOption and IMultiSelectTexts interfaces to enable/override settings and text strings:
Import the `IMultiSelectOption` and `IMultiSelectTexts` interfaces to enable/override settings and text strings:
```js
optionsModel: number[] = [1, 2]; // Default selection
// Default selection
optionsModel: number[] = [1, 2];
// Settings configuration
mySettings: IMultiSelectSettings = {
pullRight: false,
enableSearch: false,
checkedStyle: 'checkboxes',
buttonClasses: 'btn btn-default btn-secondary',
selectionLimit: 0,
closeOnSelect: false,
autoUnselect: false,
showCheckAll: false,
showUncheckAll: false,
fixedTitle: false,
enableSearch: true,
checkedStyle: 'fontawesome',
buttonClasses: 'btn btn-default btn-block',
dynamicTitleMaxItems: 3,
maxHeight: '300px',
displayAllSelectedText: true
};
// Text configuration
myTexts: IMultiSelectTexts = {
checkAll: 'Check all',
uncheckAll: 'Uncheck all',
checked: 'checked',
checkedPlural: 'checked',
searchPlaceholder: 'Search...',
checkAll: 'Select all',
uncheckAll: 'Unselect all',
checked: 'item selected',
checkedPlural: 'items selected',
searchPlaceholder: 'Find',
defaultTitle: 'Select',

@@ -93,8 +90,12 @@ allSelected: 'All selected',

/* Labels */
// Labels / Parents
myOptions: IMultiSelectOption[] = [
{ id: 1, name: 'Car brands', isLabel: true },
{ id: 2, name: 'Volvo', parentId: 1 },
{ id: 3, name: 'Colors', isLabel: true },
{ id: 4, name: 'Blue', parentId: 3 }
{ id: 3, name: 'Honda', parentId: 1 },
{ id: 4, name: 'BMW', parentId: 1 },
{ id: 5, name: 'Colors', isLabel: true },
{ id: 6, name: 'Blue', parentId: 5 },
{ id: 7, name: 'Red', parentId: 5 },
{ id: 8, name: 'White', parentId: 5 }
];

@@ -107,5 +108,46 @@

```
### Settings
| Setting | Description | Default Value |
| -------------------- | ------------------------------------------------------------------ | ---------------- |
| pullRight | Float the dropdown to the right | false |
| enableSearch | Enable searching the dropdown items | false |
| checkedStyle | Style of checked items one of 'checkboxes', 'glyphicon' or 'fontawesome' | 'checkboxes' |
| buttonClasses | CSS classes to apply to the trigger button | 'btn btn-default' |
| itemClasses | CSS classes to apply to items | '' |
| selectionLimit | Maximum number of items that may be selected (0 = no limit) | 0 |
| autoUnselect | Unselect the previous selection(s) once selectionLimit is reached | false |
| closeOnSelect | If enabled, dropdown will be closed after selection | false |
| showCheckAll | Display the `checkAll` item to select all options | false |
| showUncheckAll | Display the `uncheckAll` item to unselect all options | false |
| fixedTitle | Use the default title (do not apply the dynamic title) | false |
| dynamicTitleMaxItems | The maximum number of options to display in the dynamic title | 3 |
| maxHeight | The maximum height for the dropdown (including unit) | '300px' |
| displayAllSelectedText | Display the `allSelected` text when all options are selected | false |
## Use model driven forms with ReactiveFormsModule:
### Texts
| Text Item | Description | Default Value |
| --------------------- | ------------------------------------------ | ---------------- |
| checkAll | The text for the "check all" option | 'Check all' |
| uncheckAll | The text for the "uncheck all" option | 'Uncheck all' |
| checked | Text for "checked" with single item selected (used in dynamic title) | 'checked' |
| checkedPlural | Text for "checked" with multiple items selected (used in dynamic title) | 'checked' |
| searchPlaceholder | Text initially displayed in search input | 'Search...' |
| defaultTitle | Title displayed in button before selection | 'Select' |
| allSelected | Text displayed when all items are selected (must be enabled in options) | 'All selected' |
## Other examples
### Single select
Although this dropdown is designed for multiple selections, a common request is to only allow a single selection without requiring the user to unselect their previous selection each time. This can be accomplished by setting selectionLimit to 1 and autoUnselect to true.
```
{
...
selectionLimit: 1,
autoUnselect: true,
...
}
```
### Use model driven forms with ReactiveFormsModule:
```js

@@ -112,0 +154,0 @@ import { IMultiSelectOption } from 'angular-2-dropdown-multiselect';

@@ -103,5 +103,12 @@ /*

MultiselectDropdown.prototype.ngOnInit = function () {
var _this = this;
this.settings = Object.assign(this.defaultSettings, this.settings);
this.texts = Object.assign(this.defaultTexts, this.texts);
this.title = this.texts.defaultTitle || '';
this.parents = [];
this.options.forEach(function (option) {
if (typeof (option.parentId) !== 'undefined' && _this.parents.indexOf(option.parentId) < 0) {
_this.parents.push(option.parentId);
}
});
};

@@ -154,2 +161,3 @@ MultiselectDropdown.prototype.writeValue = function (value) {

MultiselectDropdown.prototype.setSelected = function (_event, option) {
var _this = this;
if (!this.model) {

@@ -162,2 +170,12 @@ this.model = [];

this.onRemoved.emit(option.id);
var parentIndex = option.parentId && this.model.indexOf(option.parentId);
if (parentIndex >= 0) {
this.model.splice(parentIndex, 1);
this.onRemoved.emit(option.parentId);
}
else if (this.parents.indexOf(option.id) > -1) {
var childIds_1 = this.options.filter(function (child) { return _this.model.indexOf(child.id) > -1 && child.parentId == option.id; }).map(function (child) { return child.id; });
this.model = this.model.filter(function (id) { return childIds_1.indexOf(id) < 0; });
childIds_1.forEach(function (childId) { return _this.onRemoved.emit(childId); });
}
}

@@ -168,2 +186,16 @@ else {

this.onAdded.emit(option.id);
if (option.parentId) {
var children = this.options.filter(function (child) { return child.id !== option.id && child.parentId == option.parentId; });
if (children.every(function (child) { return _this.model.indexOf(child.id) > -1; })) {
this.model.push(option.parentId);
this.onAdded.emit(option.parentId);
}
}
else if (this.parents.indexOf(option.id) > -1) {
var children = this.options.filter(function (child) { return _this.model.indexOf(child.id) < 0 && child.parentId == option.id; });
children.forEach(function (child) {
_this.model.push(child.id);
_this.onAdded.emit(child.id);
});
}
}

@@ -190,3 +222,4 @@ else {

MultiselectDropdown.prototype.updateNumSelected = function () {
this.numSelected = this.model && this.model.length || 0;
var _this = this;
this.numSelected = this.model && this.model.filter(function (id) { return _this.parents.indexOf(id) < 0; }).length || 0;
};

@@ -215,11 +248,17 @@ MultiselectDropdown.prototype.updateTitle = function () {

};
MultiselectDropdown.prototype.searchFilterApplied = function () {
return this.settings.enableSearch && this.searchFilterText && this.searchFilterText.length > 0;
};
MultiselectDropdown.prototype.checkAll = function () {
var _this = this;
this.model = this.options
.map(function (option) {
var checkedOptions = (!this.searchFilterApplied() ? this.options :
(new MultiSelectSearchFilter()).transform(this.options, this.searchFilterText))
.filter(function (option) {
if (_this.model.indexOf(option.id) === -1) {
_this.onAdded.emit(option.id);
return true;
}
return option.id;
});
return false;
}).map(function (option) { return option.id; });
this.model = this.model.concat(checkedOptions);
this.onModelChange(this.model);

@@ -230,4 +269,13 @@ this.onModelTouched();

var _this = this;
this.model.forEach(function (id) { return _this.onRemoved.emit(id); });
this.model = [];
var unCheckedOptions = (!this.searchFilterApplied() ? this.model
: (new MultiSelectSearchFilter()).transform(this.options, this.searchFilterText).map(function (option) { return option.id; }));
this.model = this.model.filter(function (id) {
if (unCheckedOptions.indexOf(id) < 0) {
return true;
}
else {
_this.onRemoved.emit(id);
return false;
}
});
this.onModelChange(this.model);

@@ -237,3 +285,3 @@ this.onModelTouched();

MultiselectDropdown.prototype.preventCheckboxCheck = function (event, option) {
if (this.settings.selectionLimit &&
if (this.settings.selectionLimit && !this.settings.autoUnselect &&
this.model.length >= this.settings.selectionLimit &&

@@ -293,3 +341,3 @@ this.model.indexOf(option.id) === -1) {

styles: ["\n a {\n outline: none !important;\n }\n "],
template: "\n <div class=\"dropdown\">\n <button type=\"button\" class=\"dropdown-toggle\" [ngClass]=\"settings.buttonClasses\"\n (click)=\"toggleDropdown()\" [disabled]=\"disabled\">{{ title }}&nbsp;<span class=\"caret\"></span></button>\n <ul *ngIf=\"isVisible\" class=\"dropdown-menu\" [class.pull-right]=\"settings.pullRight\" [class.dropdown-menu-right]=\"settings.pullRight\"\n [style.max-height]=\"settings.maxHeight\" style=\"display: block; height: auto; overflow-y: auto;\">\n <li class=\"dropdown-item search\" *ngIf=\"settings.enableSearch\">\n <div class=\"input-group input-group-sm\">\n <span class=\"input-group-addon\" id=\"sizing-addon3\"><i class=\"fa fa-search\"></i></span>\n <input type=\"text\" class=\"form-control\" placeholder=\"{{ texts.searchPlaceholder }}\"\n aria-describedby=\"sizing-addon3\" [(ngModel)]=\"searchFilterText\" [ngModelOptions]=\"{standalone: true}\">\n <span class=\"input-group-btn\" *ngIf=\"searchFilterText.length > 0\">\n \t\t\t <button class=\"btn btn-default btn-secondary\" type=\"button\" (click)=\"clearSearch($event)\"><i class=\"fa fa-times\"></i></button>\n\t </span>\n </div>\n </li>\n <li class=\"dropdown-divider divider\" *ngIf=\"settings.enableSearch\"></li>\n <li class=\"dropdown-item check-control check-control-check\" *ngIf=\"settings.showCheckAll\">\n <a href=\"javascript:;\" role=\"menuitem\" tabindex=\"-1\" (click)=\"checkAll()\">\n <span style=\"width: 16px;\"\n [ngClass]=\"{'glyphicon glyphicon-ok': settings.checkedStyle !== 'fontawesome',\n 'fa fa-check': settings.checkedStyle === 'fontawesome'}\"></span>\n {{ texts.checkAll }}\n </a>\n </li>\n <li class=\"dropdown-item check-control check-control-uncheck\" *ngIf=\"settings.showUncheckAll\">\n <a href=\"javascript:;\" role=\"menuitem\" tabindex=\"-1\" (click)=\"uncheckAll()\">\n <span style=\"width: 16px;\"\n [ngClass]=\"{'glyphicon glyphicon-remove': settings.checkedStyle !== 'fontawesome',\n 'fa fa-times': settings.checkedStyle === 'fontawesome'}\"></span>\n {{ texts.uncheckAll }}\n </a>\n </li>\n <li *ngIf=\"settings.showCheckAll || settings.showUncheckAll\" class=\"dropdown-divider divider\"></li>\n <li class=\"dropdown-item\" [ngStyle]=\"getItemStyle(option)\" *ngFor=\"let option of options | searchFilter:searchFilterText\"\n (click)=\"!option.isLabel && setSelected($event, option)\" [class.dropdown-header]=\"option.isLabel\">\n <template [ngIf]=\"option.isLabel\">\n {{ option.name }}\n </template>\n <a *ngIf=\"!option.isLabel\" href=\"javascript:;\" role=\"menuitem\" tabindex=\"-1\">\n <input *ngIf=\"settings.checkedStyle === 'checkboxes'\" type=\"checkbox\"\n [checked]=\"isSelected(option)\" (click)=\"preventCheckboxCheck($event, option)\"/>\n <span *ngIf=\"settings.checkedStyle === 'glyphicon'\" style=\"width: 16px;\"\n class=\"glyphicon\" [class.glyphicon-ok]=\"isSelected(option)\"></span>\n <span *ngIf=\"settings.checkedStyle === 'fontawesome'\" style=\"width: 16px;display: inline-block;\">\n \t\t\t <i *ngIf=\"isSelected(option)\" class=\"fa fa-check\" aria-hidden=\"true\"></i>\n \t\t\t </span>\n <span [ngClass]=\"settings.itemClasses\">\n {{ option.name }}\n </span>\n </a>\n </li>\n </ul>\n </div>\n "
template: "\n <div class=\"dropdown\">\n <button type=\"button\" class=\"dropdown-toggle\" [ngClass]=\"settings.buttonClasses\"\n (click)=\"toggleDropdown()\" [disabled]=\"disabled\">{{ title }}&nbsp;<span class=\"caret\"></span></button>\n <ul *ngIf=\"isVisible\" class=\"dropdown-menu\" [class.pull-right]=\"settings.pullRight\" [class.dropdown-menu-right]=\"settings.pullRight\"\n [style.max-height]=\"settings.maxHeight\" style=\"display: block; height: auto; overflow-y: auto;\">\n <li class=\"dropdown-item search\" *ngIf=\"settings.enableSearch\">\n <div class=\"input-group input-group-sm\">\n <span class=\"input-group-addon\" id=\"sizing-addon3\"><i class=\"fa fa-search\"></i></span>\n <input type=\"text\" class=\"form-control\" placeholder=\"{{ texts.searchPlaceholder }}\"\n aria-describedby=\"sizing-addon3\" [(ngModel)]=\"searchFilterText\" [ngModelOptions]=\"{standalone: true}\">\n <span class=\"input-group-btn\" *ngIf=\"searchFilterText.length > 0\">\n \t\t\t <button class=\"btn btn-default btn-secondary\" type=\"button\" (click)=\"clearSearch($event)\"><i class=\"fa fa-times\"></i></button>\n\t </span>\n </div>\n </li>\n <li class=\"dropdown-divider divider\" *ngIf=\"settings.enableSearch\"></li>\n <li class=\"dropdown-item check-control check-control-check\" *ngIf=\"settings.showCheckAll\">\n <a href=\"javascript:;\" role=\"menuitem\" tabindex=\"-1\" (click)=\"checkAll()\">\n <span style=\"width: 16px;\"\n [ngClass]=\"{'glyphicon glyphicon-ok': settings.checkedStyle !== 'fontawesome',\n 'fa fa-check': settings.checkedStyle === 'fontawesome'}\"></span>\n {{ texts.checkAll }}\n </a>\n </li>\n <li class=\"dropdown-item check-control check-control-uncheck\" *ngIf=\"settings.showUncheckAll\">\n <a href=\"javascript:;\" role=\"menuitem\" tabindex=\"-1\" (click)=\"uncheckAll()\">\n <span style=\"width: 16px;\"\n [ngClass]=\"{'glyphicon glyphicon-remove': settings.checkedStyle !== 'fontawesome',\n 'fa fa-times': settings.checkedStyle === 'fontawesome'}\"></span>\n {{ texts.uncheckAll }}\n </a>\n </li>\n <li *ngIf=\"settings.showCheckAll || settings.showUncheckAll\" class=\"dropdown-divider divider\"></li>\n <li class=\"dropdown-item\" [ngStyle]=\"getItemStyle(option)\" *ngFor=\"let option of options | searchFilter:searchFilterText\"\n (click)=\"!option.isLabel && setSelected($event, option)\" [class.dropdown-header]=\"option.isLabel\">\n <ng-template [ngIf]=\"option.isLabel\">\n {{ option.name }}\n </ng-template>\n <a *ngIf=\"!option.isLabel\" href=\"javascript:;\" role=\"menuitem\" tabindex=\"-1\" [style.padding-left]=\"this.parents.length>0&&this.parents.indexOf(option.id)<0&&'30px'\">\n <input *ngIf=\"settings.checkedStyle === 'checkboxes'\" type=\"checkbox\"\n [checked]=\"isSelected(option)\" (click)=\"preventCheckboxCheck($event, option)\"/>\n <span *ngIf=\"settings.checkedStyle === 'glyphicon'\" style=\"width: 16px;\"\n class=\"glyphicon\" [class.glyphicon-ok]=\"isSelected(option)\"></span>\n <span *ngIf=\"settings.checkedStyle === 'fontawesome'\" style=\"width: 16px;display: inline-block;\">\n \t\t\t <i *ngIf=\"isSelected(option)\" class=\"fa fa-check\" aria-hidden=\"true\"></i>\n \t\t\t </span>\n <span [ngClass]=\"settings.itemClasses\" [style.font-weight]=\"this.parents.indexOf(option.id)>=0?'bold':'normal'\">\n {{ option.name }}\n </span>\n </a>\n </li>\n </ul>\n </div>\n "
}),

@@ -296,0 +344,0 @@ __metadata("design:paramtypes", [core_1.ElementRef,

@@ -127,6 +127,6 @@ /*

(click)="!option.isLabel && setSelected($event, option)" [class.dropdown-header]="option.isLabel">
<template [ngIf]="option.isLabel">
<ng-template [ngIf]="option.isLabel">
{{ option.name }}
</template>
<a *ngIf="!option.isLabel" href="javascript:;" role="menuitem" tabindex="-1">
</ng-template>
<a *ngIf="!option.isLabel" href="javascript:;" role="menuitem" tabindex="-1" [style.padding-left]="this.parents.length>0&&this.parents.indexOf(option.id)<0&&'30px'">
<input *ngIf="settings.checkedStyle === 'checkboxes'" type="checkbox"

@@ -139,3 +139,3 @@ [checked]="isSelected(option)" (click)="preventCheckboxCheck($event, option)"/>

</span>
<span [ngClass]="settings.itemClasses">
<span [ngClass]="settings.itemClasses" [style.font-weight]="this.parents.indexOf(option.id)>=0?'bold':'normal'">
{{ option.name }}

@@ -176,2 +176,3 @@ </span>

model: number[];
parents: number[];
title: string;

@@ -214,3 +215,3 @@ differ: any;

if (!option.isLabel) {
return {'cursor': 'pointer'};
return {'cursor':'pointer'};
}

@@ -223,2 +224,8 @@ }

this.title = this.texts.defaultTitle || '';
this.parents = [];
this.options.forEach(option => {
if(typeof(option.parentId)!=='undefined'&&this.parents.indexOf(option.parentId)<0) {
this.parents.push(option.parentId);
}
});
}

@@ -291,2 +298,11 @@

this.onRemoved.emit(option.id);
const parentIndex = option.parentId && this.model.indexOf(option.parentId);
if (parentIndex >= 0) {
this.model.splice(parentIndex, 1);
this.onRemoved.emit(option.parentId);
} else if (this.parents.indexOf(option.id) > -1) {
let childIds = this.options.filter(child => this.model.indexOf(child.id)>-1 && child.parentId == option.id).map(child => child.id);
this.model = this.model.filter(id => childIds.indexOf(id)<0);
childIds.forEach(childId => this.onRemoved.emit(childId));
}
} else {

@@ -296,2 +312,16 @@ if (this.settings.selectionLimit === 0 || (this.settings.selectionLimit && this.model.length < this.settings.selectionLimit)) {

this.onAdded.emit(option.id);
if (option.parentId) {
let children = this.options.filter(child => child.id !== option.id && child.parentId == option.parentId);
if (children.every(child => this.model.indexOf(child.id) > -1))
{
this.model.push(option.parentId);
this.onAdded.emit(option.parentId);
}
} else if (this.parents.indexOf(option.id)>-1) {
let children = this.options.filter(child => this.model.indexOf(child.id)<0 && child.parentId == option.id);
children.forEach(child => {
this.model.push(child.id);
this.onAdded.emit(child.id);
})
}
} else {

@@ -317,3 +347,3 @@ if (this.settings.autoUnselect) {

updateNumSelected() {
this.numSelected = this.model && this.model.length || 0;
this.numSelected = this.model && this.model.filter(id => this.parents.indexOf(id) < 0).length || 0;
}

@@ -339,11 +369,18 @@

}
searchFilterApplied() {
return this.settings.enableSearch && this.searchFilterText && this.searchFilterText.length > 0;
}
checkAll() {
this.model = this.options
.map((option: IMultiSelectOption) => {
let checkedOptions = (!this.searchFilterApplied() ? this.options :
(new MultiSelectSearchFilter()).transform(this.options, this.searchFilterText))
.filter((option: IMultiSelectOption) => {
if (this.model.indexOf(option.id) === -1) {
this.onAdded.emit(option.id);
return true;
}
return option.id;
});
return false;
}).map((option: IMultiSelectOption) => option.id);
this.model = this.model.concat(checkedOptions);
this.onModelChange(this.model);

@@ -354,4 +391,13 @@ this.onModelTouched();

uncheckAll() {
this.model.forEach((id: number) => this.onRemoved.emit(id));
this.model = [];
let unCheckedOptions = (!this.searchFilterApplied() ? this.model
: (new MultiSelectSearchFilter()).transform(this.options, this.searchFilterText).map((option: IMultiSelectOption) => option.id)
);
this.model = this.model.filter((id: number) => {
if (unCheckedOptions.indexOf(id) < 0) {
return true;
} else {
this.onRemoved.emit(id);
return false;
}
});
this.onModelChange(this.model);

@@ -362,3 +408,3 @@ this.onModelTouched();

preventCheckboxCheck(event: Event, option: IMultiSelectOption) {
if (this.settings.selectionLimit &&
if (this.settings.selectionLimit && !this.settings.autoUnselect &&
this.model.length >= this.settings.selectionLimit &&

@@ -365,0 +411,0 @@ this.model.indexOf(option.id) === -1

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc