Skip to content

Commit 07558b2

Browse files
authored
Merge pull request #12770 from IgniteUI/mpopov/chip-discrepancy
Chip - fix discrepancy between WebC and Angular
2 parents 1ba8854 + eff7e09 commit 07558b2

20 files changed

+1221
-741
lines changed

CHANGELOG.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,10 @@ import { IgxGridModule } from 'igniteui-angular';
5151
imports: [IgxGridModule, AsyncPipe]
5252
})
5353
```
54-
54+
- `IgxChip`
55+
- **Behavioral Change** The `igxChip` styles have been revisited and the select container animaton has been removed when selecting/deselecting a chip.
56+
- **Behavioral Change** The remove button behavior have been revisited, now when the chip is in `disabled` state the remove button is hidden.
57+
- The `igxChip` have new input `variant` which can take any of the following values: `'primary'`, `'info'`, `'success'`, `'warning'`, `'danger'`
5558
### New Features
5659
- `IgxExpansionPanel`:
5760
- `IgxExpansionPanelTitleDirective` and `IgxExpansionPanelDescriptionDirective` show tooltip of the provided text content.

projects/igniteui-angular/src/lib/chips/chip.component.html

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,27 +14,31 @@
1414
(over)="onChipOverHandler($event)"
1515
(dropped)="onChipDrop($event)">
1616

17-
<div #selectContainer [ngClass]="selectClass(selected)">
18-
<ng-container *ngTemplateOutlet="selectIconTemplate"></ng-container>
19-
</div>
17+
<div class="igx-chip__start" #selectContainer>
18+
<div *ngIf="selected" [ngClass]="selectClass(selected)">
19+
<ng-container *ngTemplateOutlet="selectIconTemplate"></ng-container>
20+
</div>
2021

21-
<ng-content select="igx-prefix,[igxPrefix]"></ng-content>
22+
<ng-content select="igx-prefix,[igxPrefix]"></ng-content>
23+
</div>
2224

2325
<div class="igx-chip__content">
2426
<ng-content></ng-content>
2527
</div>
2628

27-
<ng-content select="igx-suffix,[igxSuffix]"></ng-content>
29+
<div class="igx-chip__end">
30+
<ng-content select="igx-suffix,[igxSuffix]"></ng-content>
2831

29-
<div class="igx-chip__remove" *ngIf="removable"
30-
[attr.tabIndex]="tabIndex"
31-
(keydown)="onRemoveBtnKeyDown($event)"
32-
(pointerdown)="onRemoveMouseDown($event)"
33-
(mousedown)="onRemoveMouseDown($event)"
34-
(click)="onRemoveClick($event)"
35-
(touchmove)="onRemoveTouchMove()"
36-
(touchend)="onRemoveTouchEnd($event)">
37-
<ng-container *ngTemplateOutlet="removeButtonTemplate"></ng-container>
32+
<div class="igx-chip__remove" *ngIf="removable"
33+
[attr.tabIndex]="tabIndex"
34+
(keydown)="onRemoveBtnKeyDown($event)"
35+
(pointerdown)="onRemoveMouseDown($event)"
36+
(mousedown)="onRemoveMouseDown($event)"
37+
(click)="onRemoveClick($event)"
38+
(touchmove)="onRemoveTouchMove()"
39+
(touchend)="onRemoveTouchEnd($event)">
40+
<ng-container *ngTemplateOutlet="removeButtonTemplate"></ng-container>
41+
</div>
3842
</div>
3943
</div>
4044

projects/igniteui-angular/src/lib/chips/chip.component.ts

Lines changed: 83 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {
1+
import {
22
Component,
33
ChangeDetectorRef,
44
EventEmitter,
@@ -16,14 +16,21 @@
1616
} from '@angular/core';
1717
import { IDisplayDensityOptions, DisplayDensityToken, DisplayDensityBase } from '../core/density';
1818
import { IgxDragDirective, IDragBaseEventArgs, IDragStartEventArgs, IDropBaseEventArgs, IDropDroppedEventArgs, IgxDropDirective } from '../directives/drag-drop/drag-drop.directive';
19-
import { IBaseEventArgs } from '../core/utils';
19+
import { IBaseEventArgs, mkenum } from '../core/utils';
2020
import { IChipResourceStrings } from '../core/i18n/chip-resources';
2121
import { CurrentResourceStrings } from '../core/i18n/resources';
22-
import { fromEvent, Subject } from 'rxjs';
23-
import { take, filter } from 'rxjs/operators';
22+
import { Subject } from 'rxjs';
2423
import { IgxIconComponent } from '../icon/icon.component';
2524
import { NgClass, NgTemplateOutlet, NgIf } from '@angular/common';
2625

26+
export const IgxChipTypeVariant = mkenum({
27+
PRIMARY: 'primary',
28+
INFO: 'info',
29+
SUCCESS: 'success',
30+
WARNING: 'warning',
31+
DANGER: 'danger'
32+
});
33+
2734
export interface IBaseChipEventArgs extends IBaseEventArgs {
2835
originalEvent: IDragBaseEventArgs | IDropBaseEventArgs | KeyboardEvent | MouseEvent | TouchEvent;
2936
owner: IgxChipComponent;
@@ -79,6 +86,21 @@ let CHIP_ID = 0;
7986
imports: [IgxDropDirective, IgxDragDirective, NgClass, NgTemplateOutlet, NgIf, IgxIconComponent]
8087
})
8188
export class IgxChipComponent extends DisplayDensityBase implements OnDestroy {
89+
90+
/**
91+
* Sets/gets the variant of the chip.
92+
*
93+
* @remarks
94+
* Allowed values are `primary`, `info`, `success`, `warning`, `danger`.
95+
* Providing an invalid value won't change the chip.
96+
*
97+
* @example
98+
* ```html
99+
* <igx-chip [variant]="success"></igx-chip>
100+
* ```
101+
*/
102+
@Input()
103+
public variant: string | typeof IgxChipTypeVariant;
82104
/**
83105
* An @Input property that sets the value of `id` attribute. If not provided it will be automatically generated.
84106
*
@@ -218,6 +240,13 @@ export class IgxChipComponent extends DisplayDensityBase implements OnDestroy {
218240
@Input()
219241
public selectIcon: TemplateRef<any>;
220242

243+
/**
244+
* @hidden
245+
* @internal
246+
*/
247+
@Input()
248+
public class = '';
249+
221250
/**
222251
* An @Input property that defines if the `IgxChipComponent` is disabled. When disabled it restricts user interactions
223252
* like focusing on click or tab, selection on click or Space, dragging.
@@ -228,6 +257,7 @@ export class IgxChipComponent extends DisplayDensityBase implements OnDestroy {
228257
* <igx-chip [id]="chip.id" [disabled]="true"></igx-chip>
229258
* ```
230259
*/
260+
@HostBinding('class.igx-chip--disabled')
231261
@Input()
232262
public disabled = false;
233263

@@ -456,6 +486,44 @@ export class IgxChipComponent extends DisplayDensityBase implements OnDestroy {
456486
@Output()
457487
public dragDrop = new EventEmitter<IChipEnterDragAreaEventArgs>();
458488

489+
@HostBinding('class.igx-chip')
490+
protected defaultClass = 'igx-chip';
491+
492+
@HostBinding('class.igx-chip--primary')
493+
protected get isPrimary() {
494+
return this.variant === IgxChipTypeVariant.PRIMARY;
495+
}
496+
497+
@HostBinding('class.igx-chip--info')
498+
protected get isInfo() {
499+
return this.variant === IgxChipTypeVariant.INFO;
500+
}
501+
502+
@HostBinding('class.igx-chip--success')
503+
protected get isSuccess() {
504+
return this.variant === IgxChipTypeVariant.SUCCESS;
505+
}
506+
507+
@HostBinding('class.igx-chip--warning')
508+
protected get isWarning() {
509+
return this.variant === IgxChipTypeVariant.WARNING;
510+
}
511+
512+
@HostBinding('class.igx-chip--danger')
513+
protected get isDanger() {
514+
return this.variant === IgxChipTypeVariant.DANGER;
515+
}
516+
517+
@HostBinding('class.igx-chip--cosy')
518+
protected get isCosy() {
519+
return this.displayDensity === 'cosy';
520+
}
521+
522+
@HostBinding('class.igx-chip--compact')
523+
protected get isCompact() {
524+
return this.displayDensity === 'compact';
525+
}
526+
459527
/**
460528
* Property that contains a reference to the `IgxDragDirective` the `IgxChipComponent` uses for dragging behavior.
461529
*
@@ -479,13 +547,6 @@ export class IgxChipComponent extends DisplayDensityBase implements OnDestroy {
479547
@ViewChild('chipArea', { read: ElementRef, static: true })
480548
public chipArea: ElementRef;
481549

482-
/**
483-
* @hidden
484-
* @internal
485-
*/
486-
@ViewChild('selectContainer', { read: ElementRef, static: true })
487-
public selectContainer: ElementRef;
488-
489550
/**
490551
* @hidden
491552
* @internal
@@ -505,7 +566,9 @@ export class IgxChipComponent extends DisplayDensityBase implements OnDestroy {
505566
* @internal
506567
*/
507568
public get removeButtonTemplate() {
508-
return this.removeIcon || this.defaultRemoveIcon;
569+
if(!this.disabled) {
570+
return this.removeIcon || this.defaultRemoveIcon;
571+
}
509572
}
510573

511574
/**
@@ -552,20 +615,6 @@ export class IgxChipComponent extends DisplayDensityBase implements OnDestroy {
552615
super(_displayDensityOptions);
553616
}
554617

555-
@HostBinding('class')
556-
private get hostClass(): string {
557-
const classes = [this.getComponentDensityClass('igx-chip')];
558-
559-
// Add the base class first for each density
560-
if (!classes.includes('igx-chip')) {
561-
classes.unshift('igx-chip');
562-
}
563-
564-
classes.push(this.disabled ? 'igx-chip--disabled' : '');
565-
566-
return classes.join(' ').toString().trim();
567-
}
568-
569618
/**
570619
* @hidden
571620
* @internal
@@ -836,10 +885,6 @@ export class IgxChipComponent extends DisplayDensityBase implements OnDestroy {
836885
cancel: false
837886
};
838887

839-
fromEvent(this.selectContainer.nativeElement, 'transitionend')
840-
.pipe(filter<TransitionEvent>(event => event.propertyName === 'width'), take(1))
841-
.subscribe(event => this.onSelectTransitionDone(event));
842-
843888
if (newValue && !this._selected) {
844889
onSelectArgs.selected = true;
845890
this.selectedChanging.emit(onSelectArgs);
@@ -848,6 +893,10 @@ export class IgxChipComponent extends DisplayDensityBase implements OnDestroy {
848893
this.renderer.addClass(this.chipArea.nativeElement, this._selectedItemClass);
849894
this._selected = newValue;
850895
this.selectedChange.emit(this._selected);
896+
this.selectedChanged.emit({
897+
owner: this,
898+
originalEvent: srcEvent
899+
});
851900
}
852901
} else if (!newValue && this._selected) {
853902
this.selectedChanging.emit(onSelectArgs);
@@ -856,6 +905,10 @@ export class IgxChipComponent extends DisplayDensityBase implements OnDestroy {
856905
this.renderer.removeClass(this.chipArea.nativeElement, this._selectedItemClass);
857906
this._selected = newValue;
858907
this.selectedChange.emit(this._selected);
908+
this.selectedChanged.emit({
909+
owner: this,
910+
originalEvent: srcEvent
911+
});
859912
}
860913
}
861914
}

projects/igniteui-angular/src/lib/chips/chip.spec.ts

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -128,24 +128,33 @@ describe('IgxChip', () => {
128128
});
129129

130130
it('should render prefix element inside the chip before the content', () => {
131-
const chipElems = fix.debugElement.queryAll(By.directive(IgxChipComponent));
131+
const igxChip = fix.debugElement.queryAll(By.directive(IgxChipComponent));
132+
const igxChipItem = igxChip[1].nativeElement;
132133

133-
// For this first chip there are 2 elements. The prefix and content span.
134-
expect(chipElems[0].nativeElement.children[0].children.length).toEqual(3);
135-
expect(chipElems[0].nativeElement.children[0].children[0].offsetWidth).toEqual(0);
136-
expect(chipElems[0].nativeElement.children[0].children[1].tagName).toEqual('IGX-ICON');
137-
expect(chipElems[0].nativeElement.children[0].children[1].hasAttribute('igxprefix')).toEqual(true);
134+
expect(igxChipItem.children[0].children[0].children[0].hasAttribute('igxprefix')).toEqual(true);
138135
});
139136

140137
it('should render remove button when enabled after the content inside the chip', () => {
141-
const chipElems = fix.debugElement.queryAll(By.directive(IgxChipComponent));
142-
const chipRemoveButton = ControlsFunction.getChipRemoveButton(chipElems[1].nativeElement);
138+
const igxChip = fix.debugElement.queryAll(By.directive(IgxChipComponent));
139+
const igxChipItem = igxChip[1].nativeElement;
140+
const chipRemoveButton = ControlsFunction.getChipRemoveButton(igxChipItem);
143141

144-
// For this second chip there are 3 elements. The prefix, content span and the remove button icon .
145-
expect(chipElems[1].nativeElement.children[0].children.length).toEqual(4);
142+
expect(igxChipItem.children[0].children[2].children[0]).toHaveClass('igx-chip__remove');
146143
expect(chipRemoveButton).toBeTruthy();
147144
});
148145

146+
it('should change chip variant', () => {
147+
const fixture = TestBed.createComponent(IgxChipComponent);
148+
const igxChip = fixture.componentInstance;
149+
150+
igxChip.variant = 'danger';
151+
152+
fixture.detectChanges();
153+
154+
expect(igxChip.variant).toMatch('danger');
155+
expect(igxChip.nativeElement).toHaveClass('igx-chip--danger');
156+
});
157+
149158
it('should set text in chips correctly', () => {
150159
const chipElements = chipArea[0].queryAll(By.directive(IgxChipComponent));
151160
const firstChipTextElement = chipElements[0].queryAllNodes(By.css(`.${CHIP_TEXT_CLASS}`));
@@ -351,7 +360,7 @@ describe('IgxChip', () => {
351360
UIInteractions.triggerKeyDownEvtUponElem(' ', secondChipComp.chipArea.nativeElement, true);
352361
fix.detectChanges();
353362
expect(secondChipComp.selectedChanging.emit).toHaveBeenCalled();
354-
expect(secondChipComp.selectedChanged.emit).not.toHaveBeenCalled();
363+
expect(secondChipComp.selectedChanged.emit).toHaveBeenCalled();
355364
expect(secondChipComp.selectedChanging.emit).not.toHaveBeenCalledWith({
356365
originalEvent: null,
357366
owner: secondChipComp,

projects/igniteui-angular/src/lib/chips/chips-area.spec.ts

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,6 @@ describe('IgxChipsArea ', () => {
105105
configureTestSuite();
106106
const CHIP_REMOVE_BUTTON = 'igx-chip__remove';
107107
const CHIP_SELECT_ICON = 'igx-chip__select';
108-
const CHIP_SELECT_ICON_HIDDEN = 'igx-chip__select--hidden';
109108
const CHIP_AREA_CLASS = 'igx-chip-area';
110109

111110
let fix;
@@ -325,22 +324,14 @@ describe('IgxChipsArea ', () => {
325324
fix = TestBed.createComponent(TestChipComponent);
326325
fix.detectChanges();
327326

328-
const selectedChip = fix.componentInstance.chipsArea.chipsList.toArray()[0];
329-
const unselectedChip = fix.componentInstance.chipsArea.chipsList.toArray()[1];
330-
selectedChip.selected = true;
327+
const igxChip = fix.componentInstance.chipsArea.chipsList.toArray()[0];
328+
const igxChipItem = igxChip.nativeElement.children[0]; // Return igx-chip__item
329+
330+
igxChip.selected = true;
331331
fix.detectChanges();
332332

333-
const selectedChipIconContainer = selectedChip.nativeElement.children[0].children[0];
334-
const unselectedChipIconContainer = unselectedChip.nativeElement.children[0].children[0];
335-
expect(selectedChip.selected).toBe(true);
336-
expect(selectedChipIconContainer.children.length).toEqual(1);
337-
expect(selectedChipIconContainer.children[0].tagName).toEqual('IGX-ICON');
338-
// expect(selectedChip.elementRef.nativeElement.children[0].children[0].offsetWidth).not.toEqual(0);
339-
expect(selectedChip.nativeElement.children[0].children[0].className).toEqual(CHIP_SELECT_ICON);
340-
expect(selectedChip.nativeElement.children[0].children[0].className).not.toEqual(CHIP_SELECT_ICON_HIDDEN);
341-
expect(unselectedChipIconContainer.children.length).toEqual(1);
342-
expect(unselectedChipIconContainer.children[0].tagName).toEqual('IGX-ICON');
343-
expect(unselectedChip.nativeElement.children[0].children[0].offsetWidth).toEqual(0);
333+
expect(igxChip.selected).toBe(true);
334+
expect(igxChipItem).toHaveClass(`igx-chip__item--selected`);
344335
});
345336

346337
it('should fire only onSelection event for chip area when selecting a chip using spacebar', () => {

0 commit comments

Comments
 (0)