angular-2-dropdown-multiselect
Advanced tools
Comparing version 0.4.1 to 1.0.0
{ | ||
"name": "angular-2-dropdown-multiselect", | ||
"version": "0.4.1", | ||
"version": "1.0.0", | ||
"description": "Customizable dropdown multiselect in Angular 2 with bootstrap css.", | ||
@@ -28,8 +28,7 @@ "main": "src/multiselect-dropdown.ts", | ||
"@angular/forms": "^2.4.3", | ||
"rxjs": "^5.0.3", | ||
"zone.js": "^0.7.5", | ||
"codelyzer": "^2.0.0-beta.4", | ||
"tslint": "^4.3.1", | ||
"rxjs": "^5.1.0", | ||
"zone.js": "^0.7.6", | ||
"codelyzer": "^2.0.0", | ||
"typescript": "^2.1.5" | ||
} | ||
} |
@@ -10,4 +10,4 @@ # Angular 2 Dropdown Multiselect for Bootstrap CSS | ||
## Dependencies | ||
* Bootstrap CSS 3 | ||
* Font Awesome *(only with search box and checkbox mode)* | ||
* Bootstrap CSS 3 or 4 | ||
* Font Awesome (optional) | ||
@@ -26,6 +26,4 @@ ## Quick start options | ||
```js | ||
import {MultiselectDropdownModule} from 'angular-2-dropdown-multiselect/src/multiselect-dropdown'; | ||
import { MultiselectDropdownModule } from 'angular-2-dropdown-multiselect'; | ||
// ... | ||
@NgModule({ | ||
@@ -35,4 +33,4 @@ // ... | ||
MultiselectDropdownModule, | ||
// ... | ||
] | ||
// ... | ||
}) | ||
@@ -44,10 +42,15 @@ ``` | ||
```js | ||
import {IMultiSelectOption} from 'angular-2-dropdown-multiselect/src/multiselect-dropdown'; | ||
import { IMultiSelectOption } from 'angular-2-dropdown-multiselect'; | ||
export class MyClass { | ||
private selectedOptions: number[]; | ||
private myOptions: IMultiSelectOption[] = [ | ||
{ id: 1, name: 'Option 1' }, | ||
{ id: 2, name: 'Option 2' }, | ||
]; | ||
export class MyClass implements OnInit { | ||
optionsModel: number[]; | ||
ngOnInit() { | ||
myOptions: IMultiSelectOption[] = [ | ||
{ id: 1, name: 'Option 1' }, | ||
{ id: 2, name: 'Option 2' }, | ||
]; | ||
} | ||
onChange() { | ||
console.log(this.optionsModel); | ||
} | ||
} | ||
@@ -59,3 +62,3 @@ ``` | ||
```html | ||
<ss-multiselect-dropdown [options]="myOptions" [(ngModel)]="selectedOptions" (ngModelChange)="onChange($event)"></ss-multiselect-dropdown> | ||
<ss-multiselect-dropdown [options]="myOptions" [(ngModel)]="optionsModel" (ngModelChange)="onChange($event)"></ss-multiselect-dropdown> | ||
``` | ||
@@ -65,7 +68,7 @@ | ||
Import the IMultiSelectSettings and IMultiSelectTexts interfaces to enable/override settings and text strings: | ||
Import the IMultiSelectOption and IMultiSelectTexts interfaces to enable/override settings and text strings: | ||
```js | ||
private selectedOptions: number[] = [1, 2]; // Default selection | ||
optionsModel: number[] = [1, 2]; // Default selection | ||
private mySettings: IMultiSelectSettings = { | ||
mySettings: IMultiSelectSettings = { | ||
pullRight: false, | ||
@@ -83,3 +86,3 @@ enableSearch: false, | ||
private myTexts: IMultiSelectTexts = { | ||
myTexts: IMultiSelectTexts = { | ||
checkAll: 'Check all', | ||
@@ -92,8 +95,48 @@ uncheckAll: 'Uncheck all', | ||
}; | ||
/* Labels */ | ||
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 } | ||
]; | ||
``` | ||
```html | ||
<ss-multiselect-dropdown [options]="mySettings" [texts]="myTexts" [settings]="mySettings" [(ngModel)]="selectedOptions"></ss-multiselect-dropdown> | ||
<ss-multiselect-dropdown [options]="myOptions" [texts]="myTexts" [settings]="mySettings" [(ngModel)]="optionsModel"></ss-multiselect-dropdown> | ||
``` | ||
## Use model driven forms with ReactiveFormsModule: | ||
```js | ||
import { IMultiSelectOption } from 'angular-2-dropdown-multiselect'; | ||
export class MyClass implements OnInit { | ||
model: number[]; | ||
myOptions: IMultiSelectOption[] = [ | ||
{ id: 1, name: 'Option 1' }, | ||
{ id: 2, name: 'Option 2' }, | ||
]; | ||
ngOnInit() { | ||
this.myForm = this.formBuilder.group({ | ||
optionsModel: [1, 2], // Default model | ||
}); | ||
this.myForm.controls['optionsModel'].valueChanges | ||
.subscribe((selectedOptions) => { | ||
// changes | ||
}); | ||
} | ||
} | ||
``` | ||
```html | ||
<form [formGroup]="myForm"> | ||
<ss-multiselect-dropdown [options]="myOptions" formControlName="optionsModel"></ss-multiselect-dropdown> | ||
</form> | ||
``` | ||
## Developing | ||
@@ -100,0 +143,0 @@ |
@@ -17,2 +17,3 @@ /* | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var core_1 = require("@angular/core"); | ||
@@ -30,6 +31,7 @@ var common_1 = require("@angular/common"); | ||
MultiSelectSearchFilter.prototype.transform = function (options, args) { | ||
var matchPredicate = function (option) { return option.name.toLowerCase().indexOf((args || '').toLowerCase()) > -1; }, getChildren = function (option) { return options.filter(function (child) { return child.parentId === option.id; }); }, getParent = function (option) { return options.find(function (parent) { return option.parentId === parent.id; }); }; | ||
return options.filter(function (option) { | ||
return option.name | ||
.toLowerCase() | ||
.indexOf((args || '').toLowerCase()) > -1; | ||
return matchPredicate(option) || | ||
(typeof (option.parentId) === 'undefined' && getChildren(option).some(matchPredicate)) || | ||
(typeof (option.parentId) !== 'undefined' && matchPredicate(getParent(option))); | ||
}); | ||
@@ -48,5 +50,6 @@ }; | ||
this.element = element; | ||
this.differs = differs; | ||
this.selectionLimitReached = new core_1.EventEmitter(); | ||
this.dropdownClosed = new core_1.EventEmitter(); | ||
this.onAdded = new core_1.EventEmitter(); | ||
this.onRemoved = new core_1.EventEmitter(); | ||
this.numSelected = 0; | ||
@@ -75,2 +78,3 @@ this.isVisible = false; | ||
defaultTitle: 'Select', | ||
allSelected: 'All selected', | ||
}; | ||
@@ -91,2 +95,3 @@ this.onModelChange = function (_) { }; | ||
this.isVisible = false; | ||
this.dropdownClosed.emit(); | ||
} | ||
@@ -97,3 +102,3 @@ }; | ||
this.texts = Object.assign(this.defaultTexts, this.texts); | ||
this.title = this.texts.defaultTitle; | ||
this.title = this.texts.defaultTitle || ''; | ||
}; | ||
@@ -118,3 +123,4 @@ MultiselectDropdown.prototype.writeValue = function (value) { | ||
}; | ||
MultiselectDropdown.prototype.clearSearch = function () { | ||
MultiselectDropdown.prototype.clearSearch = function (event) { | ||
event.stopPropagation(); | ||
this.searchFilterText = ''; | ||
@@ -138,6 +144,8 @@ }; | ||
this.model.splice(index, 1); | ||
this.onRemoved.emit(option.id); | ||
} | ||
else { | ||
if (this.settings.selectionLimit === 0 || this.model.length < this.settings.selectionLimit) { | ||
if (this.settings.selectionLimit === 0 || (this.settings.selectionLimit && this.model.length < this.settings.selectionLimit)) { | ||
this.model.push(option.id); | ||
this.onAdded.emit(option.id); | ||
} | ||
@@ -147,3 +155,5 @@ else { | ||
this.model.push(option.id); | ||
this.model.shift(); | ||
this.onAdded.emit(option.id); | ||
var removedOption = this.model.shift(); | ||
this.onRemoved.emit(removedOption); | ||
} | ||
@@ -167,5 +177,5 @@ else { | ||
if (this.numSelected === 0) { | ||
this.title = this.texts.defaultTitle; | ||
this.title = this.texts.defaultTitle || ''; | ||
} | ||
else if (this.settings.dynamicTitleMaxItems >= this.numSelected) { | ||
else if (this.settings.dynamicTitleMaxItems && this.settings.dynamicTitleMaxItems >= this.numSelected) { | ||
this.title = this.options | ||
@@ -178,2 +188,5 @@ .filter(function (option) { | ||
} | ||
else if (this.settings.displayAllSelectedText && this.model.length === this.options.length) { | ||
this.title = this.texts.allSelected || ''; | ||
} | ||
else { | ||
@@ -186,9 +199,25 @@ this.title = this.numSelected | ||
MultiselectDropdown.prototype.checkAll = function () { | ||
this.model = this.options.map(function (option) { return option.id; }); | ||
var _this = this; | ||
this.model = this.options | ||
.map(function (option) { | ||
if (_this.model.indexOf(option.id) === -1) { | ||
_this.onAdded.emit(option.id); | ||
} | ||
return option.id; | ||
}); | ||
this.onModelChange(this.model); | ||
}; | ||
MultiselectDropdown.prototype.uncheckAll = function () { | ||
var _this = this; | ||
this.model.forEach(function (id) { return _this.onRemoved.emit(id); }); | ||
this.model = []; | ||
this.onModelChange(this.model); | ||
}; | ||
MultiselectDropdown.prototype.preventCheckboxCheck = function (event, option) { | ||
if (this.settings.selectionLimit && | ||
this.model.length >= this.settings.selectionLimit && | ||
this.model.indexOf(option.id) === -1) { | ||
event.preventDefault(); | ||
} | ||
}; | ||
return MultiselectDropdown; | ||
@@ -217,2 +246,10 @@ }()); | ||
__decorate([ | ||
core_1.Output(), | ||
__metadata("design:type", Object) | ||
], MultiselectDropdown.prototype, "onAdded", void 0); | ||
__decorate([ | ||
core_1.Output(), | ||
__metadata("design:type", Object) | ||
], MultiselectDropdown.prototype, "onRemoved", void 0); | ||
__decorate([ | ||
core_1.HostListener('document: click', ['$event.target']), | ||
@@ -228,5 +265,6 @@ __metadata("design:type", Function), | ||
styles: ["\n\t a { outline: none !important; }\n "], | ||
template: "\n\t<div class=\"dropdown\">\n\t <button type=\"button\" class=\"dropdown-toggle\" [ngClass]=\"settings.buttonClasses\"\n\t (click)=\"toggleDropdown()\">{{ title }} <span class=\"caret\"></span></button>\n\t <ul *ngIf=\"isVisible\" class=\"dropdown-menu\" [class.pull-right]=\"settings.pullRight\" [class.dropdown-menu-right]=\"settings.pullRight\"\n\t [style.max-height]=\"settings.maxHeight\" style=\"display: block; height: auto; overflow-y: auto;\">\n\t\t<li class=\"dropdown-item\" *ngIf=\"settings.enableSearch\">\n\t\t <div class=\"input-group input-group-sm\">\n\t\t\t<span class=\"input-group-addon\" id=\"sizing-addon3\"><i class=\"fa fa-search\"></i></span>\n\t\t\t<input type=\"text\" class=\"form-control\" placeholder=\"{{ texts.searchPlaceholder }}\"\n\t\t\taria-describedby=\"sizing-addon3\" [(ngModel)]=\"searchFilterText\">\n\t\t\t<span class=\"input-group-btn\" *ngIf=\"searchFilterText.length > 0\">\n\t\t\t <button class=\"btn btn-default\" type=\"button\" (click)=\"clearSearch()\"><i class=\"fa fa-times\"></i></button>\n\t\t\t</span>\n\t\t </div>\n\t\t</li>\n\t\t<li class=\"dropdown-divider divider\" *ngIf=\"settings.enableSearch\"></li>\n\t\t<li class=\"dropdown-item\" *ngIf=\"settings.showCheckAll\">\n\t\t <a href=\"javascript:;\" role=\"menuitem\" tabindex=\"-1\" (click)=\"checkAll()\">\n\t\t\t<span style=\"width: 16px;\" class=\"glyphicon glyphicon-ok\"></span>\n\t\t\t{{ texts.checkAll }}\n\t\t </a>\n\t\t</li>\n\t\t<li class=\"dropdown-item\" *ngIf=\"settings.showUncheckAll\">\n\t\t <a href=\"javascript:;\" role=\"menuitem\" tabindex=\"-1\" (click)=\"uncheckAll()\">\n\t\t\t<span style=\"width: 16px;\" class=\"glyphicon glyphicon-remove\"></span>\n\t\t\t{{ texts.uncheckAll }}\n\t\t </a>\n\t\t</li>\n\t\t<li *ngIf=\"settings.showCheckAll || settings.showUncheckAll\" class=\"dropdown-divider divider\"></li>\n\t\t<li class=\"dropdown-item\" style=\"cursor: pointer;\" *ngFor=\"let option of options | searchFilter:searchFilterText\" (click)=\"setSelected($event, option)\">\n\t\t <a href=\"javascript:;\" role=\"menuitem\" tabindex=\"-1\">\n\t\t\t<input *ngIf=\"settings.checkedStyle === 'checkboxes'\" type=\"checkbox\" [checked]=\"isSelected(option)\" />\n\t\t\t<span *ngIf=\"settings.checkedStyle === 'glyphicon'\" style=\"width: 16px;\"\n\t\t\tclass=\"glyphicon\" [class.glyphicon-ok]=\"isSelected(option)\"></span>\n\t\t\t<span *ngIf=\"settings.checkedStyle === 'fontawsome'\" 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\t\t\t{{ option.name }}\n\t\t </a>\n\t\t</li>\n\t </ul>\n\t</div>\n" | ||
template: "\n\t<div class=\"dropdown\">\n\t <button type=\"button\" class=\"dropdown-toggle\" [ngClass]=\"settings.buttonClasses\"\n\t (click)=\"toggleDropdown()\">{{ title }} <span class=\"caret\"></span></button>\n <ul *ngIf=\"isVisible\" class=\"dropdown-menu\" [class.pull-right]=\"settings.pullRight\" [class.dropdown-menu-right]=\"settings.pullRight\"\n \t [style.max-height]=\"settings.maxHeight\" style=\"display: block; height: auto; overflow-y: auto;\">\n \t\t<li class=\"dropdown-item\" *ngIf=\"settings.enableSearch\">\n \t\t <div class=\"input-group input-group-sm\">\n \t\t\t<span class=\"input-group-addon\" id=\"sizing-addon3\"><i class=\"fa fa-search\"></i></span>\n \t\t\t<input type=\"text\" class=\"form-control\" placeholder=\"{{ texts.searchPlaceholder }}\"\n \t\t\taria-describedby=\"sizing-addon3\" [(ngModel)]=\"searchFilterText\">\n \t\t\t<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\t\t</span>\n \t\t </div>\n \t\t</li>\n \t\t<li class=\"dropdown-divider divider\" *ngIf=\"settings.enableSearch\"></li>\n \t\t<li class=\"dropdown-item\" *ngIf=\"settings.showCheckAll\">\n \t\t <a href=\"javascript:;\" role=\"menuitem\" tabindex=\"-1\" (click)=\"checkAll()\">\n \t\t\t<span style=\"width: 16px;\" class=\"glyphicon glyphicon-ok\"></span>\n \t\t\t{{ texts.checkAll }}\n \t\t </a>\n \t\t</li>\n \t\t<li class=\"dropdown-item\" *ngIf=\"settings.showUncheckAll\">\n \t\t <a href=\"javascript:;\" role=\"menuitem\" tabindex=\"-1\" (click)=\"uncheckAll()\">\n \t\t\t<span style=\"width: 16px;\" class=\"glyphicon glyphicon-remove\"></span>\n \t\t\t{{ texts.uncheckAll }}\n \t\t </a>\n \t\t</li>\n \t\t<li *ngIf=\"settings.showCheckAll || settings.showUncheckAll\" class=\"dropdown-divider divider\"></li>\n \t\t<li class=\"dropdown-item\" [style]=\"!option.isLabel && 'cursor: pointer'\" *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 \t\t <a *ngIf=\"!option.isLabel\" href=\"javascript:;\" role=\"menuitem\" tabindex=\"-1\">\n \t\t\t <input *ngIf=\"settings.checkedStyle === 'checkboxes'\" type=\"checkbox\" [checked]=\"isSelected(option)\" (click)=\"preventCheckboxCheck($event, option)\" />\n \t\t\t <span *ngIf=\"settings.checkedStyle === 'glyphicon'\" style=\"width: 16px;\"\n \t\t\t 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 \t {{ option.name }}\n \t\t </a>\n \t </li>\n </ul>\n\t</div>\n" | ||
}), | ||
__metadata("design:paramtypes", [typeof (_a = typeof core_1.ElementRef !== "undefined" && core_1.ElementRef) === "function" && _a || Object, typeof (_b = typeof core_1.IterableDiffers !== "undefined" && core_1.IterableDiffers) === "function" && _b || Object]) | ||
__metadata("design:paramtypes", [core_1.ElementRef, | ||
core_1.IterableDiffers]) | ||
], MultiselectDropdown); | ||
@@ -247,3 +285,2 @@ exports.MultiselectDropdown = MultiselectDropdown; | ||
exports.MultiselectDropdownModule = MultiselectDropdownModule; | ||
var _a, _b; | ||
//# sourceMappingURL=multiselect-dropdown.js.map |
@@ -20,3 +20,4 @@ /* | ||
forwardRef, | ||
IterableDiffers | ||
IterableDiffers, | ||
PipeTransform | ||
} from '@angular/core'; | ||
@@ -35,2 +36,4 @@ import { CommonModule } from '@angular/common'; | ||
name: string; | ||
isLabel?: boolean; | ||
parentId?: any; | ||
} | ||
@@ -41,3 +44,3 @@ | ||
enableSearch?: boolean; | ||
checkedStyle?: 'checkboxes' | 'glyphicon' | 'fontawsome'; | ||
checkedStyle?: 'checkboxes' | 'glyphicon' | 'fontawesome'; | ||
buttonClasses?: string; | ||
@@ -51,2 +54,3 @@ selectionLimit?: number; | ||
maxHeight?: string; | ||
displayAllSelectedText?: boolean; | ||
} | ||
@@ -61,2 +65,3 @@ | ||
defaultTitle?: string; | ||
allSelected?: string; | ||
} | ||
@@ -67,8 +72,12 @@ | ||
}) | ||
export class MultiSelectSearchFilter { | ||
export class MultiSelectSearchFilter implements PipeTransform { | ||
transform(options: Array<IMultiSelectOption>, args: string): Array<IMultiSelectOption> { | ||
return options.filter((option: IMultiSelectOption) => | ||
option.name | ||
.toLowerCase() | ||
.indexOf((args || '').toLowerCase()) > -1); | ||
const matchPredicate = (option: IMultiSelectOption) => option.name.toLowerCase().indexOf((args || '').toLowerCase()) > -1, | ||
getChildren = (option: IMultiSelectOption) => options.filter(child => child.parentId === option.id), | ||
getParent = (option: IMultiSelectOption) => options.find(parent => option.parentId === parent.id); | ||
return options.filter((option: IMultiSelectOption) => { | ||
return matchPredicate(option) || | ||
(typeof(option.parentId) === 'undefined' && getChildren(option).some(matchPredicate)) || | ||
(typeof(option.parentId) !== 'undefined' && matchPredicate(getParent(option))); | ||
}); | ||
} | ||
@@ -87,40 +96,44 @@ } | ||
(click)="toggleDropdown()">{{ title }} <span class="caret"></span></button> | ||
<ul *ngIf="isVisible" class="dropdown-menu" [class.pull-right]="settings.pullRight" [class.dropdown-menu-right]="settings.pullRight" | ||
[style.max-height]="settings.maxHeight" style="display: block; height: auto; overflow-y: auto;"> | ||
<li class="dropdown-item" *ngIf="settings.enableSearch"> | ||
<div class="input-group input-group-sm"> | ||
<span class="input-group-addon" id="sizing-addon3"><i class="fa fa-search"></i></span> | ||
<input type="text" class="form-control" placeholder="{{ texts.searchPlaceholder }}" | ||
aria-describedby="sizing-addon3" [(ngModel)]="searchFilterText"> | ||
<span class="input-group-btn" *ngIf="searchFilterText.length > 0"> | ||
<button class="btn btn-default" type="button" (click)="clearSearch()"><i class="fa fa-times"></i></button> | ||
</span> | ||
</div> | ||
</li> | ||
<li class="dropdown-divider divider" *ngIf="settings.enableSearch"></li> | ||
<li class="dropdown-item" *ngIf="settings.showCheckAll"> | ||
<a href="javascript:;" role="menuitem" tabindex="-1" (click)="checkAll()"> | ||
<span style="width: 16px;" class="glyphicon glyphicon-ok"></span> | ||
{{ texts.checkAll }} | ||
</a> | ||
</li> | ||
<li class="dropdown-item" *ngIf="settings.showUncheckAll"> | ||
<a href="javascript:;" role="menuitem" tabindex="-1" (click)="uncheckAll()"> | ||
<span style="width: 16px;" class="glyphicon glyphicon-remove"></span> | ||
{{ texts.uncheckAll }} | ||
</a> | ||
</li> | ||
<li *ngIf="settings.showCheckAll || settings.showUncheckAll" class="dropdown-divider divider"></li> | ||
<li class="dropdown-item" style="cursor: pointer;" *ngFor="let option of options | searchFilter:searchFilterText" (click)="setSelected($event, option)"> | ||
<a href="javascript:;" role="menuitem" tabindex="-1"> | ||
<input *ngIf="settings.checkedStyle === 'checkboxes'" type="checkbox" [checked]="isSelected(option)" /> | ||
<span *ngIf="settings.checkedStyle === 'glyphicon'" style="width: 16px;" | ||
class="glyphicon" [class.glyphicon-ok]="isSelected(option)"></span> | ||
<span *ngIf="settings.checkedStyle === 'fontawsome'" style="width: 16px;display: inline-block;"> | ||
<i *ngIf="isSelected(option)" class="fa fa-check" aria-hidden="true"></i> | ||
</span> | ||
{{ option.name }} | ||
</a> | ||
</li> | ||
</ul> | ||
<ul *ngIf="isVisible" class="dropdown-menu" [class.pull-right]="settings.pullRight" [class.dropdown-menu-right]="settings.pullRight" | ||
[style.max-height]="settings.maxHeight" style="display: block; height: auto; overflow-y: auto;"> | ||
<li class="dropdown-item" *ngIf="settings.enableSearch"> | ||
<div class="input-group input-group-sm"> | ||
<span class="input-group-addon" id="sizing-addon3"><i class="fa fa-search"></i></span> | ||
<input type="text" class="form-control" placeholder="{{ texts.searchPlaceholder }}" | ||
aria-describedby="sizing-addon3" [(ngModel)]="searchFilterText"> | ||
<span class="input-group-btn" *ngIf="searchFilterText.length > 0"> | ||
<button class="btn btn-default btn-secondary" type="button" (click)="clearSearch($event)"><i class="fa fa-times"></i></button> | ||
</span> | ||
</div> | ||
</li> | ||
<li class="dropdown-divider divider" *ngIf="settings.enableSearch"></li> | ||
<li class="dropdown-item" *ngIf="settings.showCheckAll"> | ||
<a href="javascript:;" role="menuitem" tabindex="-1" (click)="checkAll()"> | ||
<span style="width: 16px;" class="glyphicon glyphicon-ok"></span> | ||
{{ texts.checkAll }} | ||
</a> | ||
</li> | ||
<li class="dropdown-item" *ngIf="settings.showUncheckAll"> | ||
<a href="javascript:;" role="menuitem" tabindex="-1" (click)="uncheckAll()"> | ||
<span style="width: 16px;" class="glyphicon glyphicon-remove"></span> | ||
{{ texts.uncheckAll }} | ||
</a> | ||
</li> | ||
<li *ngIf="settings.showCheckAll || settings.showUncheckAll" class="dropdown-divider divider"></li> | ||
<li class="dropdown-item" [style]="!option.isLabel && 'cursor: pointer'" *ngFor="let option of options | searchFilter:searchFilterText" | ||
(click)="!option.isLabel && setSelected($event, option)" [class.dropdown-header]="option.isLabel"> | ||
<ng-template [ngIf]="option.isLabel"> | ||
{{ option.name }} | ||
</ng-template> | ||
<a *ngIf="!option.isLabel" href="javascript:;" role="menuitem" tabindex="-1"> | ||
<input *ngIf="settings.checkedStyle === 'checkboxes'" type="checkbox" [checked]="isSelected(option)" (click)="preventCheckboxCheck($event, option)" /> | ||
<span *ngIf="settings.checkedStyle === 'glyphicon'" style="width: 16px;" | ||
class="glyphicon" [class.glyphicon-ok]="isSelected(option)"></span> | ||
<span *ngIf="settings.checkedStyle === 'fontawesome'" style="width: 16px;display: inline-block;"> | ||
<i *ngIf="isSelected(option)" class="fa fa-check" aria-hidden="true"></i> | ||
</span> | ||
{{ option.name }} | ||
</a> | ||
</li> | ||
</ul> | ||
</div> | ||
@@ -136,2 +149,4 @@ ` | ||
@Output() dropdownClosed = new EventEmitter(); | ||
@Output() onAdded = new EventEmitter(); | ||
@Output() onRemoved = new EventEmitter(); | ||
@@ -149,2 +164,3 @@ @HostListener('document: click', ['$event.target']) | ||
this.isVisible = false; | ||
this.dropdownClosed.emit(); | ||
} | ||
@@ -179,6 +195,7 @@ } | ||
defaultTitle: 'Select', | ||
allSelected: 'All selected', | ||
}; | ||
constructor(private element: ElementRef, | ||
private differs: IterableDiffers) { | ||
differs: IterableDiffers) { | ||
this.differ = differs.find([]).create(null); | ||
@@ -190,3 +207,3 @@ } | ||
this.texts = Object.assign(this.defaultTexts, this.texts); | ||
this.title = this.texts.defaultTitle; | ||
this.title = this.texts.defaultTitle || ''; | ||
} | ||
@@ -197,3 +214,2 @@ | ||
writeValue(value: any): void { | ||
@@ -214,3 +230,3 @@ if (value !== undefined) { | ||
ngDoCheck() { | ||
let changes = this.differ.diff(this.model); | ||
const changes = this.differ.diff(this.model); | ||
if (changes) { | ||
@@ -222,3 +238,4 @@ this.updateNumSelected(); | ||
clearSearch() { | ||
clearSearch(event: Event) { | ||
event.stopPropagation(); | ||
this.searchFilterText = ''; | ||
@@ -242,12 +259,16 @@ } | ||
} | ||
let index = this.model.indexOf(option.id); | ||
const index = this.model.indexOf(option.id); | ||
if (index > -1) { | ||
this.model.splice(index, 1); | ||
this.onRemoved.emit(option.id); | ||
} else { | ||
if (this.settings.selectionLimit === 0 || this.model.length < this.settings.selectionLimit) { | ||
if (this.settings.selectionLimit === 0 || (this.settings.selectionLimit && this.model.length < this.settings.selectionLimit)) { | ||
this.model.push(option.id); | ||
this.onAdded.emit(option.id); | ||
} else { | ||
if (this.settings.autoUnselect) { | ||
this.model.push(option.id); | ||
this.model.shift(); | ||
this.onAdded.emit(option.id); | ||
const removedOption = this.model.shift(); | ||
this.onRemoved.emit(removedOption); | ||
} else { | ||
@@ -271,4 +292,4 @@ this.selectionLimitReached.emit(this.model.length); | ||
if (this.numSelected === 0) { | ||
this.title = this.texts.defaultTitle; | ||
} else if (this.settings.dynamicTitleMaxItems >= this.numSelected) { | ||
this.title = this.texts.defaultTitle || ''; | ||
} else if (this.settings.dynamicTitleMaxItems && this.settings.dynamicTitleMaxItems >= this.numSelected) { | ||
this.title = this.options | ||
@@ -280,2 +301,4 @@ .filter((option: IMultiSelectOption) => | ||
.join(', '); | ||
} else if (this.settings.displayAllSelectedText && this.model.length === this.options.length) { | ||
this.title = this.texts.allSelected || ''; | ||
} else { | ||
@@ -289,3 +312,9 @@ this.title = this.numSelected | ||
checkAll() { | ||
this.model = this.options.map(option => option.id); | ||
this.model = this.options | ||
.map((option: IMultiSelectOption) => { | ||
if (this.model.indexOf(option.id) === -1) { | ||
this.onAdded.emit(option.id); | ||
} | ||
return option.id; | ||
}); | ||
this.onModelChange(this.model); | ||
@@ -295,5 +324,15 @@ } | ||
uncheckAll() { | ||
this.model.forEach((id: number) => this.onRemoved.emit(id)); | ||
this.model = []; | ||
this.onModelChange(this.model); | ||
} | ||
preventCheckboxCheck(event: Event, option: IMultiSelectOption) { | ||
if (this.settings.selectionLimit && | ||
this.model.length >= this.settings.selectionLimit && | ||
this.model.indexOf(option.id) === -1 | ||
) { | ||
event.preventDefault(); | ||
} | ||
} | ||
} | ||
@@ -300,0 +339,0 @@ |
Sorry, the diff of this file is not supported yet
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
39202
8
1
141
609