How to change boolean value from parent component.ts to child component.ts
want to show and hide the login and logout option using ngif but not working.I do not know how to set and share boolean value between two components. I am using templateUrl.
app.component.ts:
export class AppComponent {
public isValid:boolean;
constructor(private router:Router){
}
logout(){
localStorage.removeItem('email');
this.router.navigate(['./login']);
this.isValid=true;
}
}
login.component.ts
export class LoginComponent implements OnInit {
public username:string;
public password:string;
constructor(private router:Router) { }
ngOnInit() {
}
userLogin(form:NgForm){
if(form.value.username==="admin@gmail.com" && form.value.password==="admin")
{
localStorage.setItem('email',form.value.username);
this.router.navigate(['./php']);
this.isValid=false;//not working//
} } }
app.component.html
<ul class="nav navbar-nav navbar-right">
<li *ngIf="isValid">
<a [routerLink]="['/login']" >Login</a>
</li>
<li *ngIf="!isValid">
<a (click)="logout()">LogOut</a>
</li>
</ul>
When passing data between components that lack a direct connection, such as siblings, grandchildren, etc, you should use a shared service.
You could either use RXJS BehaviorSubject
or Subject
for cross component communication.
Subject vs BehaviorSubject
Create a Service
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
@Injectable()
export class SharedService {
private valueSource = new BehaviorSubject<boolean>(false);
currentValue = this.valueSource.asObservable();
constructor() { }
changeValue(value: boolean) {
this.valueSource.next(value)
}
}
Register the service with an Angular module.
why? If we want an instance of a dependency to be shared globally and
share state
across the application we configure it on the
NgModule.
from Angular
docs
Angular module providers (@NgModule.providers)
are registered with the
application's root injector. Angular can inject the corresponding
services in any class it creates. Once created, a service instance
lives for the life of the app and Angular injects this one service
instance in every class that needs it.
@NgModule({
declarations: [
AppComponent,
],
imports: [
BrowserModule,
BrowserAnimationsModule,
],
providers: [SharedService],
bootstrap:[AppComponent],
Inject the SharedService in the components
app.component.ts:
export class AppComponent {
public isValid:boolean;
constructor(private router:Router:private service:SharedService){
this.service.currentValue.subscribe(message => this.isValid = message);//subscribe to the currentValue observable.
}
logout(){
localStorage.removeItem('email');
this.router.navigate(['./login']);
this.isValid=true;
}
login.component.ts
export class LoginComponent implements OnInit {
public username:string;
public password:string;
public isValid:boolean;
constructor(private router:Router,private service:SharedService) {}
ngOnInit() {
}
userLogin(form:NgForm){
if(form.value.username==="admin@gmail.com" && form.value.password==="admin")
{
localStorage.setItem('email',form.value.username);
this.router.navigate(['./php']);
this.isValid=false;
this.service.changeValue(this.isValid);//it calls next on the BehaviorSubject to change its value.
} } }
I do not really understand what is login component designed for, as it is not used anywhere in code provided. Anyway I would strongly suggest to go through basics again. You need to learn more about parent-child component interaction. Here you can find tutorial for that: https://angular.io/guide/component-interaction
You must use @Input
decorator you code is almost fine just add the followings sentence [isValid]="isLoginValid"
and @Input() isValid: any;
HTML App Component
<child-component [isValid]="isLoginValid"><child-component>
child.component.ts
Import {Input} from 'angular/core'
@Input() isValid: any;
....