Skip to content

Commit d18fee4

Browse files
authored
Merge branch 'main' into feature/2479-update-focusring-tokens
2 parents fa06654 + fcc7864 commit d18fee4

18 files changed

+279
-71
lines changed

.changeset/fancy-lies-kiss.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
'@sl-design-system/angular': minor
3+
---
4+
5+
- Add explicit `markForChanges()` to all `ControlValueAccessor` directives
6+
- Add support for the `<sl-number-field>` component:
7+
- Added `NumberFieldComponent` for exposing the web component API within Angular
8+
- Added `NumberFieldDirective` for Angular form integration
9+
10+
The above work the same as the existing bindings (for `<sl-text-field>` for example).

packages/angular/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
"@sl-design-system/form": "^1.2.4",
6464
"@sl-design-system/icon": "^1.2.1",
6565
"@sl-design-system/locales": "^0.0.13",
66+
"@sl-design-system/number-field": "^0.1.4",
6667
"@sl-design-system/radio-group": "^1.1.4",
6768
"@sl-design-system/select": "^2.0.4",
6869
"@sl-design-system/switch": "^1.1.4",

packages/angular/src/forms/checkbox-group.directive.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Directive, ElementRef, Inject, forwardRef } from '@angular/core';
1+
import { ChangeDetectorRef, Directive, ElementRef, Inject, forwardRef } from '@angular/core';
22
import { NG_VALIDATORS, NG_VALUE_ACCESSOR, type ValidationErrors } from '@angular/forms';
33
import { type CheckboxGroup } from '@sl-design-system/checkbox';
44
import { FormControlElementDirective } from './form-control-element.directive';
@@ -20,8 +20,11 @@ import { FormControlElementDirective } from './form-control-element.directive';
2020
]
2121
})
2222
export class CheckboxGroupDirective extends FormControlElementDirective<CheckboxGroup> {
23-
constructor(@Inject(ElementRef) elementRef: ElementRef<CheckboxGroup>) {
24-
super(elementRef);
23+
constructor(
24+
@Inject(ElementRef) elementRef: ElementRef<CheckboxGroup>,
25+
@Inject(ChangeDetectorRef) changeDetection: ChangeDetectorRef
26+
) {
27+
super(elementRef, changeDetection);
2528
}
2629

2730
override validate(): ValidationErrors | null {

packages/angular/src/forms/checkbox.directive.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Directive, ElementRef, Inject, forwardRef } from '@angular/core';
1+
import { ChangeDetectorRef, Directive, ElementRef, Inject, forwardRef } from '@angular/core';
22
import { NG_VALIDATORS, NG_VALUE_ACCESSOR, type ValidationErrors } from '@angular/forms';
33
import { type Checkbox } from '@sl-design-system/checkbox';
44
import { FormControlElementDirective } from './form-control-element.directive';
@@ -20,8 +20,11 @@ import { FormControlElementDirective } from './form-control-element.directive';
2020
]
2121
})
2222
export class CheckboxDirective extends FormControlElementDirective<Checkbox> {
23-
constructor(@Inject(ElementRef) elementRef: ElementRef<Checkbox>) {
24-
super(elementRef);
23+
constructor(
24+
@Inject(ElementRef) elementRef: ElementRef<Checkbox>,
25+
@Inject(ChangeDetectorRef) changeDetection: ChangeDetectorRef
26+
) {
27+
super(elementRef, changeDetection);
2528
}
2629

2730
override validate(): ValidationErrors | null {

packages/angular/src/forms/form-control-element.directive.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { type ElementRef, Injectable, type OnDestroy, type OnInit } from '@angular/core';
1+
import { type ChangeDetectorRef, type ElementRef, Injectable, type OnDestroy, type OnInit } from '@angular/core';
22
import { type AbstractControl, type ControlValueAccessor, type ValidationErrors, type Validator } from '@angular/forms';
33
import { type FormControl } from '@sl-design-system/form';
44

@@ -9,6 +9,7 @@ export abstract class FormControlElementDirective<T extends HTMLElement & FormCo
99
#onChange = (event: Event): void => {
1010
this.onChange((event as CustomEvent<T['formValue']>).detail);
1111
this.onTouched();
12+
this.changeDetection.markForCheck();
1213
};
1314

1415
protected onChange: (value: T['formValue']) => void = () => {};
@@ -19,7 +20,10 @@ export abstract class FormControlElementDirective<T extends HTMLElement & FormCo
1920
return this.elementRef.nativeElement;
2021
}
2122

22-
constructor(protected elementRef: ElementRef<T>) {}
23+
constructor(
24+
protected elementRef: ElementRef<T>,
25+
protected changeDetection: ChangeDetectorRef
26+
) {}
2327

2428
ngOnInit(): void {
2529
this.element.addEventListener('sl-blur', this.onTouched);
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import { ChangeDetectorRef, Directive, ElementRef, Inject, forwardRef } from '@angular/core';
2+
import { NG_VALIDATORS, NG_VALUE_ACCESSOR, type ValidationErrors } from '@angular/forms';
3+
import { type NumberField } from '@sl-design-system/number-field';
4+
import { FormControlElementDirective } from './form-control-element.directive';
5+
6+
@Directive({
7+
selector: 'sl-number-field',
8+
standalone: true,
9+
providers: [
10+
{
11+
provide: NG_VALUE_ACCESSOR,
12+
useExisting: forwardRef(() => NumberFieldDirective),
13+
multi: true
14+
},
15+
{
16+
provide: NG_VALIDATORS,
17+
useExisting: forwardRef(() => NumberFieldDirective),
18+
multi: true
19+
}
20+
]
21+
})
22+
export class NumberFieldDirective extends FormControlElementDirective<NumberField> {
23+
constructor(
24+
@Inject(ElementRef) elementRef: ElementRef<NumberField>,
25+
@Inject(ChangeDetectorRef) changeDetection: ChangeDetectorRef
26+
) {
27+
super(elementRef, changeDetection);
28+
}
29+
30+
override validate(): ValidationErrors | null {
31+
if (this.element.valid) {
32+
return null;
33+
} else if (
34+
!this.element.valid &&
35+
typeof this.element.min === 'number' &&
36+
typeof this.element.valueAsNumber === 'number' &&
37+
this.element.min > this.element.valueAsNumber
38+
) {
39+
return {
40+
rangeUnderflow: { min: this.element.min, actual: this.element.valueAsNumber }
41+
};
42+
} else if (
43+
!this.element.valid &&
44+
typeof this.element.max === 'number' &&
45+
typeof this.element.valueAsNumber === 'number' &&
46+
this.element.max < this.element.valueAsNumber
47+
) {
48+
return {
49+
rangeOverflow: { max: this.element.max, actual: this.element.valueAsNumber }
50+
};
51+
} else if (this.element.validity.valueMissing) {
52+
return { required: true };
53+
}
54+
55+
return null;
56+
}
57+
}

packages/angular/src/forms/public-api.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
export * from './checkbox-group.directive';
22
export * from './checkbox.directive';
33
export * from './form-control-element.directive';
4+
export * from './number-field.directive';
45
export * from './radio-group.directive';
56
export * from './select.directive';
67
export * from './switch.directive';

packages/angular/src/forms/radio-group.directive.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Directive, ElementRef, Inject, forwardRef } from '@angular/core';
1+
import { ChangeDetectorRef, Directive, ElementRef, Inject, forwardRef } from '@angular/core';
22
import { NG_VALIDATORS, NG_VALUE_ACCESSOR, type ValidationErrors } from '@angular/forms';
33
import { type RadioGroup } from '@sl-design-system/radio-group';
44
import { FormControlElementDirective } from './form-control-element.directive';
@@ -20,8 +20,11 @@ import { FormControlElementDirective } from './form-control-element.directive';
2020
]
2121
})
2222
export class RadioGroupDirective extends FormControlElementDirective<RadioGroup> {
23-
constructor(@Inject(ElementRef) elementRef: ElementRef<RadioGroup>) {
24-
super(elementRef);
23+
constructor(
24+
@Inject(ElementRef) elementRef: ElementRef<RadioGroup>,
25+
@Inject(ChangeDetectorRef) changeDetection: ChangeDetectorRef
26+
) {
27+
super(elementRef, changeDetection);
2528
}
2629

2730
override validate(): ValidationErrors | null {

packages/angular/src/forms/select.directive.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Directive, ElementRef, Inject, forwardRef } from '@angular/core';
1+
import { ChangeDetectorRef, Directive, ElementRef, Inject, forwardRef } from '@angular/core';
22
import { NG_VALIDATORS, NG_VALUE_ACCESSOR, type ValidationErrors } from '@angular/forms';
33
import { type Select } from '@sl-design-system/select';
44
import { FormControlElementDirective } from './form-control-element.directive';
@@ -20,8 +20,11 @@ import { FormControlElementDirective } from './form-control-element.directive';
2020
]
2121
})
2222
export class SelectDirective extends FormControlElementDirective<Select> {
23-
constructor(@Inject(ElementRef) elementRef: ElementRef<Select>) {
24-
super(elementRef);
23+
constructor(
24+
@Inject(ElementRef) elementRef: ElementRef<Select>,
25+
@Inject(ChangeDetectorRef) changeDetection: ChangeDetectorRef
26+
) {
27+
super(elementRef, changeDetection);
2528
}
2629

2730
override validate(): ValidationErrors | null {

packages/angular/src/forms/switch.directive.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Directive, ElementRef, Inject, forwardRef } from '@angular/core';
1+
import { ChangeDetectorRef, Directive, ElementRef, Inject, forwardRef } from '@angular/core';
22
import { NG_VALIDATORS, NG_VALUE_ACCESSOR } from '@angular/forms';
33
import { type Switch } from '@sl-design-system/switch';
44
import { FormControlElementDirective } from './form-control-element.directive';
@@ -20,7 +20,10 @@ import { FormControlElementDirective } from './form-control-element.directive';
2020
]
2121
})
2222
export class SwitchDirective extends FormControlElementDirective<Switch> {
23-
constructor(@Inject(ElementRef) elementRef: ElementRef<Switch>) {
24-
super(elementRef);
23+
constructor(
24+
@Inject(ElementRef) elementRef: ElementRef<Switch>,
25+
@Inject(ChangeDetectorRef) changeDetection: ChangeDetectorRef
26+
) {
27+
super(elementRef, changeDetection);
2528
}
2629
}

0 commit comments

Comments
 (0)