Данные не синхронизируются из component.ts в шаблон - PullRequest
1 голос
/ 20 апреля 2020

У меня есть панель навигации в app.component.html, которую нужно показывать на каждой странице. Мне нужно показать эту панель навигации только зарегистрированным пользователям . В app.component.ts я проверяю, вошел ли пользователь в систему, вызвав authService из метода жизненного цикла ngOnInit (). Но после получения данных isLoggedIn это не относится к app.component.html. Я перехожу к компоненту root из компонента входа в систему после успешного входа в систему, после чего навигация не отображается ИЛИ переменная isAuthenticated не вступает в силу после завершения навигации. But After a reload it shows the navigation. Как решить эту проблему? Спасибо.

app.component. html

 <ul *ngIf="isAuthenticated">
    <li><a class="active" href="/home">Home</a></li>
    <li><a href="/addContact">Add User</a></li>
    <li><a href="/listContact">List Users</a></li>
    <li class="dropdown right">
      <a href="javascript:void(0)" class="dropbtn">{{userDetails.userName}}</a>
      <div class="dropdown-content">
        <a href="javascript:void(0)">Profile</a>
        <a href="javascript:void(0)">Reset Password</a>
        <a href="#" (click)="logout($event)">Logout</a>
      </div>
    </li>
  </ul>

app.component.ts

import { Component, OnInit, OnDestroy } from '@angular/core';
import { AuthService } from './_services/auth.service';
import { Router } from '@angular/router';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  userDetails = {
    userName: '',
    userToken: ''
  }
  isAuthenticated = false;
  constructor(public authService: AuthService, private router: Router) {

  }

  ngOnInit(): void {
    this.getUserDetails()
  }

  ngOnDestroy(): void {

  }

  getUserDetails() {
    this.userDetails.userName = this.authService.getUserName()
    this.userDetails.userToken = this.authService.getToken()
    if (this.userDetails.userToken && this.userDetails.userName) {
      this.isAuthenticated = true;
    }
  }
  logout(e) {
    e.preventDefault()
    if (this.authService.signOut()) {
      this.isAuthenticated = false;
      this.router.navigate(['/login'])
    }
  }
}

login.component.ts

import { Component, OnInit } from '@angular/core';
import { AuthService } from "../../_services/auth.service";
import { Router } from '@angular/router';
@Component({
  selector: 'app-login',
  templateUrl: './login.component.html',
  styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
  login = {
    username: '',
    password: ''
  }

  constructor(private authService: AuthService, private router: Router) { }

  ngOnInit(): void {
  }

  loginContact() {

    const data = {
      username: this.login.username,
      password: this.login.password
    }
    if (data) {
      this.authService.signIn(data).subscribe(
        res => {
          var result = JSON.parse(JSON.stringify(res));
          if (result) {
            localStorage.setItem("token", result.accessToken);
            localStorage.setItem("userName", result.username);
            console.log("logged in successfully")
            this.router.navigate(['/home']);
          } else {
            this.router.navigate(['/']);
          }

        },
        error => {
          console.log(error)
          alert("Signin failed " + JSON.stringify(error))
        }
      )
    }
  }
}

login.component. html

<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>

<h2>Login Form</h2>

<form class="login_form" name="login_form" (ngSubmit)="loginContact()" method="post">
  <div class="imgcontainer">
    <img src="assets/img/img_avatar2.png" alt="Avatar" class="avatar">
  </div>

  <div class="container">
    <label for="uname"><b>Username</b></label>
    <input type="text" placeholder="Enter Username" name="username" required [(ngModel)]="login.username">

    <label for="psw"><b>Password</b></label>
    <input type="password" placeholder="Enter Password" name="password" required [(ngModel)]="login.password"> 

    <button type="submit">Login</button>
    <label>
      <input type="checkbox" checked="checked" name="remember"> Remember me
    </label>
  </div>

  <div class="container" style="background-color:#f1f1f1">
    <button type="button" class="cancelbtn">Cancel</button>
    <span class="psw">Forgot <a href="#">password?</a></span>
  </div>
</form>

</body>
</html>

Ответы [ 3 ]

1 голос
/ 20 апреля 2020

Когда вы входите в систему, app.component уже инициализирован, поэтому, когда вы успешно вошли в систему и перенаправляете на домашнюю страницу, и, как я уже сказал, app.component уже был инициализирован, поэтому он больше не будет запускать ngOnIt. Поэтому для этой проблемы вы должны использовать rxjs Subjects

, или вы можете просто использовать различные компоненты контейнера, например: один компонент контейнера auth и другой для всех ваших компонентов контейнера макета маршрутов. этот шаблон структурирует ваше приложение, а также прост в обслуживании.

@ Crazyrubixfan Вот пример лучшей структуры приложения: https://stackblitz.com/edit/angular-scfdfb?file=src%2Fapp%2Fmodules%2Fcore-layout%2Fcore-layout.component.html

1 голос
/ 20 апреля 2020

Вы можете достичь этого с помощью BehaviorSubject

сначала объявить public isAuthenticated$: BehaviorSubject<boolean>;

, а затем на ngOnInit() установить его состояние по умолчанию this.isAuthenticated$ = new BehaviorSubject(false);

изменить внутри функции getUserDetails() до this.isAuthenticated$.next(true);

, наконец, в вашем шаблоне *ngIf="isAuthenticated$ | async".

0 голосов
/ 20 апреля 2020

Я добавил Observer с SetInterval функцией, которая проверяет аутентификацию или нет, во временном интервале в app.component.ts и использовал эту переменную в шаблоне.

Я не знаю, используется ли этот метод правильно или нет (вероятно, неправильно)

app.component.ts

isAuthenticatedObs = new Observable<boolean>((observer: Observer<boolean>) => {
    setInterval(() => observer.next(this.authService.isAuthenticated())
      , 1000);
  });

app.component. html

<ul *ngIf="isAuthenticatedObs | async">
    <li><a class="active" href="/home">Home</a></li>
    <li><a href="/addContact">Add User</a></li>
    <li><a href="/listContact">List Users</a></li>
    <li class="dropdown right">
      <a href="javascript:void(0)" class="dropbtn">{{userDetails.userName}}</a>
      <div class="dropdown-content">
        <a href="javascript:void(0)">Profile</a>
        <a href="javascript:void(0)">Reset Password</a>
        <a href="#" (click)="logout($event)">Logout</a>
      </div>
    </li>
  </ul>

Пожалуйста, предложите мне лучший метод если у тебя есть. Спасибо.

...