I am having 2 components that do not have any parent-child relationship.
One component is a simple login.component.html:
<form #loginForm="ngForm" (ngSubmit)="onSubmit()">
<div class="login-container">
<mat-form-field appearance="fill">
<mat-label>Enter your username</mat-label>
<input
matInput
name="username"
type="text"
[(ngModel)]="username"
#usernameCtrl="ngModel"
required
/>
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>Enter your password</mat-label>
<input
matInput
name="password"
[type]="hide ? 'password' : 'text'"
[(ngModel)]="password"
#passwordCtrl="ngModel"
required
/>
<button
mat-icon-button
matSuffix
(click)="hide = !hide"
[attr.aria-label]="'Hide password'"
[attr.aria-pressed]="hide"
>
<mat-icon>{{ hide ? "visibility_off" : "visibility" }}</mat-icon>
</button>
</mat-form-field>
</div>
<div>
<button
mat-button
color="primary"
[disabled]="!loginForm.form.valid"
type="submit"
>
Login
</button>
</div>
</form>
and the other is a menu-bar.component.html:
<div>
<h1>Hello world!</h1>
<h2>I am visible in world all of the time!</h2>
<div *ngIf="loginSuccessfull"> <menu-app> </menu-app> </div>
</div>
When the user logs in successfully, I want to show my menu-app.component. What I did is that I defined a boolean variable that set it true when user logs in.
In login.component.ts:
onSubmit() {
if (this.username === 'a' && this.password === 'a') {
console.log('login successful');
this.loginService.updateLoginSuccessfull(true);
}
In menu-bar.component.ts:
ngOnInit() {
this.loginService.loginSuccessfull.subscribe(loginSuccessfull => this.loginSuccessfull = loginSuccessfull);
}
ngAfterContentChecked() {
this.loginService.loginSuccessfull.subscribe(loginSuccessfull => this.loginSuccessfull = loginSuccessfull);
}
As you can understand, both components are calling a service which is defined login.service.ts:
export class LoginService {
private onLogin = false;
private onLoginSuccessfull = new BehaviorSubject(this.onLogin);
loginSuccessfull = this.onLoginSuccessfull.asObservable();
constructor() { }
updateLoginSuccessfull(loginSuccessfull: boolean) {
this.onLoginSuccessfull.next(loginSuccessfull);
}
}
What am I missing? Is there any other way to do this change detection dynamically? Thanks!
The expected behaviour is to show the <menu-app></menu-app> only when the user logs in. If the user does not log in, he should not see the component.
The way I implemented does not show the component even though the use logs in successfully.
The components look mostly fine. Are you using OnPush change detection for the menu-bar component? You are also creating 2 subscriptions in the menu-bar component in ngOnInit and ngAfterContentChecked. This will update the loginSuccessful field twice each time a value is emitted from the service. Neither of these are needed if you use the
async pipe. The async pipe automatically subscribes (and unsubscribes) to the Observable, will trigger change detection when using OnPush, and reduces the code needed in the component.menu-bar.component.ts
https://stackblitz.com/edit/angular-ivy-pzss5d