https://github.com/rxlabz/redarx-angular-example
Angular Dart app with Redarx state management
https://github.com/rxlabz/redarx-angular-example
Last synced: over 1 year ago
JSON representation
Angular Dart app with Redarx state management
- Host: GitHub
- URL: https://github.com/rxlabz/redarx-angular-example
- Owner: rxlabz
- Created: 2016-12-14T14:51:16.000Z (over 9 years ago)
- Default Branch: master
- Last Pushed: 2016-12-14T23:25:42.000Z (over 9 years ago)
- Last Synced: 2025-03-09T15:08:49.703Z (over 1 year ago)
- Language: Dart
- Size: 18.6 KB
- Stars: 0
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Redarx with Angular Dart
[Redarx](https://github.com/rxlabz/redarx) is a Dart State management inspired by ngrx<=Redux<=Elm and Parsley (Apache Flex framework).
It is based on a **stream of immutable states "reduced" with a Request-Commands map**.
UI emits update request$ => commander maps requests to commands => store receives commands, and use a reduceStream transformer
to transform the command$ stream to a stream of state$ => UI is updated with the state$ stream
## Config : config.dart
The [config.dart](https://github.com/rxlabz/redarx-angular-example/blob/master/lib/config.dart) file defines :
- the Requests/Commands map
- injected token factory
```dart
const CFG_COMMANDER = const OpaqueToken('cfg.commands');
const DATA_PATH = "todos.json";
final Map requestMap = {
RequestType.LOAD_ALL: AsyncLoadAllCommand.constructor(DATA_PATH),
RequestType.ADD_TODO: AddTodoCommand.constructor(),
RequestType.UPDATE_TODO: UpdateTodoCommand.constructor(),
RequestType.CLEAR_ARCHIVES: ClearArchivesCommand.constructor(),
RequestType.COMPLETE_ALL: CompleteAllCommand.constructor(),
RequestType.TOGGLE_SHOW_COMPLETED: ToggleShowArchivesCommand.constructor()
};
CommanderConfig configFactory() {
return new CommanderConfig(requestMap);
}
const DEFAULT_STORE = const OpaqueToken('redarx.store.default');
Store, TodoModel> storeFactory() =>
new Store, TodoModel>(() => const TodoModel.empty());
final dispatcher = new Dispatcher();
const DISPATCH = const OpaqueToken('redarx.dispatch');
Dispatch dispatchFactory() => dispatcher.dispatch;
const REQUEST$ = const OpaqueToken('redarx.request\$');
Stream request$Factory() => dispatcher.request$;
```
## Dependency Injection
Redarx classes are injected in the Angular app :
- CommanderConfig
- store
- dispatch method ( Dispatcher )
- request$ stream ( Dispatcher )
```dart
@Component(
selector: 'my-app',
styleUrls: const ['app_component.css'],
templateUrl: 'app_component.html',
viewProviders: const [
const Provider(CFG_COMMANDER, useFactory: configFactory),
const Provider(DEFAULT_STORE, useFactory: storeFactory),
const Provider(DISPATCH, useFactory: dispatchFactory),
const Provider(REQUEST$, useFactory: request$Factory),
CommanderService
],
directives: const [TodoForm, TodoFooter, TodoItem])
```
## CommanderService
The Commander service is just an @Injectable wrapper for the commander.
The commander instance is build with injected :
- CommanderConfig
- Store, TodoModel>
- Stream
```dart
@Injectable()
class CommanderService {
Commander, TodoModel> commander;
CommanderService(
@Inject(CFG_COMMANDER) CommanderConfig cfg,
@Inject(DEFAULT_STORE) Store, TodoModel> store,
@Inject(REQUEST$) Stream request$
) {
commander = new Commander, TodoModel>(cfg, store, request$);
}
}
```
## Commands
[Commands](https://github.com/rxlabz/redarx-angular-example/blob/master/lib/state/commands.dart) are simple classes with an exec method.
The `exec()` method create an update instance of the state model and return it.
```dart
/// add a new task
class AddTodoCommand extends Command {
Todo todo;
AddTodoCommand(this.todo);
@override
TodoModel exec(TodoModel model) =>
new TodoModel(model.items..add(todo), model.showCompleted);
static CommandBuilder constructor() {
return (Todo todo) => new AddTodoCommand(todo);
}
}
```
## Store.state$
The Store provides a stream of immutables state$. The App Component listen to injected store state$ stream,
and injected updated values in the children components.
```dart
class AppComponent {
TodoModel state;
Function dispatch;
AppComponent(CommanderService commander, @Inject(DISPATCH) this.dispatch,
@Inject(DEFAULT_STORE) Store, TodoModel> store) {
store.state$.listen((TodoModel newState) {
state = newState;
} );
loadAll();
}
loadAll() {
dispatch(new Request(RequestType.LOAD_ALL));
}
update(Todo todo) {
dispatch(new Request(RequestType.UPDATE_TODO, withData: todo));
}
}
```
## Immutable State Model
Each app must define its state [model](https://github.com/rxlabz/redarx-angular-example/blob/master/lib/state/model.dart) class, which must extends AbstracModel.
Abstract Model has a const contructor so the state instances are const.
In this example, we use [built_collection package](https://pub.dartlang.org/packages/built_collection) which provide some immutable data structures.
Here, items are stored in a BuildList.
```dart
class TodoModel extends AbstractModel{
const TodoModel(this.items, this.showCompleted);
final BuiltList items;
final bool showCompleted;
BuiltList get todos =>
new BuiltList(items.where((Todo t) => showCompleted ? t.completed : !t.completed));
int get numCompleted => items.where((t)=>t.completed).length;
int get numRemaining => items.where((t)=>!t.completed).length;
TodoModel.empty():items = new BuiltList(), showCompleted = false;
@override
AbstractModel initial() => new TodoModel.empty();
@override
String toString() {
return '''
TodoModel{
showCompleted = $showCompleted,
todos : $todos
}
''';
}
}
```
### BuildList
A [buildList](https://www.dartdocs.org/documentation/built_collection/1.0.6/built_collection/BuiltList-class.html) instance is immutable, but gives you access to a builder to update value, and rebuild a new updated instance.
```dart
var list = BuildList([1,2,3]);
var newList = list.rebuild((b)=>b.add(4));
```
- Learn more about [built_collection](https://medium.com/@davidmorgan_14314/darts-built-collection-for-immutable-collections-db662f705eff#.bxp1wei28)