Skip to content

Commit 4e2a373

Browse files
committed
feat(template): implement naive signal compat
1 parent d2e20b9 commit 4e2a373

File tree

2 files changed

+61
-11
lines changed

2 files changed

+61
-11
lines changed

libs/template/for/src/lib/for.directive.ts

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,18 @@ import {
22
ChangeDetectorRef,
33
Directive,
44
DoCheck,
5+
effect,
56
ElementRef,
67
EmbeddedViewRef,
78
ErrorHandler,
89
Input,
10+
isSignal,
911
IterableDiffers,
1012
NgIterable,
1113
NgZone,
1214
OnDestroy,
1315
OnInit,
16+
Signal,
1417
TemplateRef,
1518
TrackByFunction,
1619
ViewContainerRef,
@@ -105,10 +108,18 @@ export class RxFor<T, U extends NgIterable<T> = NgIterable<T>>
105108
potentialObservable:
106109
| Observable<(U & NgIterable<T>) | undefined | null>
107110
| (U & NgIterable<T>)
111+
| Signal<U & NgIterable<T>>
108112
| null
109113
| undefined
110114
) {
111-
if (!isObservable(potentialObservable)) {
115+
if (
116+
typeof potentialObservable === 'function' &&
117+
isSignal(potentialObservable)
118+
) {
119+
this.staticValue = undefined;
120+
this.renderStatic = false;
121+
this.observables$.next(toObservable(potentialObservable));
122+
} else if (!isObservable(potentialObservable)) {
112123
this.staticValue = potentialObservable;
113124
this.renderStatic = true;
114125
} else {
@@ -134,7 +145,8 @@ export class RxFor<T, U extends NgIterable<T> = NgIterable<T>>
134145
* @description
135146
*
136147
* You can change the used `RenderStrategy` by using the `strategy` input of the `*rxFor`. It accepts
137-
* an `Observable<RxStrategyNames>` or [`RxStrategyNames`](https://github.com/rx-angular/rx-angular/blob/b0630f69017cc1871d093e976006066d5f2005b9/libs/cdk/render-strategies/src/lib/model.ts#L52).
148+
* an `Observable<RxStrategyNames>` or
149+
* [`RxStrategyNames`](https://github.com/rx-angular/rx-angular/blob/b0630f69017cc1871d093e976006066d5f2005b9/libs/cdk/render-strategies/src/lib/model.ts#L52).
138150
*
139151
* The default value for strategy is
140152
* [`normal`](https://www.rx-angular.io/docs/template/cdk/render-strategies/strategies/concurrent-strategies).
@@ -187,7 +199,8 @@ export class RxFor<T, U extends NgIterable<T> = NgIterable<T>>
187199
* - `@ContentChildren`
188200
*
189201
* Read more about this in the
190-
* [official docs](https://www.rx-angular.io/docs/template/api/rx-for-directive#local-strategies-and-view-content-queries-parent).
202+
* [official
203+
* docs](https://www.rx-angular.io/docs/template/api/rx-for-directive#local-strategies-and-view-content-queries-parent).
191204
*
192205
* @example
193206
* \@Component({
@@ -223,7 +236,8 @@ export class RxFor<T, U extends NgIterable<T> = NgIterable<T>>
223236
* Event listeners normally trigger zone. Especially high frequently events cause performance issues.
224237
*
225238
* Read more about this in the
226-
* [official docs](https://www.rx-angular.io/docs/template/api/rx-for-directive#working-with-event-listeners-patchzone).
239+
* [official
240+
* docs](https://www.rx-angular.io/docs/template/api/rx-for-directive#working-with-event-listeners-patchzone).
227241
*
228242
* @example
229243
* \@Component({
@@ -500,3 +514,14 @@ export class RxFor<T, U extends NgIterable<T> = NgIterable<T>>
500514
return true;
501515
}
502516
}
517+
518+
function toObservable<T>(input: Signal<T>): Observable<T> {
519+
return new Observable<T>((observer) => {
520+
const _effect = effect(() => {
521+
observer.next(input());
522+
});
523+
return () => {
524+
_effect.destroy();
525+
};
526+
});
527+
}

libs/template/let/src/lib/let.directive.ts

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
import {
22
ChangeDetectorRef,
33
Directive,
4+
effect,
45
ErrorHandler,
56
Input,
7+
isSignal,
68
NgZone,
79
OnChanges,
810
OnDestroy,
911
OnInit,
1012
Output,
13+
Signal,
1114
SimpleChanges,
1215
TemplateRef,
1316
ViewContainerRef,
@@ -73,10 +76,11 @@ export interface RxLetViewContext<T> extends RxViewContext<T> {
7376
*
7477
* **Conclusion - Structural directives**
7578
*
76-
* In contrast to global change detection, structural directives allow fine-grained control of change detection on a per directive basis.
77-
* The `LetDirective` comes with its own way to handle change detection in templates in a very efficient way.
78-
* However, the change detection behavior is configurable on a per directive or global basis.
79-
* This makes it possible to implement your own strategies, and also provides a migration path from large existing apps running with Angulars default change detection.
79+
* In contrast to global change detection, structural directives allow fine-grained control of change detection on a
80+
* per directive basis. The `LetDirective` comes with its own way to handle change detection in templates in a very
81+
* efficient way. However, the change detection behavior is configurable on a per directive or global basis. This
82+
* makes it possible to implement your own strategies, and also provides a migration path from large existing apps
83+
* running with Angulars default change detection.
8084
*
8185
* This package helps to reduce code used to create composable action streams.
8286
* It mostly is used in combination with state management libs to handle user interaction and backend communication.
@@ -114,13 +118,19 @@ export class LetDirective<U> implements OnInit, OnDestroy, OnChanges {
114118
*
115119
* @param { ObservableInput<U> | U | null | undefined } rxLet
116120
*/
117-
@Input() rxLet: ObservableInput<U> | U | null | undefined;
121+
@Input() rxLet:
122+
| ObservableInput<U>
123+
| Signal<U | null | undefined>
124+
| U
125+
| null
126+
| undefined;
118127

119128
/**
120129
* @description
121130
*
122131
* You can change the used `RenderStrategy` by using the `strategy` input of the `*rxLet`. It accepts
123-
* an `Observable<RxStrategyNames>` or [`RxStrategyNames`](https://github.com/rx-angular/rx-angular/blob/b0630f69017cc1871d093e976006066d5f2005b9/libs/cdk/render-strategies/src/lib/model.ts#L52).
132+
* an `Observable<RxStrategyNames>` or
133+
* [`RxStrategyNames`](https://github.com/rx-angular/rx-angular/blob/b0630f69017cc1871d093e976006066d5f2005b9/libs/cdk/render-strategies/src/lib/model.ts#L52).
124134
*
125135
* The default value for strategy is
126136
* [`normal`](https://www.rx-angular.io/docs/template/cdk/render-strategies/strategies/concurrent-strategies).
@@ -569,7 +579,11 @@ export class LetDirective<U> implements OnInit, OnDestroy, OnChanges {
569579
}
570580

571581
if (changes.rxLet) {
572-
this.observablesHandler.next(this.rxLet);
582+
this.observablesHandler.next(
583+
typeof this.rxLet === 'function' && isSignal(this.rxLet)
584+
? toObservable(this.rxLet)
585+
: this.rxLet
586+
);
573587
}
574588
}
575589

@@ -616,3 +630,14 @@ export class LetDirective<U> implements OnInit, OnDestroy, OnChanges {
616630
this.templateManager.nextStrategy(this.strategyHandler.values$);
617631
}
618632
}
633+
634+
function toObservable<T>(input: Signal<T>): Observable<T> {
635+
return new Observable<T>((observer) => {
636+
const _effect = effect(() => {
637+
observer.next(input());
638+
});
639+
return () => {
640+
_effect.destroy();
641+
};
642+
});
643+
}

0 commit comments

Comments
 (0)