Skip to content

Commit 9537681

Browse files
authored
Merge pull request #132 from chris--jones/feature/select_all_when_filtered
Feature/select all when filtered
2 parents e420bfc + 14a567f commit 9537681

File tree

1 file changed

+59
-13
lines changed

1 file changed

+59
-13
lines changed

src/multiselect-dropdown.ts

Lines changed: 59 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -124,18 +124,18 @@ export class MultiSelectSearchFilter implements PipeTransform {
124124
<li *ngIf="settings.showCheckAll || settings.showUncheckAll" class="dropdown-divider divider"></li>
125125
<li class="dropdown-item" [ngStyle]="getItemStyle(option)" *ngFor="let option of options | searchFilter:searchFilterText"
126126
(click)="!option.isLabel && setSelected($event, option)" [class.dropdown-header]="option.isLabel">
127-
<template [ngIf]="option.isLabel">
127+
<ng-template [ngIf]="option.isLabel">
128128
{{ option.name }}
129-
</template>
130-
<a *ngIf="!option.isLabel" href="javascript:;" role="menuitem" tabindex="-1">
129+
</ng-template>
130+
<a *ngIf="!option.isLabel" href="javascript:;" role="menuitem" tabindex="-1" [style.padding-left]="this.parents.length>0&&this.parents.indexOf(option.id)<0&&'30px'">
131131
<input *ngIf="settings.checkedStyle === 'checkboxes'" type="checkbox"
132132
[checked]="isSelected(option)" (click)="preventCheckboxCheck($event, option)"/>
133133
<span *ngIf="settings.checkedStyle === 'glyphicon'" style="width: 16px;"
134134
class="glyphicon" [class.glyphicon-ok]="isSelected(option)"></span>
135135
<span *ngIf="settings.checkedStyle === 'fontawesome'" style="width: 16px;display: inline-block;">
136136
<i *ngIf="isSelected(option)" class="fa fa-check" aria-hidden="true"></i>
137137
</span>
138-
<span [ngClass]="settings.itemClasses">
138+
<span [ngClass]="settings.itemClasses" [style.font-weight]="this.parents.indexOf(option.id)>=0?'bold':'normal'">
139139
{{ option.name }}
140140
</span>
141141
</a>
@@ -171,6 +171,7 @@ export class MultiselectDropdown implements OnInit, DoCheck, ControlValueAccesso
171171
}
172172

173173
model: number[];
174+
parents: number[];
174175
title: string;
175176
differ: any;
176177
numSelected: number = 0;
@@ -208,14 +209,20 @@ export class MultiselectDropdown implements OnInit, DoCheck, ControlValueAccesso
208209

209210
getItemStyle(option: IMultiSelectOption): any {
210211
if (!option.isLabel) {
211-
return {'cursor': 'pointer'};
212+
return {'cursor':'pointer'};
212213
}
213214
}
214215

215216
ngOnInit() {
216217
this.settings = Object.assign(this.defaultSettings, this.settings);
217218
this.texts = Object.assign(this.defaultTexts, this.texts);
218219
this.title = this.texts.defaultTitle || '';
220+
this.parents = [];
221+
this.options.forEach(option => {
222+
if(typeof(option.parentId)!=='undefined'&&this.parents.indexOf(option.parentId)<0) {
223+
this.parents.push(option.parentId);
224+
}
225+
});
219226
}
220227

221228
onModelChange: Function = (_: any) => {};
@@ -283,10 +290,33 @@ export class MultiselectDropdown implements OnInit, DoCheck, ControlValueAccesso
283290
if (index > -1) {
284291
this.model.splice(index, 1);
285292
this.onRemoved.emit(option.id);
293+
const parentIndex = option.parentId && this.model.indexOf(option.parentId);
294+
if (parentIndex >= 0) {
295+
this.model.splice(parentIndex, 1);
296+
this.onRemoved.emit(option.parentId);
297+
} else if (this.parents.indexOf(option.id) > -1) {
298+
let childIds = this.options.filter(child => this.model.indexOf(child.id)>-1 && child.parentId == option.id).map(child => child.id);
299+
this.model = this.model.filter(id => childIds.indexOf(id)<0);
300+
childIds.forEach(childId => this.onRemoved.emit(childId));
301+
}
286302
} else {
287303
if (this.settings.selectionLimit === 0 || (this.settings.selectionLimit && this.model.length < this.settings.selectionLimit)) {
288304
this.model.push(option.id);
289305
this.onAdded.emit(option.id);
306+
if (option.parentId) {
307+
let children = this.options.filter(child => child.id !== option.id && child.parentId == option.parentId);
308+
if (children.every(child => this.model.indexOf(child.id) > -1))
309+
{
310+
this.model.push(option.parentId);
311+
this.onAdded.emit(option.parentId);
312+
}
313+
} else if (this.parents.indexOf(option.id)>-1) {
314+
let children = this.options.filter(child => this.model.indexOf(child.id)<0 && child.parentId == option.id);
315+
children.forEach(child => {
316+
this.model.push(child.id);
317+
this.onAdded.emit(child.id);
318+
})
319+
}
290320
} else {
291321
if (this.settings.autoUnselect) {
292322
this.model.push(option.id);
@@ -307,7 +337,7 @@ export class MultiselectDropdown implements OnInit, DoCheck, ControlValueAccesso
307337
}
308338

309339
updateNumSelected() {
310-
this.numSelected = this.model && this.model.length || 0;
340+
this.numSelected = this.model && this.model.filter(id => this.parents.indexOf(id) < 0).length || 0;
311341
}
312342

313343
updateTitle() {
@@ -328,28 +358,44 @@ export class MultiselectDropdown implements OnInit, DoCheck, ControlValueAccesso
328358
+ (this.numSelected === 1 ? this.texts.checked : this.texts.checkedPlural);
329359
}
330360
}
361+
362+
searchFilterApplied() {
363+
return this.settings.enableSearch && this.searchFilterText && this.searchFilterText.length > 0;
364+
}
331365

332366
checkAll() {
333-
this.model = this.options
334-
.map((option: IMultiSelectOption) => {
367+
let checkedOptions = (!this.searchFilterApplied() ? this.options :
368+
(new MultiSelectSearchFilter()).transform(this.options, this.searchFilterText))
369+
.filter((option: IMultiSelectOption) => {
335370
if (this.model.indexOf(option.id) === -1) {
336371
this.onAdded.emit(option.id);
372+
return true;
337373
}
338-
return option.id;
339-
});
374+
return false;
375+
}).map((option: IMultiSelectOption) => option.id);
376+
this.model = this.model.concat(checkedOptions);
340377
this.onModelChange(this.model);
341378
this.onModelTouched();
342379
}
343380

344381
uncheckAll() {
345-
this.model.forEach((id: number) => this.onRemoved.emit(id));
346-
this.model = [];
382+
let unCheckedOptions = (!this.searchFilterApplied() ? this.model
383+
: (new MultiSelectSearchFilter()).transform(this.options, this.searchFilterText).map((option: IMultiSelectOption) => option.id)
384+
);
385+
this.model = this.model.filter((id: number) => {
386+
if (unCheckedOptions.indexOf(id) < 0) {
387+
return true;
388+
} else {
389+
this.onRemoved.emit(id);
390+
return false;
391+
}
392+
});
347393
this.onModelChange(this.model);
348394
this.onModelTouched();
349395
}
350396

351397
preventCheckboxCheck(event: Event, option: IMultiSelectOption) {
352-
if (this.settings.selectionLimit &&
398+
if (this.settings.selectionLimit && !this.settings.autoUnselect &&
353399
this.model.length >= this.settings.selectionLimit &&
354400
this.model.indexOf(option.id) === -1
355401
) {

0 commit comments

Comments
 (0)