Reputation: 19
I'm trying to use NgRx with the angular material, to open and close the sidenav, but I'm not maintaining it.
My Store:
export const sidenavFeatureKey = 'sidenav';
export interface SidenavState {
status: boolean
}
export const initialSidenavState: SidenavState = {
status: false
}
export const sidenavReducer = createReducer(
initialSidenavState,
on(toggleSideNav,
(state) => {
return {
...state,
status: !state.status
}
}
)
)
my action
export const toggleSideNav = createAction(
"[Toolbar - Sidenav] Change sidenav to true or false"
)
my header
export class HeaderComponent {
constructor(private sidenavStore: Store<SidenavState>) {
}
toggleSidenav() {
this.sidenavStore.dispatch(toggleSideNav())
}
}
<mat-toolbar absolute>
<button (click)="toggleSidenav()" mat-icon-button>
<mat-icon>menu</mat-icon>
</button>
<span>My App</span>
<span class="example-spacer"></span>
<button aria-label="Example icon-button with heart icon" class="example-icon favorite-icon" mat-icon-button>
<mat-icon>favorite</mat-icon>
</button>
<button aria-label="Example icon-button with share icon" class="example-icon" mat-icon-button>
<mat-icon>share</mat-icon>
</button>
</mat-toolbar>
and my sidenav
export class SidenavComponent implements OnInit {
sidenavStatus: boolean = true;
constructor(private sidenavStore: Store<SidenavState>) {
};
ngOnInit() {
this.sidenavStore.select("status").subscribe(
toggle => this.sidenavStatus = toggle
);
}
}
<mat-sidenav-container>
<mat-sidenav [(opened)]="sidenavStatus" mode="side">
<p>Hiding</p>
</mat-sidenav>
<mat-sidenav-content>
<p>Hello</p>
</mat-sidenav-content>
</mat-sidenav-container>
My Store status, changes from true to false when clicking on the header button, but the sidenav does not open and close.
Upvotes: 0
Views: 306
Reputation: 1771
This may be unrelatd, but you don't need two-way binding on opened
, as sidenavStatus
will be updated via your selector and the actions you emit. You could replace [(opened)]
with [opened]
as follows:
sidenav.html
<mat-sidenav-container>
<mat-sidenav [opened]="sidenavStatus" mode="side">
<p>Hiding</p>
</mat-sidenav>
<mat-sidenav-content>
<p>Hello</p>
</mat-sidenav-content>
</mat-sidenav-container>
This would then guarantee that the only thing responsible for controlling the state of your sidebar is the sidenavStatus
variable in the parent component (unless of course you have logic in your mat-sidenav
component which is changing the value of opened
internally).
We could take this one step further and replace sidenavStatus
with an Observable
that contains only the toggle state you are interested in and then use this in the template with the async
pipe
sidenav.ts
export class SidenavComponent implements OnInit {
sidenavStatus$: Observable<boolean>;
constructor(private sidenavStore: Store<SidenavState>) {
};
ngOnInit() {
this.sidenavStatus$ = this.sidenavStore.select("status");
}
}
sidenav.html
<mat-sidenav-container>
<mat-sidenav [opened]="sidenavStatus$ | async" mode="side">
<p>Hiding</p>
</mat-sidenav>
<mat-sidenav-content>
<p>Hello</p>
</mat-sidenav-content>
</mat-sidenav-container>
Now, whatever value resides in the store for the selector "status"
will be fed directly into your child component. If it still doesn't work, you can then at least rule out the store implementation as the source of the issue
Upvotes: 0