0

Actually, I have a subject which will provide the authentication status. I have postlistcomponent which will show all the posts & in that component i have edit & delete buttons. Whenever i login after successful authentication a boolean value (true/false) is sent from auth service to postlist component. Then based on the boolean value we are allowing users to edit or delete the post.

In my case this is not happening. After successful authentication, edit and post buttons are not visible

auth.service.ts

private token : string;
private authStatusListener = new Subject<boolean>()

 getToken() {
        return this.token
    }

    getAuthStatusListener() {
        return this.authStatusListener.asObservable()
    }

loginUser(email : string , password : string) {
        const authData : AuthData = {email : email,password : password}
        this.http.post<{token: string}>("http://localhost:3000/api/user/login%22,authData)
        .subscribe((response) => {
            const serverGeneratedToken = response.token
            this.token = serverGeneratedToken
            this.authStatusListener.next(true)
        })

login.component.ts

    onLogin(form : NgForm) {

        if(form.invalid){
            return;
        }
        this.authService.loginUser(form.value.email,form.value.password)
        form.resetForm();
    }

post-list.component.ts

constructor(public postsService:PostsService,private authService : AuthService) {}

     private authListenerSub : Subscription
     userIsAuthenticated = false

ngOnInit(){
         this.isLoading = true
         this.postsService.getPosts(this.postsPerPage,this.currentPage)
         this.postsService.getPostUpdateListener()
         .subscribe((postData : {posts : Post[] , postCount : number}) => {
             this.isLoading = false
             this.posts = postData.posts
             this.totalPosts = postData.postCount
         })

         this.authService.getAuthStatusListener().subscribe(isAuthenticated => {
            this.userIsAuthenticated = isAuthenticated
         })
     }

post-list.component.html

<mat-action-row *ngIf="userIsAuthenticated">
            <a mat-button color="primary" [routerLink]="['/edit',post.id]">EDIT</a>
            <a mat-button color="warn" (click)="onDelete(post.id)">DELETE</a>
        </mat-action-row>
Shivaay
  • 143
  • 1
  • 1
  • 6
  • In `post-list.component.ts` put a `debugger;` inside of the callback function of `getAuthStatusListener()` and see what the value of `isAuthenticated` is. Also, in `auth.service.ts`, I would not subscribe in a service because this is an anti-pattern. I would return the `http` observable from the service and subscribe to it in `login.component.ts`. – AliF50 Jan 30 '20 at 15:33
  • I couldn't see the value there for isAuthenticated – Shivaay Jan 30 '20 at 15:37
  • Any errors in the console? Is the function under `subscribe` in `loginUser` executed, and does it have the correct `this` context? Specifically, no errors like `Cannot read property 'next' of undefined`? – mbojko Jan 30 '20 at 15:38
  • It could be that the subject is not being initiated with a value like `mbojko` suggested. Try logging in and then see if you get a value. – AliF50 Jan 30 '20 at 15:39
  • stick a `console.log(this.userIsAuthenticated)` after `this.userIsAuthenticated = isAuthenticated` to see if this is component issue or to do with the authservice – Andrew Allen Jan 30 '20 at 16:30

2 Answers2

0

Angular is only updating the view, if you change data in the "Angular zone". The asynchronous call in your example does not qualify for this. But if you want, you can put it in the Angular zone or use rxjs or extract part of the code to a new component to solve this problem.

Angular Zone

The most common use of this service is to optimize performance when starting a work consisting of one or more asynchronous tasks that don't require UI updates or error handling to be handled by Angular. Such tasks can be kicked off via runOutsideAngular and if needed, these tasks can reenter the Angular zone via run. https://angular.io/api/core/NgZone

add this in constructor

constructor(private ngZone: NgZone ) { }

in your case example

 ngOnInit(){
    this.authService.getAuthStatusListener().subscribe(isAuthenticated => {
             this.ngZone.run( () => {
            this.userIsAuthenticated = isAuthenticated
      });

         })
  }

According to this answer, it would cause the whole application to detect changes, whereas your ChangeDetectorRef.detectChanges approach would only detect changes in your component and it's descendants.

shashi kumar
  • 362
  • 2
  • 9
0

Use BehaviorSubject instead of Subject, read more, you are subscribing to the subject after publishing the value, hence the subscribe event in post-list.component.ts is never triggered.

Munzer
  • 2,216
  • 2
  • 18
  • 25