In this exercise we will refactor app-shell
component and get familiar with RxState.
First let's add RxState to our app-shell.component.ts
:
// Exercise 7: Add RxState import here
import { RxState } from "@rx-angular/state";
State is a local service, add it to component providers:
// Exercise 7: Add RxState and RxActionFactory here
providers: [RxEffects, RxState],
Provide it in the constructor:
constructor(
// Exercise 7: Add RxState here
private state: RxState<{ sideDrawerOpen: boolean }>,
...
) {}
Now we need to initialize our default value.
Go to init
function and set the initial state:
init() {
// Exercise 7: initialize state here
this.state.set({sideDrawerOpen: false});
...
}
Let's refactor our view model.
Replace viewModel$
stream with select
method.
// Exercise 7: Replace it with state.select()
readonly viewState$ = this.state.select('sideDrawerOpen');
// this.state$.pipe(
// distinctUntilChanged((o, n) => o.sideDrawerOpen === n.sideDrawerOpen),
// shareReplay({ bufferSize: 1, refCount: true })
// );
Now we can remove our state$
BehaviorSubject
:
// Exercise 7: Remove state$
// private readonly state$ = new BehaviorSubject<{ sideDrawerOpen: boolean }>({
// sideDrawerOpen: false,
// });
Create a subject called sideDrawerOpenToggle
:
// Exercise 7: Create ui actions here
readonly sideDrawerOpenToggle = new Subject<boolean>();
Connect Subject
to state in init
method:
init() {
// Exercise 7: initialize state here
this.state.set({sideDrawerOpen: false});
// Exercise 7: connect ui here
this.state.connect('sideDrawerOpen', this.sideDrawerOpenToggle);
...
}
Replace closeSidenav
call with Subject.next
.
// Exercise 7: replace with ui action
() => this.sideDrawerOpenToggle.next(false);
Do a cleanup:
// Exercise 7: remove this function
// closeSidenav = () => {
// this.state$.next({
// sideDrawerOpen: false,
// });
// };
// Exercise 7: remove this function
// sideDrawerOpenToggle = (sideDrawerOpen: boolean) => {
// this.state$.next({
// sideDrawerOpen,
// });
// };
In app-shell.component.html
replace calls of sideDrawerOpenToggle
with sideDrawerOpenToggle.next(!vs)
<!-- Exercise 7: replace with actions -->
<ui-side-drawer [opened]="vs" (openedChange)="sideDrawerOpenToggle.next(false)">
...
</ui-side-drawer>
<!-- Exercise 7: replace with actions -->
<ui-hamburger-button
data-uf="menu-btn"
class="ui-toolbar--action"
(click)="sideDrawerOpenToggle.next(!vs)"
>
...
</ui-hamburger-button>
RxActions is another tool provided by rx-angular. Main goal is to simplify triggers that causing state updates or side effects.
Add RxActionFactory
import:
// Exercise 7: Add RxActionFactory import here
import { RxActionFactory } from "../shared/rxa-custom/actions";
Add it to providers:
// Exercise 7: Add RxState and RxActionFactory here
providers: [RxEffects, RxState, RxActionFactory],
Add actions to the constructor:
constructor(
// Exercise 7: Add RxState here
private state: RxState<{ sideDrawerOpen: boolean }>,
// Exercise 7: Add RxActionFactory here
private actionsF: RxActionFactory<{sideDrawerOpenToggle: boolean}>,
...
) {}
Replace sideDrawerOpenToggle
with ui
property:
// Exercise 7: Create ui actions here
readonly ui = this.actionsF.create();
Connect ui.sideDrawerOpenToggle$
to state instead of Subject
:
init() {
// Exercise 7: initialize state here
this.state.set({sideDrawerOpen: false});
// Exercise 7: connect ui here
this.state.connect('sideDrawerOpen', this.ui.sideDrawerOpenToggle$);
...
}
Replace Subject.next
with a call of sideDrawerOpenToggle()
:
// Exercise 7: replace with ui action
() => this.ui.sideDrawerOpenToggle(false);
Remove sideDrawerOpenToggle
subject:
// Exercise 7: Create ui actions here
// readonly sideDrawerOpenToggle = new Subject<boolean>();
Refactor template:
<!-- Exercise 7: replace with actions -->
<ui-side-drawer [opened]="vs" (openedChange)="ui.sideDrawerOpenToggle(false)">
...
</ui-side-drawer>
<!-- Exercise 7: replace with actions -->
<ui-hamburger-button
data-uf="menu-btn"
class="ui-toolbar--action"
(click)="ui.sideDrawerOpenToggle(!vs)"
>
...
</ui-hamburger-button>