Skip to content

Commit 544be48

Browse files
simeonoffgedinakovakdinev
authored
refactor(button): emit selected event (#9315)
* refactor(button): emit selected event * refactor(button-group): update button state on selection Co-authored-by: Galina Edinakova <[email protected]> Co-authored-by: Konstantin Dinev <[email protected]>
1 parent d860375 commit 544be48

File tree

4 files changed

+215
-60
lines changed

4 files changed

+215
-60
lines changed

projects/igniteui-angular/src/lib/buttonGroup/buttonGroup.component.ts

+43-29
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ export const ButtonGroupAlignment = mkenum({
3333
horizontal: 'horizontal',
3434
vertical: 'vertical'
3535
});
36-
export type ButtonGroupAlignment = (typeof ButtonGroupAlignment)[keyof typeof ButtonGroupAlignment];
36+
export type ButtonGroupAlignment = typeof ButtonGroupAlignment[keyof typeof ButtonGroupAlignment];
3737

3838
let NEXT_ID = 0;
3939

@@ -61,7 +61,6 @@ let NEXT_ID = 0;
6161
selector: 'igx-buttongroup',
6262
templateUrl: 'buttongroup-content.component.html'
6363
})
64-
6564
export class IgxButtonGroupComponent extends DisplayDensityBase implements AfterContentInit, AfterViewInit, OnDestroy {
6665
/**
6766
* A collection containing all buttons inside the button group.
@@ -123,6 +122,7 @@ export class IgxButtonGroupComponent extends DisplayDensityBase implements After
123122
* ```
124123
*/
125124
@Input() public multiSelection = false;
125+
126126
/**
127127
* An @Input property that allows setting the buttons in the button group.
128128
* ```typescript
@@ -150,6 +150,7 @@ export class IgxButtonGroupComponent extends DisplayDensityBase implements After
150150
* ```
151151
*/
152152
@Input() public values: any;
153+
153154
/**
154155
* An @Input property that allows you to disable the `igx-buttongroup` component. By default it's false.
155156
* ```html
@@ -165,7 +166,7 @@ export class IgxButtonGroupComponent extends DisplayDensityBase implements After
165166
this._disabled = value;
166167

167168
if (this.viewButtons && this.templateButtons) {
168-
this.buttons.forEach((b) => b.disabled = this._disabled);
169+
this.buttons.forEach((b) => (b.disabled = this._disabled));
169170
}
170171
}
171172
}
@@ -238,7 +239,6 @@ export class IgxButtonGroupComponent extends DisplayDensityBase implements After
238239
@ViewChildren(IgxButtonDirective) private viewButtons: QueryList<IgxButtonDirective>;
239240
@ContentChildren(IgxButtonDirective) private templateButtons: QueryList<IgxButtonDirective>;
240241

241-
242242
/**
243243
* Returns true if the `igx-buttongroup` alignment is vertical.
244244
* Note that in order for the accessor to work correctly the property should be set explicitly.
@@ -264,14 +264,18 @@ export class IgxButtonGroupComponent extends DisplayDensityBase implements After
264264
public selectedIndexes: number[] = [];
265265

266266
protected buttonClickNotifier$ = new Subject<boolean>();
267+
protected buttonSelectedNotifier$ = new Subject<boolean>();
267268
protected queryListNotifier$ = new Subject<boolean>();
268269

269270
private _isVertical: boolean;
270271
private _itemContentCssClass: string;
271272
private _disabled = false;
272273

273-
constructor(private _cdr: ChangeDetectorRef, private _renderer: Renderer2,
274-
@Optional() @Inject(DisplayDensityToken) protected _displayDensityOptions: IDisplayDensityOptions) {
274+
constructor(
275+
private _cdr: ChangeDetectorRef,
276+
private _renderer: Renderer2,
277+
@Optional() @Inject(DisplayDensityToken) protected _displayDensityOptions: IDisplayDensityOptions
278+
) {
275279
super(_displayDensityOptions);
276280
}
277281

@@ -308,15 +312,23 @@ export class IgxButtonGroupComponent extends DisplayDensityBase implements After
308312
}
309313

310314
const button = this.buttons[index];
311-
const buttonElement = button.nativeElement;
315+
button.select();
316+
}
312317

313-
this.selectedIndexes.push(index);
314-
button.selected = true;
318+
/**
319+
* @hidden
320+
* @internal
321+
*/
322+
public updateSelected(index: number) {
323+
const button = this.buttons[index];
315324

316-
this._renderer.setAttribute(buttonElement, 'aria-pressed', 'true');
317-
this._renderer.addClass(buttonElement, 'igx-button-group__item--selected');
325+
if(this.selectedIndexes.indexOf(index) === -1) {
326+
this.selectedIndexes.push(index);
327+
this.selected.emit({ button, index });
328+
}
318329

319-
this.selected.emit({ button, index });
330+
this._renderer.setAttribute(button.nativeElement, 'aria-pressed', 'true');
331+
this._renderer.addClass(button.nativeElement, 'igx-button-group__item--selected');
320332

321333
const indexInViewButtons = this.viewButtons.toArray().indexOf(button);
322334
if (indexInViewButtons !== -1) {
@@ -352,20 +364,18 @@ export class IgxButtonGroupComponent extends DisplayDensityBase implements After
352364
}
353365

354366
const button = this.buttons[index];
355-
const buttonElement = button.nativeElement;
356-
357367
this.selectedIndexes.splice(this.selectedIndexes.indexOf(index), 1);
358-
button.selected = false;
359-
360-
this._renderer.setAttribute(buttonElement, 'aria-pressed', 'false');
361-
this._renderer.removeClass(buttonElement, 'igx-button-group__item--selected');
362368

363-
this.deselected.emit({ button, index });
369+
this._renderer.setAttribute(button.nativeElement, 'aria-pressed', 'false');
370+
this._renderer.removeClass(button.nativeElement, 'igx-button-group__item--selected');
371+
button.deselect();
364372

365373
const indexInViewButtons = this.viewButtons.toArray().indexOf(button);
366374
if (indexInViewButtons !== -1) {
367375
this.values[indexInViewButtons].selected = false;
368376
}
377+
378+
this.deselected.emit({ button, index });
369379
}
370380

371381
/**
@@ -392,17 +402,20 @@ export class IgxButtonGroupComponent extends DisplayDensityBase implements After
392402
// initial configuration
393403
this.buttons.forEach((button, index) => {
394404
const buttonElement = button.nativeElement;
405+
this._renderer.addClass(buttonElement, 'igx-button-group__item');
395406

396407
if (this.disabled) {
397408
button.disabled = true;
398409
}
399410

400411
if (button.selected) {
401-
this.selectButton(index);
412+
this.updateSelected(index);
402413
}
403414

404-
button.buttonClick.pipe(takeUntil(this.buttonClickNotifier$)).subscribe((ev) => this._clickHandler(ev, index));
405-
this._renderer.addClass(buttonElement, 'igx-button-group__item');
415+
button.buttonClick.pipe(takeUntil(this.buttonClickNotifier$)).subscribe((_) => this._clickHandler(index));
416+
button.buttonSelected
417+
.pipe(takeUntil(this.buttonSelectedNotifier$))
418+
.subscribe((_) => this.updateSelected(index));
406419
});
407420
};
408421

@@ -420,18 +433,21 @@ export class IgxButtonGroupComponent extends DisplayDensityBase implements After
420433
this.buttonClickNotifier$.next();
421434
this.buttonClickNotifier$.complete();
422435

436+
this.buttonSelectedNotifier$.next();
437+
this.buttonSelectedNotifier$.complete();
438+
423439
this.queryListNotifier$.next();
424440
this.queryListNotifier$.complete();
425441
}
426442

427443
/**
428444
* @hidden
429445
*/
430-
public _clickHandler(_: MouseEvent, i: number) {
431-
if (this.selectedIndexes.indexOf(i) !== -1) {
432-
this.deselectButton(i);
433-
} else {
446+
public _clickHandler(i: number) {
447+
if (this.selectedIndexes.indexOf(i) === -1) {
434448
this.selectButton(i);
449+
} else {
450+
this.deselectButton(i);
435451
}
436452
}
437453
}
@@ -449,6 +465,4 @@ export interface IButtonGroupEventArgs extends IBaseEventArgs {
449465
exports: [IgxButtonGroupComponent],
450466
imports: [IgxButtonModule, CommonModule, IgxRippleModule, IgxIconModule]
451467
})
452-
453-
export class IgxButtonGroupModule {
454-
}
468+
export class IgxButtonGroupModule {}

projects/igniteui-angular/src/lib/directives/button/button.directive.ts

+59-12
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
} from '@angular/core';
1414
import { DisplayDensityBase, DisplayDensityToken, IDisplayDensityOptions, DisplayDensity } from '../../core/density';
1515
import { mkenum } from '../../core/utils';
16+
import { IBaseEventArgs } from '../../core/utils';
1617

1718
const IgxButtonType = mkenum({
1819
Flat: 'flat',
@@ -53,22 +54,16 @@ export class IgxButtonDirective extends DisplayDensityBase {
5354
private static ngAcceptInputType_type: IgxButtonType | '';
5455

5556
/**
56-
* Gets or sets whether the button is selected.
57-
* Mainly used in the IgxButtonGroup component and it will have no effect if set separately.
58-
*
59-
* @example
60-
* ```html
61-
* <button igxButton="flat" [selected]="button.selected"></button>
62-
* ```
57+
* Called when the button is clicked.
6358
*/
64-
@Input()
65-
public selected = false;
59+
@Output()
60+
public buttonClick = new EventEmitter<any>();
6661

6762
/**
68-
* Called when the button is clicked.
63+
* Called when the button is selected.
6964
*/
7065
@Output()
71-
public buttonClick = new EventEmitter<any>();
66+
public buttonSelected = new EventEmitter<IButtonEventArgs>();
7267

7368
/**
7469
* Sets/gets the `role` attribute.
@@ -119,6 +114,38 @@ export class IgxButtonDirective extends DisplayDensityBase {
119114
*/
120115
private _backgroundColor: string;
121116

117+
/**
118+
* @hidden
119+
* @internal
120+
*/
121+
private _selected = false;
122+
123+
/**
124+
* Gets or sets whether the button is selected.
125+
* Mainly used in the IgxButtonGroup component and it will have no effect if set separately.
126+
*
127+
* @example
128+
* ```html
129+
* <button igxButton="flat" [selected]="button.selected"></button>
130+
* ```
131+
*/
132+
@Input()
133+
public set selected(value: boolean) {
134+
if(this._selected !== value) {
135+
if(!this._selected) {
136+
this.buttonSelected.emit({
137+
button: this
138+
});
139+
}
140+
141+
this._selected = value;
142+
}
143+
}
144+
145+
public get selected(): boolean {
146+
return this._selected;
147+
}
148+
122149
constructor(
123150
public element: ElementRef,
124151
private _renderer: Renderer2,
@@ -192,7 +219,7 @@ export class IgxButtonDirective extends DisplayDensityBase {
192219
*
193220
* @example
194221
* ```html
195-
* <button igxButton= "flat" igxLabel="Label"></button>
222+
* <button igxButton="flat" igxLabel="Label"></button>
196223
* ```
197224
*/
198225
@Input('igxLabel')
@@ -298,6 +325,26 @@ export class IgxButtonDirective extends DisplayDensityBase {
298325
public get disabledAttribute() {
299326
return this._disabled ? this._disabled : null;
300327
}
328+
329+
/**
330+
* @hidden
331+
* @internal
332+
*/
333+
public select() {
334+
this.selected = true;
335+
}
336+
337+
/**
338+
* @hidden
339+
* @internal
340+
*/
341+
public deselect() {
342+
this._selected = false;
343+
}
344+
}
345+
346+
export interface IButtonEventArgs extends IBaseEventArgs {
347+
button: IgxButtonDirective;
301348
}
302349

303350
/**

0 commit comments

Comments
 (0)