diff --git a/packages/signals_core/lib/src/async/computed.dart b/packages/signals_core/lib/src/async/computed.dart index e8cf6228..3e77f79b 100644 --- a/packages/signals_core/lib/src/async/computed.dart +++ b/packages/signals_core/lib/src/async/computed.dart @@ -10,7 +10,7 @@ import 'future.dart'; /// /// ```dart /// final movieId = signal('id'); -/// late final movie = computedFrom(args, ([movieId]) => fetchMovie(args.first)); +/// late final movie = computedFrom([movieId], (args) => fetchMovie(args.first)); /// ``` /// /// Since all dependencies are passed in as arguments there is no need to worry about calling the signals before any async gaps with await. @@ -32,6 +32,129 @@ FutureSignal computedFrom( ); } +/// [computedFrom] for one signal. +FutureSignal computedFrom1( + ReadonlySignal signal1, + Future Function(A value1) fn, { + T? initialValue, + String? debugLabel, + bool autoDispose = false, + bool lazy = true, +}) { + return FutureSignal( + () => fn(signal1()), + dependencies: [signal1], + initialValue: initialValue, + debugLabel: debugLabel, + autoDispose: autoDispose, + lazy: lazy, + ); +} + +/// [computedFrom] for two signals. +FutureSignal computedFrom2( + ReadonlySignal signal1, + ReadonlySignal signal2, + Future Function( + A value1, + B value2, + ) fn, { + T? initialValue, + String? debugLabel, + bool autoDispose = false, + bool lazy = true, +}) { + return FutureSignal( + () => fn(signal1(), signal2()), + dependencies: [signal1, signal2], + initialValue: initialValue, + debugLabel: debugLabel, + autoDispose: autoDispose, + lazy: lazy, + ); +} + +/// [computedFrom] for three signals. +FutureSignal computedFrom3( + ReadonlySignal signal1, + ReadonlySignal signal2, + ReadonlySignal signal3, + Future Function( + A value1, + B value2, + C value3, + ) fn, { + T? initialValue, + String? debugLabel, + bool autoDispose = false, + bool lazy = true, +}) { + return FutureSignal( + () => fn(signal1(), signal2(), signal3()), + dependencies: [signal1, signal2, signal3], + initialValue: initialValue, + debugLabel: debugLabel, + autoDispose: autoDispose, + lazy: lazy, + ); +} + +/// [computedFrom] for four signals. +FutureSignal computedFrom4( + ReadonlySignal signal1, + ReadonlySignal signal2, + ReadonlySignal signal3, + ReadonlySignal signal4, + Future Function( + A value1, + B value2, + C value3, + D value4, + ) fn, { + T? initialValue, + String? debugLabel, + bool autoDispose = false, + bool lazy = true, +}) { + return FutureSignal( + () => fn(signal1(), signal2(), signal3(), signal4()), + dependencies: [signal1, signal2, signal3, signal4], + initialValue: initialValue, + debugLabel: debugLabel, + autoDispose: autoDispose, + lazy: lazy, + ); +} + +/// [computedFrom] for five signals. +FutureSignal computedFrom5( + ReadonlySignal signal1, + ReadonlySignal signal2, + ReadonlySignal signal3, + ReadonlySignal signal4, + ReadonlySignal signal5, + Future Function( + A value1, + B value2, + C value3, + D value4, + E value5, + ) fn, { + T? initialValue, + String? debugLabel, + bool autoDispose = false, + bool lazy = true, +}) { + return FutureSignal( + () => fn(signal1(), signal2(), signal3(), signal4(), signal5()), + dependencies: [signal1, signal2, signal3, signal4, signal5], + initialValue: initialValue, + debugLabel: debugLabel, + autoDispose: autoDispose, + lazy: lazy, + ); +} + /// Async Computed is syntax sugar around [FutureSignal]. /// /// _Inspired by [computedAsync](https://ngxtension.netlify.app/utilities/signals/computed-async/) from Angular NgExtension._ diff --git a/packages/signals_core/test/async/state_test.dart b/packages/signals_core/test/async/state_test.dart index 92431f6d..586d6d61 100644 --- a/packages/signals_core/test/async/state_test.dart +++ b/packages/signals_core/test/async/state_test.dart @@ -152,7 +152,7 @@ void main() { expect(value, true); }); }); - + group('pattern matching', () { test('loading', () { final s = AsyncState.loading(); diff --git a/packages/signals_flutter/lib/src/mixins/signals.dart b/packages/signals_flutter/lib/src/mixins/signals.dart index 7b2196d4..0bc3dc1f 100644 --- a/packages/signals_flutter/lib/src/mixins/signals.dart +++ b/packages/signals_flutter/lib/src/mixins/signals.dart @@ -105,7 +105,7 @@ mixin SignalsMixin on State { /// /// ```dart /// final movieId = signal('id'); - /// late final movie = computedFrom(args, ([movieId]) => fetchMovie(args.first)); + /// late final movie = computedFrom([movieId], (args) => fetchMovie(args.first)); /// ``` /// /// Since all dependencies are passed in as arguments there is no need to worry about calling the signals before any async gaps with await. @@ -125,6 +125,111 @@ mixin SignalsMixin on State { )); } + /// [createComputedFrom] for one signal. + FutureSignal createComputedFrom1( + ReadonlySignal signal1, + Future Function(A value1) fn, { + S? initialValue, + String? debugLabel, + bool lazy = true, + }) { + return _bindLocal(computedFrom1( + signal1, + fn, + initialValue: initialValue, + debugLabel: debugLabel, + lazy: lazy, + )); + } + + /// [createComputedFrom] for two signals. + FutureSignal createComputedFrom2( + ReadonlySignal signal1, + ReadonlySignal signal2, + Future Function(A value1, B value2) fn, { + S? initialValue, + String? debugLabel, + bool lazy = true, + }) { + return _bindLocal(computedFrom2( + signal1, + signal2, + fn, + initialValue: initialValue, + debugLabel: debugLabel, + lazy: lazy, + )); + } + + /// [createComputedFrom] for three signals. + FutureSignal createComputedFrom3( + ReadonlySignal signal1, + ReadonlySignal signal2, + ReadonlySignal signal3, + Future Function(A value1, B value2, C value3) fn, { + S? initialValue, + String? debugLabel, + bool lazy = true, + }) { + return _bindLocal(computedFrom3( + signal1, + signal2, + signal3, + fn, + initialValue: initialValue, + debugLabel: debugLabel, + lazy: lazy, + )); + } + + /// [createComputedFrom] for four signals. + FutureSignal createComputedFrom4( + ReadonlySignal signal1, + ReadonlySignal signal2, + ReadonlySignal signal3, + ReadonlySignal signal4, + Future Function(A value1, B value2, C value3, D value4) fn, { + S? initialValue, + String? debugLabel, + bool lazy = true, + }) { + return _bindLocal(computedFrom4( + signal1, + signal2, + signal3, + signal4, + fn, + initialValue: initialValue, + debugLabel: debugLabel, + lazy: lazy, + )); + } + + /// [createComputedFrom] for five signals. + FutureSignal createComputedFrom5( + ReadonlySignal signal1, + ReadonlySignal signal2, + ReadonlySignal signal3, + ReadonlySignal signal4, + ReadonlySignal signal5, + Future Function(A value1, B value2, C value3, D value, E value5) fn, { + S? initialValue, + String? debugLabel, + bool lazy = true, + }) { + return _bindLocal(computedFrom5( + signal1, + signal2, + signal3, + signal4, + signal5, + fn, + initialValue: initialValue, + debugLabel: debugLabel, + lazy: lazy, + )); + } + /// Async Computed is syntax sugar around [FutureSignal]. /// /// _Inspired by [computedAsync](https://ngxtension.netlify.app/utilities/signals/computed-async/) from Angular NgExtension._