createModel#
Creates a new model constructor with an instanced factory.
A SignalModel is a highly powerful architectural primitive designed to manage cohesive packages of related state, business logic, actions, and side effects.
Under the hood, SignalModel automatically tracks, scopes, and manages the lifecycle of any
Effects
instantiated during its factory execution. When the model is disposed (by calling
model.dispose()),
all nested/captured effects are clean up automatically, ensuring complete prevention of memory leaks.
Furthermore, if the factory returns a standard Dart Map, and wrapInAction
is enabled (default),
all nested function properties are automatically wrapped in batched action
transactions to optimize updates.
1. Advanced Architecture: Type-Safe Wrappers using Dart 3+ Extension Types#
While dynamic subscript access model'increment' is fast and flexible, it lacks static analysis safety.
To achieve compile-time type-safety, you can wrap the returned SignalModel
in a standard Dart 3 extension type:
import 'package:signals/signals.dart';
// 1. Define the reactive model constructor
final counterModel = createModel(() {
final count = signal(0);
// Captured nested side-effect (e.g. logging or syncing to local storage)
effect(() {
print('Nested logger: count is ${count.value}');
});
return <String, dynamic>{
'count': count,
'increment': () => count.value++,
};
});
// 2. Create a premium, compile-safe extension type wrapper
extension type TypeSafeCounter(SignalModel<Map<String, dynamic>> _model) {
int get count => (_model['count'] as Signal<int>).value;
set count(int val) => (_model['count'] as Signal<int>).value = val;
void increment() => (_model['increment'] as Function)();
void dispose() => _model.dispose();
}
void main() {
// 3. Instantiate and wrap the model
final counter = TypeSafeCounter(counterModel());
// Now you have a beautifully autocomplete-friendly, compile-safe API!
print(counter.count); // Prints: 0 (and registers effect print: Nested logger: count is 0)
counter.increment(); // Prints: Nested logger: count is 1
// Dispose when done to clean up all captured nested effects
counter.dispose();
}
SignalModel#
A premium wrapper for cohesive state packages constructed with createModel.
It holds the instanced model value and all the Effects that were captured during its construction. Disposing the SignalModel automatically disposes of all nested/captured effects, completely avoiding memory leaks.
Premium Pattern: Dart 3+ Extension Type Wrappers#
To avoid unchecked subscript access like model['count'].value, wrap your model in an extension type:
extension type TypeSafeCounter(SignalModel<Map<String, dynamic>> _model) {
int get count => (_model['count'] as Signal<int>).value;
set count(int val) => (_model['count'] as Signal<int>).value = val;
void increment() => (_model['increment'] as Function)();
void dispose() => _model.dispose();
}
Constructors#
View Constructors
SignalModel(this.value, this._effects, {this.options = const SignalModelOptions()})
Creates a new model instance.
Properties#
View Properties
T value
The instanced model value.
SignalModelOptions options
Options used to configure this model.
Methods#
View Methods
dynamic [](Object? key)
Access properties dynamically if the underlying value is a Map.
void []=(dynamic key, dynamic val)
Set properties dynamically if the underlying value is a Map.
void dispose()
Disposes of all captured effects.
SignalModelOptions#
Options for configuring a SignalModel.
Provides configuration for debug labeling (name) and whether to automatically wrap Map functions in transaction-safe, batched actions (wrapInAction).
Example Usage#
import 'package:preact_signals/preact_signals.dart';
final options = const SignalModelOptions(
name: 'user-profile-model',
wrapInAction: true,
);
Constructors#
View Constructors
SignalModelOptions({this.name, this.wrapInAction = true})
Creates a new instance of SignalModelOptions.
Properties#
View Properties
String? name
The name or debug label of the model.
bool wrapInAction
Whether to automatically wrap returned Map functions in actions. Defaults to true.
Methods#
View Methods
SignalModelOptions copyWith({String? name, bool? wrapInAction})
Copy options with new values.
bool ==(Object other)
int hashCode
SignalModelConstructor#
A constructor for models that manages nested effects.
The model constructor starts capturing effects when called, storing them inside the returned SignalModel.
Example Usage#
import 'package:preact_signals/preact_signals.dart';
final myModel = SignalModelConstructor(() => 'data');
final model = myModel();
print(model.value); // Prints: data
Constructors#
View Constructors
SignalModelConstructor(this._factory, {this.options = const SignalModelOptions()})
Creates a new instance of SignalModelConstructor.