Skip to content

Commit 30e289b

Browse files
committed
refactor(widgets): input signals, host bindings
1 parent 864ba6b commit 30e289b

17 files changed

+204
-208
lines changed

projects/coreui-angular/src/lib/widget/widget-stat-a/widget-stat-a.component.html

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,28 @@
11
<ng-container>
22
<c-card-body [ngClass]="bodyClasses">
33
<div>
4-
@if (!!value || templates?.widgetValueTemplate) {
4+
@if (!!value() || templates?.['widgetValueTemplate']) {
55
<div class="fs-4 fw-semibold">
6-
<ng-container *ngTemplateOutlet="templates?.widgetValueTemplate || defaultWidgetValueTemplate" />
6+
<ng-container *ngTemplateOutlet="templates?.['widgetValueTemplate'] || defaultWidgetValueTemplate" />
77
</div>
88
}
9-
@if (!!title || templates?.widgetTitleTemplate) {
9+
@if (!!title() || templates?.['widgetTitleTemplate']) {
1010
<div>
11-
<ng-container *ngTemplateOutlet="templates?.widgetTitleTemplate || defaultWidgetTitleTemplate" />
11+
<ng-container *ngTemplateOutlet="templates?.['widgetTitleTemplate'] || defaultWidgetTitleTemplate" />
1212
</div>
1313
}
1414
</div>
15-
<ng-container *ngTemplateOutlet="templates?.widgetActionTemplate || defaultWidgetActionTemplate" />
15+
<ng-container *ngTemplateOutlet="templates?.['widgetActionTemplate'] || defaultWidgetActionTemplate" />
1616
</c-card-body>
17-
<ng-container *ngTemplateOutlet="templates?.widgetChartTemplate || defaultWidgetChartTemplate" />
17+
<ng-container *ngTemplateOutlet="templates?.['widgetChartTemplate'] || defaultWidgetChartTemplate" />
1818
</ng-container>
1919

2020
<ng-template #defaultWidgetTitleTemplate>
21-
{{ title }}
21+
{{ title() }}
2222
</ng-template>
2323

2424
<ng-template #defaultWidgetValueTemplate>
25-
{{ value }}
25+
{{ value() }}
2626
</ng-template>
2727

2828
<ng-template #defaultWidgetChartTemplate>

projects/coreui-angular/src/lib/widget/widget-stat-a/widget-stat-a.component.spec.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@ describe('WidgetStatAComponent', () => {
99
beforeEach(async () => {
1010
await TestBed.configureTestingModule({
1111
imports: [WidgetStatAComponent]
12-
})
13-
.compileComponents();
12+
}).compileComponents();
1413
});
1514

1615
beforeEach(() => {
@@ -22,4 +21,8 @@ describe('WidgetStatAComponent', () => {
2221
it('should create', () => {
2322
expect(component).toBeTruthy();
2423
});
24+
25+
it('should have css class"', () => {
26+
expect(fixture.nativeElement).toHaveClass('card');
27+
});
2528
});
Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import { AfterContentInit, Component, ContentChildren, HostBinding, Input, QueryList } from '@angular/core';
1+
import { Component, computed, contentChildren, effect, input, InputSignal, TemplateRef } from '@angular/core';
22

33
import { Colors } from '../../coreui.types';
44
import { TemplateIdDirective } from '../../shared';
5-
import { CardBodyComponent } from '../../card';
5+
import { CardBodyComponent, CardComponent } from '../../card';
66
import { NgClass, NgTemplateOutlet } from '@angular/common';
77

88
@Component({
@@ -11,37 +11,45 @@ import { NgClass, NgTemplateOutlet } from '@angular/common';
1111
exportAs: 'cWidgetStatA',
1212
imports: [CardBodyComponent, NgClass, NgTemplateOutlet],
1313
standalone: true,
14-
host: { class: 'card' }
14+
host: { class: 'card', '[class]': 'hostClasses()' }
1515
})
16-
export class WidgetStatAComponent implements AfterContentInit {
16+
export class WidgetStatAComponent extends CardComponent {
1717
/**
1818
* Sets the color context of the component to one of CoreUI’s themed colors.
1919
* @type Colors
2020
*/
21-
@Input() color?: Colors;
21+
// override readonly color = input<Colors>();
22+
2223
/**
2324
* Title of the widget to display
2425
* @type string
2526
*/
26-
@Input() title?: string;
27+
readonly title: InputSignal<string | undefined> = input();
28+
2729
/**
2830
* Value for your widget to display
2931
* @type string
3032
*/
31-
@Input() value?: string;
33+
readonly value: InputSignal<string | undefined> = input<string>();
34+
35+
templates: Record<string, TemplateRef<any>> = {};
3236

33-
templates: any = {};
37+
readonly contentTemplates = contentChildren(TemplateIdDirective, { descendants: true });
3438

35-
@ContentChildren(TemplateIdDirective, { descendants: true }) contentTemplates!: QueryList<TemplateIdDirective>;
39+
readonly contentTemplatesEffect = effect(() => {
40+
this.contentTemplates().forEach((child: TemplateIdDirective) => {
41+
this.templates[child.id] = child.templateRef;
42+
});
43+
});
3644

37-
@HostBinding('class')
38-
get hostClasses() {
45+
override readonly hostClasses = computed(() => {
46+
const color = this.color();
3947
return {
4048
card: true,
41-
[`bg-${this.color}`]: !!this.color,
42-
'text-white': !!this.color
43-
};
44-
}
49+
[`bg-${color}`]: !!color,
50+
'text-white': !!color
51+
} as Record<string, boolean>;
52+
});
4553

4654
get bodyClasses() {
4755
return {
@@ -51,10 +59,4 @@ export class WidgetStatAComponent implements AfterContentInit {
5159
'align-items-start': true
5260
};
5361
}
54-
55-
ngAfterContentInit(): void {
56-
this.contentTemplates.forEach((child: TemplateIdDirective) => {
57-
this.templates[child.id] = child.templateRef;
58-
});
59-
}
6062
}

projects/coreui-angular/src/lib/widget/widget-stat-b/widget-stat-b.component.spec.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@ describe('WidgetStatBComponent', () => {
99
beforeEach(async () => {
1010
await TestBed.configureTestingModule({
1111
imports: [WidgetStatBComponent]
12-
})
13-
.compileComponents();
12+
}).compileComponents();
1413
});
1514

1615
beforeEach(() => {
@@ -22,4 +21,8 @@ describe('WidgetStatBComponent', () => {
2221
it('should create', () => {
2322
expect(component).toBeTruthy();
2423
});
24+
25+
it('should have css class"', () => {
26+
expect(fixture.nativeElement).toHaveClass('card');
27+
});
2528
});

projects/coreui-angular/src/lib/widget/widget-stat-b/widget-stat-b.component.ts

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { booleanAttribute, Component, HostBinding, input, InputSignal, InputSignalWithTransform } from '@angular/core';
1+
import { booleanAttribute, Component, computed, input, InputSignal, InputSignalWithTransform } from '@angular/core';
22
import { NgClass } from '@angular/common';
33

44
import { CardBodyComponent, CardComponent } from '../../card';
@@ -9,7 +9,7 @@ import { CardBodyComponent, CardComponent } from '../../card';
99
exportAs: 'cWidgetStatB',
1010
standalone: true,
1111
imports: [CardBodyComponent, NgClass],
12-
host: { class: 'card' }
12+
host: { class: 'card', '[class]': 'hostClasses()' }
1313
})
1414
export class WidgetStatBComponent extends CardComponent {
1515
constructor() {
@@ -33,33 +33,34 @@ export class WidgetStatBComponent extends CardComponent {
3333
* Title of the widget to display
3434
* @type string
3535
*/
36-
readonly title: InputSignal<string | undefined> = input();
36+
readonly title: InputSignal<string | undefined> = input<string>();
3737

3838
/**
3939
* Helper text for your widget.
4040
* @type string
4141
*/
42-
readonly text: InputSignal<string | undefined> = input();
42+
readonly text: InputSignal<string | undefined> = input<string>();
4343

4444
/**
4545
* Value for your widget to display
4646
* @type string
4747
*/
48-
readonly value: InputSignal<string | undefined> = input();
48+
readonly value: InputSignal<string | undefined> = input<string>();
4949

5050
/**
5151
* Invert colors from their default dark shade.
5252
* @type boolean
5353
*/
5454
readonly inverse: InputSignalWithTransform<boolean, unknown> = input(false, { transform: booleanAttribute });
5555

56-
@HostBinding('class')
57-
override get hostClasses() {
56+
override readonly hostClasses = computed(() => {
57+
const color = this.color();
58+
const textColor = this.textColor();
5859
return {
5960
card: true,
60-
[`bg-${this.color()}`]: !!this.color(),
61-
[`text-${this.textColor()}`]: !!this.textColor(),
61+
[`bg-${color}`]: !!color,
62+
[`text-${textColor}`]: !!textColor,
6263
'text-white': this.inverse()
63-
};
64-
}
64+
} as Record<string, boolean>;
65+
});
6566
}

projects/coreui-angular/src/lib/widget/widget-stat-c/widget-stat-c.component.html

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,26 @@
11
<c-card-body>
2-
@if (icon || templates?.widgetIconTemplate) {
3-
<div [ngClass]="iconClasses">
4-
<ng-container *ngTemplateOutlet="templates?.widgetIconTemplate || defaultWidgetIconTemplate" />
2+
@if (icon() || templates?.['widgetIconTemplate']) {
3+
<div [ngClass]="iconClasses()">
4+
<ng-container *ngTemplateOutlet="templates?.['widgetIconTemplate'] || defaultWidgetIconTemplate" />
55
</div>
66
}
7-
@if (!!value) {
8-
<div [ngClass]="valueClasses">
9-
{{ value }}
7+
@if (!!value()) {
8+
<div [ngClass]="valueClasses()">
9+
{{ value() }}
1010
</div>
1111
}
12-
@if (!!title) {
13-
<div [ngClass]="titleClasses">
14-
{{ title }}
12+
@if (!!title()) {
13+
<div [ngClass]="titleClasses()">
14+
{{ title() }}
1515
</div>
1616
}
17-
@if (templates?.widgetProgressTemplate) {
18-
<ng-container *ngTemplateOutlet="templates?.widgetProgressTemplate || defaultWidgetProgressTemplate" />
17+
@if (templates?.['widgetProgressTemplate']) {
18+
<ng-container *ngTemplateOutlet="templates?.['widgetProgressTemplate'] || defaultWidgetProgressTemplate" />
1919
}
2020
</c-card-body>
2121

2222
<ng-template #defaultWidgetIconTemplate>
23-
{{ icon }}
23+
{{ icon() }}
2424
</ng-template>
2525

2626
<ng-template #defaultWidgetProgressTemplate>

projects/coreui-angular/src/lib/widget/widget-stat-c/widget-stat-c.component.spec.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@ describe('WidgetStatCComponent', () => {
99
beforeEach(async () => {
1010
await TestBed.configureTestingModule({
1111
imports: [WidgetStatCComponent]
12-
})
13-
.compileComponents();
12+
}).compileComponents();
1413
});
1514

1615
beforeEach(() => {
@@ -22,4 +21,8 @@ describe('WidgetStatCComponent', () => {
2221
it('should create', () => {
2322
expect(component).toBeTruthy();
2423
});
24+
25+
it('should have css class"', () => {
26+
expect(fixture.nativeElement).toHaveClass('card');
27+
});
2528
});

0 commit comments

Comments
 (0)