@@ -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