Skip to content

Commit 29ef3fb

Browse files
committed
feat(cdk/bidi): add value signal to Directionality
1 parent d4cccb7 commit 29ef3fb

File tree

4 files changed

+37
-22
lines changed

4 files changed

+37
-22
lines changed

src/cdk/bidi/dir.ts

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,15 @@
66
* found in the LICENSE file at https://angular.dev/license
77
*/
88

9-
import {Directive, Output, Input, EventEmitter, AfterContentInit, OnDestroy} from '@angular/core';
9+
import {
10+
AfterContentInit,
11+
Directive,
12+
EventEmitter,
13+
Input,
14+
OnDestroy,
15+
Output,
16+
signal,
17+
} from '@angular/core';
1018

1119
import {Direction, Directionality, _resolveDirectionality} from './directionality';
1220

@@ -23,9 +31,6 @@ import {Direction, Directionality, _resolveDirectionality} from './directionalit
2331
exportAs: 'dir',
2432
})
2533
export class Dir implements Directionality, AfterContentInit, OnDestroy {
26-
/** Normalized direction that accounts for invalid/unsupported values. */
27-
private _dir: Direction = 'ltr';
28-
2934
/** Whether the `value` has been set to its initial value. */
3035
private _isInitialized: boolean = false;
3136

@@ -38,19 +43,19 @@ export class Dir implements Directionality, AfterContentInit, OnDestroy {
3843
/** @docs-private */
3944
@Input()
4045
get dir(): Direction {
41-
return this._dir;
46+
return this.valueSignal();
4247
}
4348
set dir(value: Direction | 'auto') {
44-
const previousValue = this._dir;
49+
const previousValue = this.valueSignal();
4550

4651
// Note: `_resolveDirectionality` resolves the language based on the browser's language,
4752
// whereas the browser does it based on the content of the element. Since doing so based
4853
// on the content can be expensive, for now we're doing the simpler matching.
49-
this._dir = _resolveDirectionality(value);
54+
this.valueSignal.set(_resolveDirectionality(value));
5055
this._rawDir = value;
5156

52-
if (previousValue !== this._dir && this._isInitialized) {
53-
this.change.emit(this._dir);
57+
if (previousValue !== this.valueSignal() && this._isInitialized) {
58+
this.change.emit(this.valueSignal());
5459
}
5560
}
5661

@@ -59,6 +64,8 @@ export class Dir implements Directionality, AfterContentInit, OnDestroy {
5964
return this.dir;
6065
}
6166

67+
readonly valueSignal = signal<Direction>('ltr');
68+
6269
/** Initialize once default value has been set. */
6370
ngAfterContentInit() {
6471
this._isInitialized = true;

src/cdk/bidi/directionality.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* found in the LICENSE file at https://angular.dev/license
77
*/
88

9-
import {EventEmitter, Injectable, OnDestroy, inject} from '@angular/core';
9+
import {EventEmitter, Injectable, OnDestroy, inject, signal} from '@angular/core';
1010
import {DIR_DOCUMENT} from './dir-document-token';
1111

1212
export type Direction = 'ltr' | 'rtl';
@@ -33,7 +33,14 @@ export function _resolveDirectionality(rawValue: string): Direction {
3333
@Injectable({providedIn: 'root'})
3434
export class Directionality implements OnDestroy {
3535
/** The current 'ltr' or 'rtl' value. */
36-
readonly value: Direction = 'ltr';
36+
get value() {
37+
return this.valueSignal();
38+
}
39+
40+
/**
41+
* The current 'ltr' or 'rtl' value.
42+
*/
43+
readonly valueSignal = signal<Direction>('ltr');
3744

3845
/** Stream that emits whenever the 'ltr' / 'rtl' state changes. */
3946
readonly change = new EventEmitter<Direction>();
@@ -46,7 +53,7 @@ export class Directionality implements OnDestroy {
4653
if (_document) {
4754
const bodyDir = _document.body ? _document.body.dir : null;
4855
const htmlDir = _document.documentElement ? _document.documentElement.dir : null;
49-
this.value = _resolveDirectionality(bodyDir || htmlDir || 'ltr');
56+
this.valueSignal.set(_resolveDirectionality(bodyDir || htmlDir || 'ltr'));
5057
}
5158
}
5259

src/dev-app/dev-app/dev-app-directionality.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,21 @@
77
*/
88

99
import {Direction, Directionality} from '@angular/cdk/bidi';
10-
import {EventEmitter, Injectable, OnDestroy} from '@angular/core';
10+
import {EventEmitter, Injectable, OnDestroy, signal} from '@angular/core';
1111

1212
@Injectable()
1313
export class DevAppDirectionality implements Directionality, OnDestroy {
1414
readonly change = new EventEmitter<Direction>();
1515

1616
get value(): Direction {
17-
return this._value;
17+
return this.valueSignal();
1818
}
1919
set value(value: Direction) {
20-
this._value = value;
20+
this.valueSignal.set(value);
2121
this.change.next(value);
2222
}
23-
private _value: Direction = 'ltr';
23+
24+
valueSignal = signal<Direction>('ltr');
2425

2526
ngOnDestroy() {
2627
this.change.complete();

src/material/datepicker/date-range-input.spec.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import {FocusMonitor} from '@angular/cdk/a11y';
2-
import {Directionality} from '@angular/cdk/bidi';
2+
import {Direction, Directionality} from '@angular/cdk/bidi';
33
import {BACKSPACE, LEFT_ARROW, RIGHT_ARROW} from '@angular/cdk/keycodes';
44
import {OverlayContainer} from '@angular/cdk/overlay';
55
import {dispatchFakeEvent, dispatchKeyboardEvent} from '@angular/cdk/testing/private';
6-
import {Component, Directive, ElementRef, Provider, Type, ViewChild} from '@angular/core';
7-
import {ComponentFixture, TestBed, fakeAsync, flush, inject, tick} from '@angular/core/testing';
6+
import {Component, Directive, ElementRef, Provider, signal, Type, ViewChild} from '@angular/core';
7+
import {ComponentFixture, fakeAsync, flush, inject, TestBed, tick} from '@angular/core/testing';
88
import {
99
FormControl,
1010
FormGroup,
@@ -15,11 +15,11 @@ import {
1515
Validator,
1616
Validators,
1717
} from '@angular/forms';
18+
import {NoopAnimationsModule} from '@angular/platform-browser/animations';
19+
import {Subscription} from 'rxjs';
1820
import {ErrorStateMatcher, MatNativeDateModule} from '../core';
1921
import {MatFormField, MatFormFieldModule, MatLabel} from '../form-field';
2022
import {MatInputModule} from '../input';
21-
import {NoopAnimationsModule} from '@angular/platform-browser/animations';
22-
import {Subscription} from 'rxjs';
2323
import {MatDateRangeInput} from './date-range-input';
2424
import {MatEndDate, MatStartDate} from './date-range-input-parts';
2525
import {MatDateRangePicker} from './date-range-picker';
@@ -830,7 +830,7 @@ describe('MatDateRangeInput', () => {
830830

831831
it('moves focus between fields with arrow keys when cursor is at edge (RTL)', () => {
832832
class RTL extends Directionality {
833-
override readonly value = 'rtl';
833+
override readonly valueSignal = signal<Direction>('rtl');
834834
}
835835
const fixture = createComponent(StandardRangePicker, [
836836
{

0 commit comments

Comments
 (0)