Reputation: 43
I want to pass data to my navbar component when I log in to my login component, but my navbar content doesn't update.
My navbar component is in the app-module and my login component is in another module.
I tried use services to share data.
My login component, this component is in the another module
export class LoginComponent {
userCredentials;
constructor(
private readonly _authService: AuthService,
) {
}
login() {
this._authService.auth(this.userCredentials)
.subscribe(
(response: any) => {
const dataForm = {
usuario: response.user,
rol: this.response.role,
};
this._authService.setSession(response);
},
error => {
console.log(error);
}
);
}
}
My NavBarComponent, this component is in app-module
export class NavbarComponent {
isLogged = false;
susbscription: Subscription;
constructor(
private readonly _authService: AuthService,
) {
this.suscripcion = this._authService
.changeState$
.subscribe(
(isLogged) => {
this.isLogged = isLogged;
},
error => console.log(error)
);
}
}
My NavBar Html
<mat-toolbar color="primary">
<mat-toolbar-row>
<span>SUPERMERCADO</span>
<span class="spacer"></span>
<div *ngIf="!isLogged">
<button mat-button
Login
</button>
</div>
<div *ngIf="isLogged">
<p>Welcome</p>
</div>
</mat-toolbar-row>
</mat-toolbar>
My Service, this service is not in the app-module
@Injectable()
export class AuthService {
protected url = environment.url;
protected model = '/user';
isLogged = false;
private changeState = new Subject<boolean>();
changeState$ = this.changeState.asObservable();
constructor(
private readonly _router: Router,
protected readonly httpclient: HttpClient,
) {
}
setSession(data: any) {
this.isLogged = true;
this.changeState.next(this.isLogged);
}
auth(dataForm: any): Observable<any> {
const url = `${this.url}${this.model}/login`;
return this.httpclient.post(url, dataForm);
}
}
I'm using angular 8.2.0
Upvotes: 2
Views: 116
Reputation: 1298
From Component
import { Component, OnInit, ViewChild} from '@angular/core';
import { dataService } from "src/app/service/data.service";
@Component( {
selector: 'app-sideWidget',
templateUrl: './sideWidget.html',
styleUrls: ['./linked-widget.component.css']
} )
export class sideWidget{
constructor( private LWTableColumnNames: dataService ) {
}
ngOnInit() {
this.LWTableColumnNames.refLWTableColumnNames = "patient"; //this line of code will pass the value through data service
}
}
data service
import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable } from 'rxjs';
@Injectable()
export class dataService {
refLWTableColumnNames: string;//creating an object for the data
}
To Component
import { Component, OnInit } from '@angular/core';
import { dataService } from "src/app/service/data.service";
@Component( {
selector: 'app-linked-widget',
templateUrl: './linked-widget.component.html',
styleUrls: ['./linked-widget.component.css']
} )
export class LinkedWidgetComponent implements OnInit {
constructor(private LWTableColumnNames: dataService) { }
ngOnInit() {
console.log(this.LWTableColumnNames.refLWTableColumnNames); // out put will be string "patient"
}
}
Stackbliz demo in this way you can send values to different sibling components(not only parent child component)
Upvotes: -1
Reputation: 201
Is the LoginComponent part of a lazy loaded Module?
If so you need to add the providedIn: 'root' property to the AuthService:
@Injectable({
providedIn : 'root'
})
Make sure to remove it from the providers properties of the Module.
If your LoginComponent is not lazy loaded, make sure you only import the AuthService once in AppModule. Otherwise you may end up with multiple instances of AuthService.
If you want AuthService to be part of a module, you can use the forRoot pattern to ensure services are imported only once:
@NgModule({
// declarations, imports and exports only
})
export class SharedModule {
static forRoot(): ModuleWithProviders {
return {
ngModule: SharedModule,
providers: [// your services]
}
}
@NgModule({
imports: [SharedModule.forRoot()]
})
export class AppModule {}
If on Angular 8, you can also do:
@Injectable({
providedIn: SharedModule
})
export class AuthService
You want the same instance of AuthService to be available to both AppModule and the Module where your LoginComponent is.
Lastly, if this is not the issue you may have a problem where NavBarComponent subscribes to the changeState$ observable after it emits. In this case you need to change changeState to be a BehaviorSubject, so when NavBarComponent subscribes it receives the last emitted value.
Upvotes: 1
Reputation: 298
Store Data In Local Storage and access it any where in the components where you want just make one shared service to fetch info and use it. By {{}} string interpolation Service Part
getUserInfo() {
const savedCredentials = localStorage.getItem(credentialsKey);
return JSON.parse(savedCredentials);
}
Component Part:
this.currentUser = this.authService.getUserInfo();
And Access Data Like This :
this.currentUser.BusinessDate
Upvotes: 0
Reputation: 11934
There might be 2 reasons as to why your code does not work as expected.
changeState
subject emits data before the navbar component subscribes to it.
From what I can understand, when you are on the login page, so the navbar component shouldn't be loaded yet. When you. In your LoginComponent
, you first emit the data, then, when NavbarComponent
is loaded, you subscribe to the observable that just emitted.const s = new Subject();
s.next('not seen...');
s.next('not seen...');
s.next('not seen...');
s.subscribe(d => console.log('SUBSCRIBER 1: ', d))
// You must first subscribe, as the `Subject` does not holds any values on itself
s.subscribe(d => console.log('SUBSCRIBER 2: ', d))
// `Subscriber 1` will also receive those
s.next('value1 !!');
s.next('value2 !!');
/*
SUBSCRIBER 1: value1 !!
SUBSCRIBER 2: value1 !!
SUBSCRIBER 1: value2 !!
SUBSCRIBER 2: value2 !!
*/
const bs = new BehaviorSubject(null);
bs.next('not seen');
// It will retain only the last value for the new subscribers
bs.next('hmmm!!')
bs.subscribe(v => console.log('subscriber 1 of BS: ', v))
bs.next('value1!')
bs.subscribe(v => console.log('subscriber 2 of BS: ', v))
/*
subscriber 1 of BS: hmmm!!
subscriber 1 of BS: value1!
subscriber 2 of BS: value1!
*/
Here is a StackBlitz demo if you want to explore.
So, if you replace your Subject
with a BehaviorSubject(null)
, it should work.
AuthService
is not part of the AppModule
. There might be a chance of not getting a singleton.Injectable({ providedIn: 'root' })
decorator to your AuthService
class(which will also make the service tree-shakable).Upvotes: 1