Skip to content

Commit 9ebc54b

Browse files
committed
refactor(button): input signals
1 parent 995a0bf commit 9ebc54b

File tree

6 files changed

+76
-71
lines changed

6 files changed

+76
-71
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,36 @@
1-
import { Component, HostBinding, Input } from '@angular/core';
1+
import { booleanAttribute, Component, computed, input, InputSignal, InputSignalWithTransform } from '@angular/core';
22

33
@Component({
44
selector: 'c-button-group',
55
template: '<ng-content />',
6-
standalone: true
6+
standalone: true,
7+
host: { '[attr.role]': 'role()', '[class]': 'hostClasses()' }
78
})
89
export class ButtonGroupComponent {
9-
1010
/**
1111
* Size the component small or large.
1212
* @type { 'sm' | 'lg' }
1313
*/
14-
@Input() size?: 'sm' | 'lg';
14+
size: InputSignal<'sm' | 'lg' | undefined> = input();
15+
1516
/**
1617
* Create a set of buttons that appear vertically stacked rather than horizontally. Split button dropdowns are not supported here.
1718
* @type boolean
1819
*/
19-
@Input() vertical?: boolean;
20+
vertical: InputSignalWithTransform<boolean, unknown> = input(false, { transform: booleanAttribute });
21+
2022
/**
2123
* Default role attr for ButtonGroup. [docs]
22-
* @type string
24+
* @type InputSignal<string>
2325
* @default 'group'
2426
*/
25-
@HostBinding('attr.role')
26-
@Input() role = 'group';
27+
role: InputSignal<string> = input('group');
2728

28-
@HostBinding('class')
29-
get hostClasses(): any {
29+
hostClasses = computed(() => {
3030
return {
31-
'btn-group': !this.vertical,
32-
'btn-group-vertical': this.vertical,
33-
[`btn-group-${this.size}`]: !!this.size
31+
'btn-group': !this.vertical(),
32+
'btn-group-vertical': this.vertical(),
33+
[`btn-group-${this.size()}`]: !!this.size()
3434
};
35-
}
36-
35+
});
3736
}
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,16 @@
1-
import { Component, HostBinding, Input } from '@angular/core';
1+
import { Component, input, InputSignal } from '@angular/core';
22

33
@Component({
44
selector: 'c-button-toolbar',
55
template: '<ng-content />',
66
standalone: true,
7-
host: { class: 'btn-toolbar' }
7+
host: { class: 'btn-toolbar', '[attr.role]': 'role()' }
88
})
99
export class ButtonToolbarComponent {
1010
/**
1111
* Default role attr for ButtonToolbar. [docs]
12-
* @type string
12+
* @type InputSignal<string>
1313
* @default 'toolbar'
1414
*/
15-
@HostBinding('attr.role')
16-
@Input()
17-
role = 'toolbar';
15+
role: InputSignal<string> = input('toolbar');
1816
}

projects/coreui-angular/src/lib/button/button-close.directive.spec.ts

+4-3
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ class MockElementRef extends ElementRef {}
1313
class TestComponent {}
1414

1515
describe('ButtonCloseDirective', () => {
16-
1716
let component: TestComponent;
1817
let fixture: ComponentFixture<TestComponent>;
1918
let elementRef: DebugElement;
@@ -32,8 +31,10 @@ describe('ButtonCloseDirective', () => {
3231
});
3332

3433
it('should create an instance', () => {
35-
const directive = new ButtonCloseDirective();
36-
expect(directive).toBeTruthy();
34+
TestBed.runInInjectionContext(() => {
35+
const directive = new ButtonCloseDirective();
36+
expect(directive).toBeTruthy();
37+
});
3738
});
3839

3940
it('should have css classes', () => {
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,29 @@
1-
import { booleanAttribute, Directive, HostBinding, Input } from '@angular/core';
1+
import { booleanAttribute, computed, Directive, input, InputSignalWithTransform } from '@angular/core';
22
import { ThemeDirective } from '../shared/theme.directive';
33
import { ButtonDirective } from './button.directive';
44

55
@Directive({
66
selector: '[cButtonClose]',
77
standalone: true,
88
hostDirectives: [{ directive: ThemeDirective, inputs: ['dark'] }],
9-
host: { class: 'btn btn-close' }
9+
host: { class: 'btn btn-close', '[class]': 'hostClasses()', '[attr.type]': 'type()' }
1010
})
1111
export class ButtonCloseDirective extends ButtonDirective {
1212
/**
1313
* Change the default color to white.
1414
* @type boolean
1515
* @deprecated 5.0.0. Use `cButtonClose.dark` instead.
1616
*/
17-
@Input({ transform: booleanAttribute }) white: string | boolean = false;
17+
white: InputSignalWithTransform<boolean, unknown> = input(false, { transform: booleanAttribute });
1818

19-
@HostBinding('class')
20-
override get hostClasses(): any {
19+
override hostClasses = computed(() => {
2120
return {
2221
btn: true,
2322
'btn-close': true,
24-
'btn-close-white': this.white,
25-
[`btn-${this.size}`]: !!this.size,
26-
disabled: this.disabled,
27-
active: this.active
28-
};
29-
}
23+
'btn-close-white': this.white(),
24+
[`btn-${this.size()}`]: !!this.size(),
25+
disabled: this.disabled(),
26+
active: this.active()
27+
} as Record<string, boolean>;
28+
});
3029
}

projects/coreui-angular/src/lib/button/button.directive.spec.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ class MockElementRef extends ElementRef {}
1313
class TestComponent {}
1414

1515
describe('ButtonDirective', () => {
16-
1716
let component: TestComponent;
1817
let fixture: ComponentFixture<TestComponent>;
1918
let elementRef: DebugElement;
@@ -32,14 +31,15 @@ describe('ButtonDirective', () => {
3231
});
3332

3433
it('should create an instance', () => {
35-
const directive = new ButtonDirective();
36-
expect(directive).toBeTruthy();
34+
TestBed.runInInjectionContext(() => {
35+
const directive = new ButtonDirective();
36+
expect(directive).toBeTruthy();
37+
});
3738
});
3839

3940
it('should have css classes', () => {
4041
expect(elementRef.nativeElement).toHaveClass('btn');
4142
expect(elementRef.nativeElement).toHaveClass('btn-lg');
4243
expect(elementRef.nativeElement).toHaveClass('btn-info');
4344
});
44-
4545
});
Original file line numberDiff line numberDiff line change
@@ -1,88 +1,96 @@
1-
import { booleanAttribute, Directive, HostBinding, Input } from '@angular/core';
1+
import {
2+
booleanAttribute,
3+
computed,
4+
Directive,
5+
HostBinding,
6+
input,
7+
InputSignal,
8+
InputSignalWithTransform
9+
} from '@angular/core';
210

311
import { ButtonType, Colors, Shapes } from '../coreui.types';
412

513
@Directive({
614
selector: '[cButton]',
715
exportAs: 'cButton',
816
standalone: true,
9-
host: { class: 'btn' }
17+
host: { class: 'btn', '[class]': 'hostClasses()', '[attr.type]': 'type()' }
1018
})
1119
export class ButtonDirective {
1220
/**
1321
* Toggle the active state for the component. [docs]
14-
* @type boolean
22+
* @type InputSignalWithTransform<boolean, unknown>
1523
*/
16-
@Input({ transform: booleanAttribute }) active: string | boolean = false;
24+
active: InputSignalWithTransform<boolean, unknown> = input(false, { transform: booleanAttribute });
1725

1826
/**
1927
* Sets the color context of the component to one of CoreUI’s themed colors. [docs]
20-
* @type Colors
28+
* @type InputSignal<Colors>
2129
*/
22-
@Input() color?: Colors = 'primary';
30+
color: InputSignal<Colors> = input<Colors>('primary');
31+
2332
/**
2433
* Toggle the disabled state for the component.
25-
* @type boolean
34+
* @type InputSignalWithTransform<boolean, unknown>
2635
*/
27-
@Input({ transform: booleanAttribute }) disabled: string | boolean = false;
36+
disabled: InputSignalWithTransform<boolean, unknown> = input(false, { transform: booleanAttribute });
2837

2938
/**
3039
* Select the shape of the component.
31-
* @type { 'rounded' | 'rounded-top' | 'rounded-end' | 'rounded-bottom' | 'rounded-start' | 'rounded-circle' | 'rounded-pill' | 'rounded-0' | 'rounded-1' | 'rounded-2' | 'rounded-3' | string }
40+
* @type InputSignal<Shapes>
3241
*/
33-
@Input() shape?: Shapes;
42+
shape: InputSignal<Shapes | undefined> = input<Shapes>();
3443

3544
/**
3645
* Size the component small or large.
37-
* @type {'sm' | 'lg'}
46+
* @type InputSignal<'sm' | 'lg' | ''>
3847
*/
39-
@Input() size?: 'sm' | 'lg' | '' = '';
48+
size: InputSignal<'' | 'sm' | 'lg'> = input<'' | 'sm' | 'lg'>('');
4049

4150
/**
4251
* Specifies the type of button. Always specify the type attribute for the `<button>` element.
4352
* Different browsers may use different default types for the `<button>` element.
53+
* @type InputSignal<ButtonType>
54+
* @default 'button'
4455
*/
45-
@HostBinding('attr.type')
46-
@Input()
47-
type: ButtonType = 'button';
56+
type: InputSignal<ButtonType> = input<ButtonType>('button');
4857

4958
/**
5059
* Set the button variant to an outlined button or a ghost button.
51-
* @type {'ghost' | 'outline'}
60+
* @type InputSignal<'ghost' | 'outline' | undefined>
5261
*/
53-
@Input() variant?: 'ghost' | 'outline';
62+
variant: InputSignal<'ghost' | 'outline' | undefined> = input<'ghost' | 'outline'>();
5463

55-
@HostBinding('class')
56-
get hostClasses(): any {
64+
hostClasses = computed(() => {
5765
return {
5866
btn: true,
59-
[`btn-${this.color}`]: !!this.color && !this.variant,
60-
[`btn-${this.variant}`]: !!this.variant && !this.color,
61-
[`btn-${this.variant}-${this.color}`]: !!this.variant && !!this.color,
62-
[`btn-${this.size}`]: !!this.size,
63-
[`${this.shape}`]: !!this.shape,
64-
disabled: this.disabled,
65-
active: this.active
66-
};
67-
}
67+
[`btn-${this.color()}`]: !!this.color() && !this.variant(),
68+
[`btn-${this.variant()}`]: !!this.variant() && !this.color(),
69+
[`btn-${this.variant()}-${this.color()}`]: !!this.variant() && !!this.color(),
70+
[`btn-${this.size()}`]: !!this.size(),
71+
[`${this.shape()}`]: !!this.shape(),
72+
disabled: this.disabled(),
73+
active: this.active()
74+
} as Record<string, boolean>;
75+
});
6876

6977
@HostBinding('attr.aria-disabled')
7078
get ariaDisabled() {
71-
return this.disabled || null;
79+
return this.disabled() || null;
7280
}
7381

7482
@HostBinding('attr.aria-pressed')
7583
get isActive(): boolean | null {
76-
return <boolean>this.active || null;
84+
return <boolean>this.active() || null;
7785
}
7886

7987
@HostBinding('attr.disabled')
8088
get attrDisabled() {
81-
return this.disabled ? '' : null;
89+
return this.disabled() ? '' : null;
8290
}
8391

8492
@HostBinding('attr.tabindex')
8593
get tabIndex(): string | null {
86-
return this.disabled ? '-1' : null;
94+
return this.disabled() ? '-1' : null;
8795
}
8896
}

0 commit comments

Comments
 (0)